AutoHotkey Community

It is currently May 24th, 2012, 9:12 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: March 29th, 2007, 9:19 am 
Offline

Joined: December 1st, 2006, 9:27 am
Posts: 460
I'm having problems with getting the caption of tabs. This code tries to get tab 1 caption from SciTE, but only crashes SciTE and also Dr Watson.
The first SendMessage works and it gets the number of tabs, so the TabControl is responding. I think the problem is how the structure is set up for the TCM_GETITEM SendMessage. Is there something obvious that I'm missing?
Code:
WinGetActiveTitle, aTitle
SendMessage, 0x1304, 0, 0, SysTabControl321, %aTitle% ahk_class SciTEWindow   ;TCM_GETITEMCount
TabCount := ErrorLevel

;1   -   byte0   -   mask
;2   -   byte4   -   dwState
;3   -   byte8   -   dwStateMask
;4   -   byte12   -   pszText
;5   -   byte16   -   cchTextMax
;6   -   byte20   -   iImage
;7   -   byte24   -   lParam

VarSetCapacity(TabName,128,0)      ;allocate var
VarSetCapacity(TCITEM, 100, 0)      ;allocate var

InsertInteger(1, TCITEM, 0)         ;Mask - TCIF_TEXT
InsertInteger(&TabName, TCITEM, 12)   ;pszText
InsertInteger(128, TCITEM, 16)         ;cchTextMax

SendMessage, 0x1305, 1, &TCITEM, SysTabControl321, %aTitle% ahk_class SciTEWindow  ;TCM_GETITEM

msgbox,%ErrorLevel%`n%TabCount%`n%TabName%

Thanks!

_________________
Image


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 4th, 2007, 7:15 am 
Offline

Joined: December 1st, 2006, 9:27 am
Posts: 460
The problem was that for certain calls that require structures, you have to manage the memory space stuff yourself with OpenProcess and VirtualAllocEx.
The example returns the tab captions from the specified window in a comma-delimited string.

I made it a function for ease-of-use. You specifiy the window Title, ClassNN, TabControl ClassNN, and tab number:
Code:
getTabText(vTitle, vWin, vControl, vTabnum)


Code:
;reference (thanks shimanov): http://www.autohotkey.com/forum/viewtopic.php?t=8840

aTitle := "AutoHotkey Help"
sWin := "HH Parent"
sControl := "SysTabControl321"
   
   SendMessage, 0x1304, 0, 0, %sControl%, %aTitle% ahk_class %sWin%   ;TCM_GETITEMCount
   TabCount := ErrorLevel  ;get number of tabs
   
   tabs=
   loop %TabCount%
   {   sTabnum := A_Index - 1
      vTab := getTabText(aTitle, sWin, sControl, sTabnum)
      tabs .= vTab . ","
   }
   msgbox,%tabs%
   
