GUI: control types and maximum string lengths Topic is solved

Get help with using AutoHotkey and its commands and hotkeys
User avatar
jeeswg
Posts: 5175
Joined: 19 Dec 2016, 01:58
Location: UK

GUI: control types and maximum string lengths

20 Nov 2017, 20:03

I'm posting here in case anyone has any good links/information on the maximum string lengths for items in the following 8 control types. Thanks.
- ListBox
- ComboBox
- SysListView32
- SysHeader32
- SysTreeView32
- msctls_statusbar32
- ToolbarWindow32
- SysTabControl32
User avatar
jeeswg
Posts: 5175
Joined: 19 Dec 2016, 01:58
Location: UK

Re: GUI: control types and maximum string lengths  Topic is solved

23 Nov 2017, 20:17

One piece of information:
SB_GETTEXT message (Windows)
https://msdn.microsoft.com/en-us/librar ... s.85).aspx
This message returns a maximum of 65,535 characters. If the text string is longer than that, it is truncated.
I did some tests, the main conclusions were:
- You can display 5460 characters fine (5641 if include the null) in all 8 control types, beyond that, some controls display blanks (listviews/listview headers/treeviews continue to display fine).
- You can retrieve 65534 (65535 if include the null) characters from one of the items (parts) in a status bar control. The documentation suggests that this is the maximum number of characters you can get, but that you can set a larger number.
- It is not clear what the actual limits of these control types are.

Code: Select all

;==================================================

;gui controls - items - investigate maximum string lengths
;use q hotkey to show MsgBox
;tested on Windows 7 x64 with AHK v1.1.26.01 x32

;limits:
;ukn	ListBox
;ukn	ComboBox
;ukn	SysListView32
;ukn	SysHeader32
;ukn	SysTreeView32
;65534	msctls_statusbar32 [65534 is get limit, set limit unknown]
;ukn	ToolbarWindow32
;ukn	SysTabControl32

;5460: all display fine
;5461: only LV/LVH/TV display fine
;65534: limit for SB
;522235: SB can be created
;522236: SB error: 'Error: Can't create control.'

;==================================================

#SingleInstance force
;note: for some controls, | is a special character in the AHK Gui command
vText := ""
VarSetCapacity(vText, 1000000*2)
;vText := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
vText .= "z"
Loop, 1000
;Loop, 50000
;Loop, 100000
;Loop, 200000
	vText .= A_Index
;MsgBox, % StrLen(vText)
;vText := SubStr(vText, 1, 100)
;vText := SubStr(vText, 1, 5460)
;vText := SubStr(vText, 1, 5461)
;vText := SubStr(vText, 1, 522235)
;vText := SubStr(vText, 1, 522236)
vMaxChars := StrLen(vText)+1

DetectHiddenWindows, On
Gui, New, +HwndhGui, MyWinTitle
Gui, Add, ListBox, y30 +Multi, % vText ;LBS_EXTENDEDSEL := 0x800 ;LBS_MULTIPLESEL := 0x8
;Gui, Add, ComboBox,, % vText
Gui, Add, ComboBox, +Simple, % vText ;CBS_SIMPLE := 0x1
Gui, Add, ListView, r3, % vText
LV_Add("Select", vText)
Gui, Add, TreeView
vTV1 := TV_Add(vText)
Gui, Add, StatusBar,, % vText
Gui, Add, Tab3, h40, % vText
Gui, Tab ;future controls are not part of any tab control

;ToolbarWindow32
;Gui, Add, Custom, ClassToolbarWindow32
;Gui, Add, Custom, ClassToolbarWindow32 0x100 ;TBSTYLE_TOOLTIPS := 0x100
Gui, Add, Custom, ClassToolbarWindow32 0x1000 ;TBSTYLE_LIST := 0x1000 ;text to side of buttons
;Gui, Add, Custom, ClassToolbarWindow32 0x1100
ControlGet, hTB, Hwnd,, ToolbarWindow321, % "ahk_id " hGUI
;SendMessage, 0x43C, 0, 0,, % "ahk_id " hTB ;TB_SETMAXTEXTROWS ;text omitted from buttons
;note: if more than one button has the same idCommand, then only the last button with that idCommand will have a ToolTip
vCount := 5, vSize := A_PtrSize=8?32:20
VarSetCapacity(TBBUTTON, vCount*vSize, 0)
Loop, % vCount
{
	vText%A_Index% := "TB " A_Index
	if (A_Index = 1)
		vText1 := vText
	vOffset := (A_Index-1)*vSize
	;TBSTATE_ENABLED := 4
	NumPut(A_Index-1, TBBUTTON, vOffset, "Int") ;iBitmap
	NumPut(A_Index-1, TBBUTTON, vOffset+4, "Int") ;idCommand
	NumPut(0x4, TBBUTTON, vOffset+8, "UChar") ;fsState
	NumPut(&vText%A_Index%, TBBUTTON, vOffset+(A_PtrSize=8?24:16), "Ptr") ;iString
}
hIL := IL_Create(5, 2, 0)
IL_Add(hIL, A_AhkPath, -159) ;green H
IL_Add(hIL, A_AhkPath, -206) ;green S
IL_Add(hIL, A_AhkPath, -207) ;red H
IL_Add(hIL, A_AhkPath, -208) ;red S
IL_Add(hIL, A_AhkPath, -160) ;file icon
SendMessage, 0x430, 0, % hIL,, % "ahk_id " hTB ;TB_SETIMAGELIST
;TB_ADDBUTTONSW := 0x444 ;TB_ADDBUTTONSA := 0x414
vMsg := A_IsUnicode?0x444:0x414
SendMessage, % vMsg, % vCount, % &TBBUTTON,, % "ahk_id " hTB ;TB_ADDBUTTONSW / TB_ADDBUTTONSA

