The structure doesn't contain a 'size' member. So it's safe to allocate the maximum structure size in any case. It's 88 bytes on Vista+ 64-bit. (But you'll 'waste' some bytes on XP and 32-bit OSes.)CommCtrl.h wrote:Code: Select all
typedef struct tagLVITEMW { UINT mask; int iItem; int iSubItem; UINT state; UINT stateMask; LPWSTR pszText; int cchTextMax; int iImage; LPARAM lParam; int iIndent; #if (NTDDI_VERSION >= NTDDI_WINXP) int iGroupId; UINT cColumns; // tile view columns PUINT puColumns; #endif #if (NTDDI_VERSION >= NTDDI_VISTA) int* piColFmt; int iGroup; // readonly. only valid for owner data. #endif } LVITEMW, *LPLVITEMW;
[ListView] How to force "LV_GetText()" function to get text longer than 8191 characters? Topic is solved
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
what just me said.
The problem with many development environments (mine included) is that you have only one PC to test on. If you are a responsible developer, you write your stuff so that it will work on other versions of AutoHotkey (ANSI, Unicode, x64) and other versions of Windows but testing it on all possible environments is tough, if not impossible.
The problem with many development environments (mine included) is that you have only one PC to test on. If you are a responsible developer, you write your stuff so that it will work on other versions of AutoHotkey (ANSI, Unicode, x64) and other versions of Windows but testing it on all possible environments is tough, if not impossible.
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
And what about getting the max "byte" integer number from a listview "RowX/ColX" (through DllCall, of course) and store it in "MaxbyteFound" variable, then use "VarSetCapacity(var, MaxbyteFound, 0)", then get the string from listview "RowX/ColX" and store it in "Var" variable?
I think the above is exactly what "ControlGetText" does:
https://autohotkey.com/docs/commands/Co ... tm#Remarks
https://docs.microsoft.com/en-us/window ... eving-text
f the retrieved text appears to be truncated (incomplete), try using VarSetCapacity(OutputVar, 55) prior to ControlGetText [replace 55 with a size that is considerably longer than the truncated text]. This is necessary because some applications do not respond properly to the WM_GETTEXTLENGTH message, which causes AutoHotkey to make the output variable too small to fit all the text.
Last edited by User on 25 Oct 2018, 19:21, edited 1 time in total.
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
I apologize. It is very unclear to me what you are asking here. I have some idea but I'm not sure. If you could restate the question/requirement, I'll try to help if I can.User wrote: ↑25 Oct 2018, 11:28And what about getting the max "byte" integer number from a listview "RowX/ColX" (through DllCall, of course) and store it in "MaxbyteFound" variable, then use "VarSetCapacity(var, MaxbyteFound, 0)", then get the string from listview "RowX/ColX" and store it in "Var" variable?
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
- "LVM_GetItemLength(LvCtrl, 3, 2)" and store in "MaxbyteFound" var
- then, "VarSetCapacity(Text, MaxbyteFound, 0)"
- "LVM_GetItemText(LvCtrl, 3, 2)" and store in "Text" var
Sorry, but I can't be more clear than that! (just the same "ControlGetText" does!)
https://autohotkey.com/docs/commands/Co ... tm#Remarks
https://docs.microsoft.com/en-us/window ... eving-text
Code: Select all
gui, add, edit, w400 h300 +HScroll gGetLength +HwndEditCtrlId, hhhhh
gui, add, text, w100 vTextCtrl +border,
gui, show
GetLength: ;______________ Get text Length _______________
SendMessage, 0xE,0,0,, % "ahk_id" EditCtrlId ;"0xE" = WM_GETTEXTLENGTH
TextLength := ErrorLevel
guicontrol, , TextCtrl, % TextLength
return
guiclose: ;______________ gui close ________________
exitapp
Code: Select all
if (((GV:=DllCall("GetVersion"))&0xFF . "." . GV>>8&0xFF)>=6.0) ;Vista+ (Vista and later versions)
sizeofLVITEM:=(A_PtrSize=8) ? 72:60
else
sizeofLVITEM:=(A_PtrSize=8) ? 64:52 ;WinXp- (winxp and earlier versions?)
Last edited by User on 25 Oct 2018, 19:45, edited 1 time in total.
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
- Do you want a listview control with every Unicode character? Am I right?
- Is it possible to do word wrap with a listview control, to see each character?
- Btw I worked on a list of common structs with parameter info, here:
list of structs with parameters (sizes and types) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 74&t=30497
- Is it possible to do word wrap with a listview control, to see each character?
Code: Select all
;[JEE_LVGetText/JEE_LVSetText functions]
;GUIs via DllCall: get/set internal/external control text - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
q:: ;create listview with every Unicode character
Gui, New, +HwndhGui, MyWinTitle
Gui, Add, ListView, +HwndhLV r3, LVH 1|LVH 2|LVH 3
Loop, 3
if (A_Index = 1)
LV_Add("Select", "LV A" A_Index, "LV B" A_Index, "LV C" A_Index)
else
LV_Add("", "LV A" A_Index, "LV B" A_Index, "LV C" A_Index)
Gui, Show, w300 h300
vText := ""
;VarSetCapacity(vText, 10000000*2)
VarSetCapacity(vText, 2162687*2)
Loop, 1114111
vText .= Chr(A_Index)
JEE_LVSetText(hLV, vText, 1, 1,,, "m10000000")
Gui, Show, w300 h300
vText := JEE_LVGetText(hLV, 1, 1,,, "m10000000")
MsgBox, % StrLen(vText) "`r`n" (StrLen(vText)/1114111)
return
list of structs with parameters (sizes and types) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 74&t=30497
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
@jeeswg, what I want is already accomplished, get all the text from a listview item!
The 1114111 unicode characters were used just for testings!
This is nothing to do with "listview control to contain every Unicode characters"!
_________________
Now we are just trying to find the best way to define "Maxbyte" from @Jballi function!
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
I'm sorry, there is no "GetTextLength" message or equivalent for the ListView item text. The actual length can discovered with a try and fail loop. PM and I will show you an example.User wrote: ↑25 Oct 2018, 19:06- "LVM_GetItemLength(LvCtrl, 3, 2)" and store in "MaxbyteFound" var
- then, "VarSetCapacity(Text, MaxbyteFound, 0)"
- "LVM_GetItemText(LvCtrl, 3, 2)" and store in "Text" var
Sorry, but I can't be more clear than that! (just the same "ControlGetText" does!)
https://autohotkey.com/docs/commands/Co ... tm#Remarks
https://docs.microsoft.com/en-us/window ... eving-textby the way, is the code below correct?Code: Select all
gui, add, edit, w400 h300 +HScroll gGetLength +HwndEditCtrlId, hhhhh gui, add, text, w100 vTextCtrl +border, gui, show GetLength: ;______________ Get text Length _______________ SendMessage, 0xE,0,0,, % "ahk_id" EditCtrlId ;"0xE" = WM_GETTEXTLENGTH TextLength := ErrorLevel guicontrol, , TextCtrl, % TextLength return guiclose: ;______________ gui close ________________ exitapp
Code: Select all
if (((GV:=DllCall("GetVersion"))&0xFF . "." . GV>>8&0xFF)>=6.0) ;Vista+ (Vista and later versions) sizeofLVITEM:=(A_PtrSize=8) ? 72:60 else sizeofLVITEM:=(A_PtrSize=8) ? 64:52 ;WinXp- (winxp and earlier versions?)
Also, per just me, there is no cbSize member in the structure, so it's safe to always set the size of the LVITEM structure to the maximum size which is 88. Ex: VarSetCapacity(LVITEM,88,0)
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
well, if there is no way to get the text length of a listview item, that's ok! (I will set default maxchar to autohotkey default #maxmem, which is 64Megabyte!)
@jballi thanks for your help and for your function! (You should create a new thread just for this function of yours, and keep it updated from there!)
[Last Thing]:
(Oops, my bad! Got it! I should use sizeofLVITEM:=88 inside the function instead the code below! Thanks! - You really need to create a new thread just for this function and keep it updated!)
I really need you to confirm if the below code is correct because I want to paste it inside your function, and I don't want to spread wrong infos!
Code: Select all
if (((GV:=DllCall("GetVersion"))&0xFF . "." . GV>>8&0xFF)>=6.0) ;Vista+ (Vista and later versions)
sizeofLVITEM:=(A_PtrSize=8) ? 72:60
else
sizeofLVITEM:=(A_PtrSize=8) ? 64:52 ;WinXp- (winxp and earlier versions?)
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
@jballi, just to make things clear here:
sizeofLVITEM := 88, is supported by xp+ x32 and vista+ x64 (so xp x64 is not supported, correct?)
in the other hand:
the code below is supported by xp-/+ x32/x64 (correct?)
Code: Select all
if (((GV:=DllCall("GetVersion"))&0xFF . "." . GV>>8&0xFF)>=6.0) ;Vista+ x32/x64 (Vista and later versions?)
sizeofLVITEM:=(A_PtrSize=8) ? 72:60
else
sizeofLVITEM:=(A_PtrSize=8) ? 64:52 ;WinXp- x32/x64 (winxp and earlier versions?)
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
To be clear again. 88 is the magic number and should work for all versions of AutoHotkey and all versions of Windows.
For example:
VarSetCapacity(LVITEM,88,0)
If you want to save a few bytes when running a 32-bit version of AutoHotkey, you can use the following:
VarSetCapacity(LVITEM,A_PtrSize=8 ? 88:60,0)
For example:
VarSetCapacity(LVITEM,88,0)
If you want to save a few bytes when running a 32-bit version of AutoHotkey, you can use the following:
VarSetCapacity(LVITEM,A_PtrSize=8 ? 88:60,0)
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
@jballi, I modified this last version that you posted in this thread to my like\needs! (If there is something that I should\must change, please let me know!)
- LVM_GetSizeOfLVITEM() function is not necessary anymore (I removed it)
- The function now uses 1-based indexes
- l_Text variable does not consume all the bytes at function call (it consumes all the bytes only if necessary\needed)
- Default Max_bytes set to 64000100 bytes (64 Megabytes, the same default used by AHK for variables)
Code: Select all
;The default "Max_bytes" the function can Get = 64 Megabytes (Can be changed, Example below)!
;LVM_GetItemText(LVCtrlId, 3, 2, 256000100), the "Max_bytes" = 256 Megabytes
gui, wait: add, text, w300 h200, Please Wait!!!
gui, wait: show
gui, add, listview, w600 h300 Grid +HwndLVCtrlId, Id|A|B|C
gui, add, button, vGetFocused gGet, Get - Focused row / col2 - data
gui, add, button, x+5 gGet, Get - row3 / col2 - data
loop, 3
LV_ModifyCol(a_index, 100)
loop, 3
LV_ADD(,a_index, "A" a_index " ", "B" a_index " ", "C" a_index " ")
loop, 1114111
text .= chr(a_index)
text .= "`r`nEnd"
LV_Modify(3, "col2", text)
gui, wait: destroy
gui, show
return
Get: ;_____________ Get _________________
gui, wait: add, text, w300 h200, Please Wait!!!
gui, wait: show
gui, Get:Default
gui, destroy
gui, add, edit, w400 h300 +HScroll +HwndEditCtrlId,
gui, add, text, w400 vStrLen +border,
gui, 1:Default
if (a_guicontrol = "GetFocused")
StringFound := LVM_GetItemText(LVCtrlId, LV_GetNext(0, "F"), 2) ;Focused row, 2=col
else
StringFound := LVM_GetItemText(LVCtrlId, 3, 2) ;3=row, 2=col
gui, Get:Default
if (text == StringFound) ;"==" is case sensitive
Result := "Matched"
else
Result := "Un-Matched"
;guicontrol, , % EditCtrlId, % StringFound
ControlSetText , , % StringFound, % "ahk_id" EditCtrlId
guicontrol, , StrLen, % "String Length = " StrLen(StringFound) " / 'Text' and 'StringFound' vars " Result "!"
gui, wait: destroy
gui, show
return
guiclose: ;_______________ gui close _________________
WaitGuiClose:
exitapp
LVM_GetItemText(hLV, p_Item, p_Column := 1, p_Max_bytes := 64000100) ;_______________ LVM_GetItemText(Function) - v1.1 "User" - by "jballi" Autohotkey forum user ____________________
{
;by "jballi" Autohotkey forum user:
;(AHK v1.1+ 64-bit now supported): https://autohotkey.com/boards/viewtopic.php?p=245633#p245633
;p_Max_bytes := 64000100 (64 Megabytes is the default value, the same used by AHK)
;https://autohotkey.com/docs/commands/_MaxMem.htm#Remarks
Static Dummy53843366
Static LVIF_TEXT:=0x1 ;-- LVITEM flags
Static LVM_GETITEMTEXTA:=0x102D ;-- LVM_FIRST + 45 (Message)
Static LVM_GETITEMTEXTW:=0x1073 ;-- LVM_FIRST + 115 (Message)
Static sizeofLVITEM := A_PtrSize = 8 ? 88 : 60
;"88" should work with all versions of AutoHotkey (32/64bit) and all versions of Windows (xp+ 32/64bit)
;"60" will be used in order to save few bytes when running 32-bit versions of AutoHotkey
p_Item--, p_Column-- ;turns function into 1-based index (row\col 1 is 1, row\col 2 is 2, row\col 3 is 3, and so on ...!)
;-- Create and populate LVITEM structure
VarSetCapacity(l_Text, p_Max_bytes)
;removed "0" from the third\last parameter (prevents "l_Text" variable to consume, for example, all the 64MB as soon as the function is called!)
;by removing "0" from the third\last parameter, "l_Text" variable will consume the 64MB only if necessary\needed!
;msgbox, wait - Open "Task manager" and check "Autohotkey.exe" ram usage!
VarSetCapacity(LVITEM,sizeofLVITEM,0)
NumPut(LVIF_TEXT, LVITEM,0,"UInt") ;-- mask
NumPut(p_Item, LVITEM,4,"Int") ;-- iItem
NumPut(p_Column, LVITEM,8,"Int") ;-- iSubItem
NumPut(&l_Text, LVITEM,(A_PtrSize=8) ? 24:20,"Ptr")
;-- pszText
NumPut(p_Max_bytes,LVITEM,(A_PtrSize=8) ? 32:24,"Int")
;-- cchTextMax. Note: This contains the number of TCHARs in the buffer
; pointed to by pszText.
;-- Collect text
SendMessage
,% A_IsUnicode ? LVM_GETITEMTEXTW:LVM_GETITEMTEXTA
,p_Item
,&LVITEM
,,ahk_id %hLV%
VarSetCapacity(l_Text,-1)
Return l_Text
}
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
The function looks good but the 64MB limit is wasteful and could cause an "out of memory" script error on smaller systems. Removing 0 from the third\last parameter of the VarSetCapacity function is correct for the LVM_GETITEMTEXT message but it does not stop the l_Text variable from consuming the 64MB. It only stops AutoHotkey from initializing the space with 0 (null) values.
Here is an alternative version of the function. It uses a fail loop to ensure that all text is collected from the specified ListView row/column. In 99.9+% of the requests, only one loop iteration is required so there should be no performance degradation.
Disclaimer: I've tested the function but it hasn't gone through any system-level testing or performance testing.
I hope this is helpful.
20181122_1313 Edit: Function updated to include VarSetCapacity(l_Text,-1). I originally took this statement out because it wasn't needed in my initial tests but other tests revealed that it is required.
Here is an alternative version of the function. It uses a fail loop to ensure that all text is collected from the specified ListView row/column. In 99.9+% of the requests, only one loop iteration is required so there should be no performance degradation.
Disclaimer: I've tested the function but it hasn't gone through any system-level testing or performance testing.
Code: Select all
;------------------------------
;
; Function: LVM_GetText
;
; Description:
;
; Gets the text of a ListView row/column.
;
; Parameters:
;
; p_Row - 1-based row index.
;
; p_Column - 1-based column index.
;
; p_MaxTCHARs - See the *Maximum Characters* section for more information.
;
; Returns:
;
; Text from the specified row/column.
;
; Maximum Characters:
;
; The p_MaxTCHARs parameter contains the initial maximum number of characters
; of text (including a trailing null character) to retrieve. If the ListView
; row/subitem contains more text than the limit defined by p_MaxTCHARs, the
; capacity is doubled and the function will try again. This "double the
; capacity and try again" process will continue until all the text for the
; ListView row/subitem is collected.
;
; The current default for p_MaxTCHARs parameter is 16384 which is double the
; current AutoHotkey limit for this request. This default should allow the
; function to collect all of the text for most ListView rows/subitems on the
; first try. The developer can set this parameter to any value but any large
; deviation is not recommended.
;
; If the p_MaxTCHARs parameter is set to a very large value or if the ListView
; row/subitem contains a very large amount of text, is it possible (although
; unlikely) for the function to generate a "Out of Memory" script error.
; Thorough testing is recommended.
;
; Remarks:
;
; ErrorLevel is set to the number of characters returned.
;
;-------------------------------------------------------------------------------
LVM_GetText(hLV,p_Row,p_Column:=1,p_MaxTCHARs:=16384)
{
Static Dummy45758032
;-- LVITEM flags
,LVIF_TEXT:=0x1
;-- Messages
,LVM_GETITEMTEXTA:=0x102D ;-- LVM_FIRST + 45
,LVM_GETITEMTEXTW:=0x1073 ;-- LVM_FIRST + 115
;-- Create and populate LVITEM structure
VarSetCapacity(LVITEM,A_PtrSize=8 ? 88:60,0)
NumPut(LVIF_TEXT,LVITEM,0,"UInt") ;-- mask
NumPut(p_Row-1, LVITEM,4,"Int") ;-- iItem
NumPut(p_Column-1,LVITEM,8,"Int") ;-- iSubItem
;-- Get text
; Note: A fixed loop limit was added during development/testing to remove
; the possibility of an infinite loop. It's no longer needed but it
; remains as a fail-safe.
Loop 9
{
VarSetCapacity(l_Text,A_IsUnicode ? p_MaxTCHARs*2:p_MaxTCHARs)
NumPut(&l_Text,LVITEM,A_PtrSize=8 ? 24:20,"Ptr")
;-- pszText
NumPut(p_MaxTCHARs,LVITEM,A_PtrSize=8 ? 32:24,"Int")
;-- cchTextMax. Note: This contains the number of TCHARs in the
; buffer pointed to by pszText.
;-- Get text
SendMessage
,% A_IsUnicode ? LVM_GETITEMTEXTW:LVM_GETITEMTEXTA
,p_Row-1
,&LVITEM
,,ahk_id %hLV%
;-- Does the number of characters retrieved equal the maximum possible
; characters minus the trailing null char? If not, we're done.
if (ErrorLevel<>p_MaxTCHARs-1)
Break
;-- Double the capacity and try again
p_MaxTCHARs*=2
}
VarSetCapacity(l_Text,-1)
Return l_Text
}
20181122_1313 Edit: Function updated to include VarSetCapacity(l_Text,-1). I originally took this statement out because it wasn't needed in my initial tests but other tests revealed that it is required.
Last edited by jballi on 22 Nov 2018, 14:16, edited 1 time in total.
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
That's right, it may cause an "out of memory" script error on smaller systems.
I tested it out in my system! I have 4gb of ram, while testing, 2.5gb was being used by my system and 1.5gb was free\available! I set Max_byte = 2100100100 = 2gb and as soon as the function was called, "out of memory" script error showed up! (even though "l_Text" variable consumed no byte at all!)
So it means that, if you don't have 64MB of ram free/available in your system, "out of memory" script error shows up as soon as the function is called!
I think the above is AutoHotKey fault though, and should be fixed! (the "out of memory" script error should show up only if the "AutoHotKey.exe" process itself, while consuming bytes, finds out that there is no more "bytes" to consume from ram or, for example, fixes a limit, while consuming bytes, if free ram available = 100 MB => "out of memory" script error shows up! )
The fail loop method seems a great solution, will test it out and let you know later what I think about it!
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
Bug fix in the LVM_GetText function. See my previous post for the details.
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
Tested the fail loop method and it works!
I noticed one issue, if VarSetCapacity(l_Text,A_IsUnicode ? p_MaxTCHARs*2:p_MaxTCHARs) is changed to VarSetCapacity(l_Text,p_MaxTCHARs) the below problem occurs:
Do you know why? Any workaround? (I want to use "max_byte" parameter instead "max_character" )
Working test code:
Code: Select all
gui, wait: add, text, w300 h200, Please Wait!!!
gui, wait: show
gui, add, listview, w600 h300 Grid +HwndLVCtrlId, Id|A|B|C
gui, add, button, vGetFocused gGet, Get - Focused row / col2 - data
gui, add, button, x+5 gGet, Get - row3 / col2 - data
loop, 3
LV_ModifyCol(a_index, 100)
loop, 3
LV_ADD(,a_index, "A" a_index " ", "B" a_index " ", "C" a_index " ")
loop, 1114111
text .= chr(a_index)
text .= "`r`nEnd"
LV_Modify(3, "col2", text)
gui, wait: destroy
gui, show
return
Get: ;_____________ Get _________________
gui, wait: add, text, w300 h200, Please Wait!!!
gui, wait: show
gui, Get:Default
gui, destroy
gui, add, edit, w400 h300 +HScroll +HwndEditCtrlId,
gui, add, text, w400 vStrLen +border,
gui, 1:Default
if (a_guicontrol = "GetFocused")
StringFound := LVM_GetText(LVCtrlId, LV_GetNext(0, "F"), 2) ;Focused row, 2=col
else
StringFound := LVM_GetText(LVCtrlId, 3, 2) ;3=row, 2=col
gui, Get:Default
if (text == StringFound) ;"==" is case sensitive
Result := "Matched"
else
Result := "Un-Matched"
;guicontrol, , % EditCtrlId, % StringFound
ControlSetText , , % StringFound, % "ahk_id" EditCtrlId
guicontrol, , StrLen, % "String Length = " StrLen(StringFound) " / 'Text' and 'StringFound' vars " Result "!"
gui, wait: destroy
gui, show
return
guiclose: ;_______________ gui close _________________
WaitGuiClose:
exitapp
;------------------------------
;
; Function: LVM_GetText
;
; Description:
;
; Gets the text of a ListView row/column.
;
; Parameters:
;
; p_Row - 1-based row index.
;
; p_Column - 1-based column index.
;
; p_MaxTCHARs - See the *Maximum Characters* section for more information.
;
; Returns:
;
; Text from the specified row/column.
;
; Maximum Characters:
;
; The p_MaxTCHARs parameter contains the initial maximum number of characters
; of text (including a trailing null character) to retrieve. If the ListView
; row/subitem contains more text than the limit defined by p_MaxTCHARs, the
; capacity is doubled and the function will try again. This "double the
; capacity and try again" process will continue until all the text for the
; ListView row/subitem is collected.
;
; The current default for p_MaxTCHARs parameter is 16384 which is double the
; current AutoHotkey limit for this request. This default should allow the
; function to collect all of the text for most ListView rows/subitems on the
; first try. The developer can set this parameter to any value but any large
; deviation is not recommended.
;
; If the p_MaxTCHARs parameter is set to a very large value or if the ListView
; row/subitem contains a very large amount of text, is it possible (although
; unlikely) for the function to generate a "Out of Memory" script error.
; Thorough testing is recommended.
;
; Remarks:
;
; ErrorLevel is set to the number of characters returned.
;
;-------------------------------------------------------------------------------
LVM_GetText(hLV,p_Row,p_Column:=1,p_MaxTCHARs:=16384)
{
Static Dummy45758032
;-- LVITEM flags
,LVIF_TEXT:=0x1
;-- Messages
,LVM_GETITEMTEXTA:=0x102D ;-- LVM_FIRST + 45
,LVM_GETITEMTEXTW:=0x1073 ;-- LVM_FIRST + 115
;-- Create and populate LVITEM structure
VarSetCapacity(LVITEM,A_PtrSize=8 ? 88:60,0)
NumPut(LVIF_TEXT,LVITEM,0,"UInt") ;-- mask
NumPut(p_Row-1, LVITEM,4,"Int") ;-- iItem
NumPut(p_Column-1,LVITEM,8,"Int") ;-- iSubItem
;-- Get text
; Note: A fixed loop limit was added during development/testing to remove
; the possibility of an infinite loop. It's no longer needed but it
; remains as a fail-safe.
Loop 9
{
VarSetCapacity(l_Text,A_IsUnicode ? p_MaxTCHARs*2:p_MaxTCHARs)
NumPut(&l_Text,LVITEM,A_PtrSize=8 ? 24:20,"Ptr")
;-- pszText
NumPut(p_MaxTCHARs,LVITEM,A_PtrSize=8 ? 32:24,"Int")
;-- cchTextMax. Note: This contains the number of TCHARs in the
; buffer pointed to by pszText.
;-- Get text
SendMessage
,% A_IsUnicode ? LVM_GETITEMTEXTW:LVM_GETITEMTEXTA
,p_Row-1
,&LVITEM
,,ahk_id %hLV%
;-- Does the number of characters retrieved equal the maximum possible
; characters minus the trailing null char? If not, we're done.
if (ErrorLevel<>p_MaxTCHARs-1)
Break
;-- Double the capacity and try again
p_MaxTCHARs*=2
}
VarSetCapacity(l_Text,-1)
Return l_Text
}
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
The LVM_GETITEMTEXT message uses the LVITEM structure to determine what's what. The pszText member contain the address to the space where the retrieved text is stored. The cchTextMax member must be set to the number of characters have been allocated. The amount of space necessary depends on whether you are using ANSI or Unicode. If using ANSI, every character uses 1 byte of space. If using Unicode (UTF-16), every character uses 2 bytes of space.
So... when you changed VarSetCapacity(l_Text,A_IsUnicode ? p_MaxTCHARs*2:p_MaxTCHARs) to VarSetCapacity(l_Text,p_MaxTCHARs), you told the LVM_GETITEMTEXT message that you had allocated twice as much space than you actually allocated. In other words, you allocated half as much space as you needed so when the message tried to access memory that wasn't there, you get an exception and AutoHotkey crashes.
So... when you changed VarSetCapacity(l_Text,A_IsUnicode ? p_MaxTCHARs*2:p_MaxTCHARs) to VarSetCapacity(l_Text,p_MaxTCHARs), you told the LVM_GETITEMTEXT message that you had allocated twice as much space than you actually allocated. In other words, you allocated half as much space as you needed so when the message tried to access memory that wasn't there, you get an exception and AutoHotkey crashes.
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
Well, I will pretend that I understood what you post above (which I didn't), but anyway, I realized that with the fail loop method above, I don't need to worry about "p_maxChar" or "p_maxbyte", in fact, I will remove those parameters from the function! (I will set it internally inside the function to 1000100 characters, which is 1MB for ANSI? and 2MB for Unicode?)
By the way, do you have anything against removing "p_maxChar" or "p_maxbyte" parameters? Do you think it's unsafe or something?
Re: [ListView] How to force "LV_GetText()" function to get text longer than 8191 characters?
The p_MaxTCHARs parameter has a default value that is meant to be ignored (read: unspecified) in most cases. For example:
Code: Select all
StringFound:=LVM_GetText(hLV,LV_GetNext(0,"F"),1)
Code: Select all
StringFound:=LVM_GetText(hLV,LV_GetNext(0,"F"),2,1048576)