Return
;vTitle=window title   vWin=window class   vControl=control ClassNN   vTabNum=tab number
getTabText(vTitle, vWin, vControl, vTabnum)
{
   global
   WinGet, pid_target, PID, %vTitle% ahk_class %vWin%

   ;get handle to process inside pid_target   ;0x38=PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE
   remote_process := DllCall("OpenProcess", "uint", 0x38, "int", false, "uint", pid_target)
   IfEqual, remote_process, , Goto errEnd
   
   ;get address allocated for foreign structure   ;0x1000=MEM_COMMIT   ;0x4=PAGE_READWRITE   
   remote_struct := DllCall("VirtualAllocEx", "uint", remote_process, "uint", 0, "uint", 20, "uint", 0x1000, "uint", 0x4)
   IfEqual, remote_struct, , Goto errEnd
   
   ;get address allocated for foreign text buffer   ;0x1000=MEM_COMMIT   ;0x4=PAGE_READWRITE
   remote_buffer := DllCall("VirtualAllocEx", "uint", remote_process, "uint", 0, "uint", 128, "uint", 0x1000, "uint", 0x4)
   IfEqual, remote_buffer, , Goto errEnd
   
   ;create structure for TCM_GETITEM
   VarSetCapacity(TCITEM, 20, 1)               ;allocate var
   InsertInteger(1, TCITEM, 0)                  ;Mask - TCIF_TEXT=1
   InsertInteger(remote_buffer, TCITEM, 12)   ;pszText
   InsertInteger(128, TCITEM, 16)               ;cchTextMax
   
   ;write structure to foreign address
   res := DllCall( "WriteProcessMemory", "uint", remote_process, "uint", remote_struct, "uint", &TCITEM, "uint", 20, "uint", 0 )

   SendMessage, 0x1305, %vTabnum%, remote_struct, %vControl%, ahk_pid %pid_target%  ;TCM_GETITEM
   getres = %ErrorLevel%   ;get the info for the tab

   VarSetCapacity(TabName, 128, 1)   ;get the tab text
   result := DllCall("ReadProcessMemory", "uint", remote_process, "uint", remote_buffer, "uint", &TabName, "uint", 128, "uint", 0)
   
   free()
   Return TabName
   errEnd:
      free()
      Return "Fail"
}

free()
{
   global
   ;free buffer
   result := DllCall( "VirtualFreeEx", "uint", remote_process, "uint", remote_buffer, "uint", 0, "uint", 0x8000 )   ; MEM_RELEASE
   ;free structure
   result := DllCall( "VirtualFreeEx", "uint", remote_process, "uint", remote_struct, "uint", 0, "uint", 0x8000 )   ; MEM_RELEASE   
   ;free willy
   result := DllCall( "CloseHandle", "uint", remote_process )
}

ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
; pSource is a string (buffer) whose memory area contains a raw/binary integer at pOffset.
; The caller should pass true for pSigned to interpret the result as signed vs. unsigned.
; pSize is the size of PSource's integer in bytes (e.g. 4 bytes for a DWORD or Int).
; pSource must be ByRef to avoid corruption during the formal-to-actual copying process
; (since pSource might contain valid data beyond its first binary zero).
{
    Loop %pSize%  ; Build the integer by adding up its bytes.
        result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
    if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
        return result  ; Signed vs. unsigned doesn't matter in these cases.
    ; Otherwise, convert the value (now known to be 32-bit) to its signed counterpart:
    return -(0xFFFFFFFF - result + 1)
}

InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; The caller must ensure that pDest has sufficient capacity.  To preserve any existing contents in pDest,
; only pSize number of bytes starting at pOffset are altered in it.
{
    Loop %pSize%  ; Copy each byte in the integer into the structure as raw binary data.
        DllCall("RtlFillMemory", "UInt", &pDest + pOffset + A_Index-1, "UInt", 1, "UChar", pInteger >> 8*(A_Index-1) & 0xFF)
}

[EDIT]Fixed typo - thanks skrommel!

_________________
Image


Last edited by Micahs on May 24th, 2008, 3:56 pm, edited 2 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject: small error
PostPosted: June 20th, 2007, 7:50 pm 
Offline

Joined: July 30th, 2004, 8:50 pm
Posts: 192
:) There's a small typo in the 8th line in the code above:

Code:
   TabCount := ErrorLevel  -  get number of tabs

should read
Code:
   TabCount := ErrorLevel  ;  get number of tabs

_________________
www.1HourSoftware.com


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 9th, 2007, 9:34 am 
Offline

Joined: February 17th, 2005, 10:06 am
Posts: 280
Location: Hungary, Budapest
I tried the script with Skrommel's correction, but still, it does not return the captions. What can be wrong? (yes AHK help window is open)

_________________
Is there another word for synonym?


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: [VxE], BrandonHotkey, engunneer, Google [Bot], Klark92, NarutoMan, rbrtryn, Tegno, Yahoo [Bot] and 60 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group