Gui, Show
SendMessage, 0x421,,,, % "ahk_id " hTB ;TB_AUTOSIZE
return

;==================================================

q::
WinGet, hWnd, ID, A
if !(hWnd = hGui)
	return
oArray := {}
vPIs64 := (A_PtrSize=8)
vPtrType := vPIs64?"Int64":"Int"

;1 ListBox
vIndex := 1
ControlGet, hCtl, Hwnd,, ListBox1, A
vChars := SendMessage(0x18A, vIndex-1, 0,, "ahk_id " hCtl) ;LB_GETTEXTLEN := 0x18A
if !(vChars = 0xFFFFFFFF) ;LB_ERR := -1
{
	vSize := (vChars+1) << !!A_IsUnicode
	VarSetCapacity(vTemp, vSize, 0)
	SendMessage(0x189, vIndex-1, &vTemp,, "ahk_id " hCtl) ;LB_GETTEXT := 0x189
	VarSetCapacity(vTemp, -1)
}
oArray.Push(vTemp)

;2 ComboBox
vIndex := 1
ControlGet, hCtl, Hwnd,, ComboBox1, A
vChars := SendMessage(0x149, vIndex-1, 0,, "ahk_id " hCtl) ;CB_GETLBTEXTLEN := 0x149
if !(vChars = 0xFFFFFFFF) ;CB_ERR := -1
{
	vSize := (vChars+1) << !!A_IsUnicode
	VarSetCapacity(vTemp, vSize, 0)
	SendMessage(0x148, vIndex-1, &vTemp,, "ahk_id " hCtl) ;CB_GETLBTEXT := 0x148
	VarSetCapacity(vTemp, -1)
}
oArray.Push(vTemp)

;3 SysListView32
vIndex := 1, vCol := 1
ControlGet, hCtl, Hwnd,, SysListView321, A
vSize1 := vPIs64?40:28
vSize2 := vMaxChars << !!A_IsUnicode
VarSetCapacity(LVITEM, vSize1, 0)
VarSetCapacity(vTemp, vSize2, 0)
NumPut(0x1, &LVITEM, 0, "UInt") ;mask ;LVIF_TEXT := 0x1
NumPut(&vTemp, &LVITEM, vPIs64?24:20, vPtrType) ;pszText
NumPut(vMaxChars, &LVITEM, vPIs64?32:24, "Int") ;cchTextMax
NumPut(vIndex-1, &LVITEM, 4, "Int") ;iItem
NumPut(vCol-1, &LVITEM, 8, "Int") ;iSubItem
SendMessage(A_IsUnicode?0x1073:0x102D, vIndex-1, &LVITEM,, "ahk_id " hCtl) ;LVM_GETITEMTEXTW := 0x1073 ;LVM_GETITEMTEXTA := 0x102D
VarSetCapacity(vTemp, -1)
oArray.Push(vTemp)

;4 SysHeader32
vIndex := 1
ControlGet, hCtl, Hwnd,, SysHeader321, A
vSize1 := vPIs64?72:48
vSize2 := vMaxChars << !!A_IsUnicode
VarSetCapacity(HDITEM, vSize1, 0)
VarSetCapacity(vTemp, vSize2, 0)
NumPut(0x2, &HDITEM, 0, "UInt") ;mask ;HDI_TEXT := 0x2
NumPut(&vTemp, &HDITEM, 8, vPtrType) ;pszText
NumPut(vMaxChars, &HDITEM, vPIs64?24:16, "Int") ;cchTextMax
SendMessage(A_IsUnicode?0x120B:0x1203, vIndex-1, &HDITEM,, "ahk_id " hCtl) ;HDM_GETITEMW := 0x120B ;HDM_GETITEMA := 0x1203
VarSetCapacity(vTemp, -1)
oArray.Push(vTemp)

