AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

[SOLVED] Tab Caption with SysTabControl321 & TCM_GETITEM

 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help
View previous topic :: View next topic  
Author Message
Micahs



Joined: 01 Dec 2006
Posts: 338

PostPosted: Thu Mar 29, 2007 9:19 am    Post subject: [SOLVED] Tab Caption with SysTabControl321 & TCM_GETITEM Reply with quote

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!
_________________
Back to top
View user's profile Send private message
Micahs



Joined: 01 Dec 2006
Posts: 338

PostPosted: Wed Apr 04, 2007 7:15 am    Post subject: Reply with quote

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!
_________________


Last edited by Micahs on Sat May 24, 2008 3:56 pm; edited 2 times in total
Back to top
View user's profile Send private message
skrommel



Joined: 30 Jul 2004
Posts: 177

PostPosted: Wed Jun 20, 2007 7:50 pm    Post subject: small error Reply with quote

Smile 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
Back to top
View user's profile Send private message Visit poster's website
SanskritFritz



Joined: 17 Feb 2005
Posts: 283
Location: Hungary, Budapest

PostPosted: Thu Aug 09, 2007 9:34 am    Post subject: Reply with quote

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?
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Ask for Help All times are GMT
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group