;5 SysTreeView32
;will get the root item
ControlGet, hCtl, Hwnd,, SysTreeView321, A
vSize1 := vPIs64?56:40
vSize2 := vMaxChars << !!A_IsUnicode
VarSetCapacity(TVITEM, vSize1, 0)
VarSetCapacity(vTemp, vSize2, 0)
;TVGN_ROOT := 0x0
hItem := SendMessage(0x110A, 0x0, 0,, "ahk_id " hCtl) ;TVM_GETNEXTITEM := 0x110A
NumPut(0x1, &TVITEM, 0, "UInt") ;mask ;TVIF_TEXT := 0x1
NumPut(&vTemp, &TVITEM, vPIs64?24:16, vPtrType) ;pszText
NumPut(vMaxChars, &TVITEM, vPIs64?32:20, "UInt") ;cchTextMax
NumPut(hItem, &TVITEM, vPIs64?8:4, vPtrType) ;hItem
SendMessage(A_IsUnicode?0x113E:0x110C, 0, &TVITEM,, "ahk_id " hCtl) ;TVM_GETITEMW := 0x113E ;TVM_GETITEMA := 0x110C
VarSetCapacity(vTemp, -1)
oArray.Push(vTemp)

;6 msctls_statusbar32
vIndex := 1
ControlGet, hCtl, Hwnd,, msctls_statusbar321, A
vSize := vMaxChars << !!A_IsUnicode
VarSetCapacity(vTemp, vSize, 0)
SendMessage(A_IsUnicode?0x40D:0x402, vIndex-1, &vTemp,, "ahk_id " hCtl) ;SB_GETTEXTW := 0x40D ;SB_GETTEXTA := 0x402
VarSetCapacity(vTemp, -1)
oArray.Push(vTemp)

;7 ToolbarWindow32
vIDCmd := 0
ControlGet, hCtl, Hwnd,, ToolbarWindow321, A
vChars := SendMessage(A_IsUnicode?0x44B:0x42D, vIDCmd, 0,, "ahk_id " hCtl) ;TB_GETBUTTONTEXTW := 0x44B ;TB_GETBUTTONTEXTA := 0x42D
if !(vChars = 0xFFFFFFFF)
{
	vSize := (vChars+1) << !!A_IsUnicode
	VarSetCapacity(vTemp, vSize, 0)
	SendMessage(A_IsUnicode?0x44B:0x42D, vIDCmd, &vTemp,, "ahk_id " hCtl) ;TB_GETBUTTONTEXTW := 0x44B ;TB_GETBUTTONTEXTA := 0x42D
	VarSetCapacity(vTemp, -1)
}
oArray.Push(vTemp)

;8 SysTabControl32
vIndex := 1
ControlGet, hCtl, Hwnd,, SysTabControl321, A
vSize1 := vPIs64?40:28
vSize2 := vMaxChars << !!A_IsUnicode
VarSetCapacity(TCITEM, vSize1, 0)
VarSetCapacity(vTemp, vSize2, 0)
NumPut(0x1, &TCITEM, 0, "UInt") ;mask ;TCIF_TEXT := 0x1
NumPut(&vTemp, &TCITEM, vPIs64?16:12, "Ptr") ;pszText
NumPut(vMaxChars, &TCITEM, vPIs64?24:16, "Int") ;cchTextMax
SendMessage(A_IsUnicode?0x133C:0x1305, vIndex-1, &TCITEM,, "ahk_id " hCtl) ;TCM_GETITEMW := 0x133C ;TCM_GETITEMA := 0x1305
VarSetCapacity(vTemp, -1)
oArray.Push(vTemp)

vList := "ListBox,ComboBox,SysListView32,SysHeader32,SysTreeView32,msctls_statusbar32,ToolbarWindow32,SysTabControl32"
vOutput := ""
Loop, Parse, vList, % ","
	vOutput .= (oArray[A_Index] = vText) "`t" StrLen(oArray[A_Index]) "`t" A_LoopField "`r`n"
Clipboard := vOutput
MsgBox, % vOutput
return

;==================================================

GuiClose:
ExitApp
return

;==================================================

SendMessage(Msg, wParam:="", lParam:="", Control:="", WinTitle:="", WinText:="", ExcludeTitle:="", ExcludeText:="", Timeout:="")
{
    local MsgReply
    SendMessage %Msg%, %wParam%, %lParam%, %Control%, %WinTitle%, %WinText%, %ExcludeTitle%, %ExcludeText%, %Timeout%
    MsgReply := (ErrorLevel = "FAIL") ? "" : ErrorLevel
    ErrorLevel := (ErrorLevel = "FAIL")
    return MsgReply
}

;==================================================

Return to “Ask For Help”

Who is online

Users browsing this forum: eqv, MaEstRo, TAC109, Tigerlily, vergas78 and 24 guests