Archive: Reading lines from a richedit control


Reading lines from a richedit control
I've been trying to adapt the 'Dump log to file' function ( http://nsis.sourceforge.net/wiki/Dump_log_to_file ) to be able to dump the content of a RichEdit control - without success so far...

There are three basic changes I've made, beside getting the proper window..

GetDlgItem $0 $0 1204   ; 1204 is the correct control in my case


Instead of the line with "${LVM_GETITEMCOUNT}", I use :
SendMessage $0 0xBA 0 0 $6  ; 0xBA = EM_GETLINECOUNT


So far so good - I get the correct number of lines in the richedit control in $6.

Instead of the line with "${LVM_GETITEMTEXT}", I use :
# 0xC4 = EM_GETLINE
System::Call "User32::SendMessageA(i, i, i, i) i ($0, 0xc4, $2, r1)"


Followed by the original line :
System::Call "*$3(&t${NSIS_MAX_STRLEN} .r4)"


And that's where the problem starts... $4, at that point, contains zip, nada, nothing. In the dump log function, this contains the text from the installer log on line $2.

Any thoughts on why this isn't working ? I tried looking up the MSDN info, but as far as I can tell the format is correct ( handle, message, line number, buffer ). Any help would be much appreciated.

If a post with the complete script is required, just let me know.

That's because you still put the return value in the structure pointed to by $1. That structure points to the buffer pointed to by $3, but it's no longer used by you. Replace r1 with r3 in the SendMessage call you've posted above.


Hi kichik,

Thank you very much for your reply. Unfortunately, changing .r1 with .r3 didn't do anything either. Can't seem to wrap my head around what's happening, exactly...

Here's the important bit of the code, with your change...


# $0 = richedit control's handle
# get (0xBA) the linecount from the control ($0) and stick in $6
# 0xBA = EM_GETLINECOUNT
SendMessage $0 0xBA 0 0 $6
MessageBox MB_OK "Numlines: $6" ; so far so good
# allocate a buffer with appropriate size
System::Alloc ${NSIS_MAX_STRLEN}
# pointer to that buffer's address into $3
Pop $3
# start a line counter at 0 (zero)
StrCpy $2 0
# not entirely sure what this line does,
# but I thought it made a copy of the buffer
# and put the max string length on the first line
System::Call "*(i, i, i, i, i, i, i, i, i) i (0, 0, 0, 0, 0, r3, ${NSIS_MAX_STRLEN}) .r1"
loop:
# if the current line is the last, then we're done
StrCmp $2 $6 done
# From the control ($0) Get (0xC4) the line ($2) into the buffer ($3)
# 0xC4 = EM_GETLINE
System::Call "User32::SendMessageA(i, i, i, i) i ($0, 0xC4, $2, r3)"
# get the data from $3 into $4
System::Call "*$3(&t${NSIS_MAX_STRLEN} .r4)"
# show the line
MessageBox MB_OK "Line: $4" ; $4 is empty :/
# increase line counter
IntOp $2 $2 + 1
# on to the next
Goto loop


# $R0 = richedit control's handle
SendMessage $R0 ${EM_GETLINECOUNT} 0 0 $R3

System::Alloc ${NSIS_MAX_STRLEN}
Pop $R1
StrCpy $R2 0

loop:
StrCmp $R2 $R3 free
System::Call 'kernel32::lstrcpyA(i R1, t ${NSIS_MAX_STRLEN})'
System::Call 'user32::SendMessageA(i R0, i ${EM_GETLINE}, i R2, i R1) i .R4'
System::Call '*$R1(&t${NSIS_MAX_STRLEN} .R5)'
IntOp $R2 $R2 + 1
StrCpy $R5 $R5 $R4
MessageBox MB_YESNO "Line: $R5$\n$\nFind next?" IDYES loop

free:
System::Free $R1

That works - thank you very much!

And I can actually almost tell what's going on.
lstrcpyA is used to put the buffer size into the first word of the buffer, as per the EM_GETLINE spec thing...
Then the $R2th line from control $R0 is retrieved (EM_GETLINE) into the buffer ($R1), and the result of the operation is put into $R4?
Then the content of that buffer($R1) is put into a var ($R5).
So the only bit that confuses me is the StrCpy where you put the result of the GETLINE call at the end of the actual line of content... rather, the reason for doing this.


Sorry, had not much time for previous reply, so few mistakes appeared:


# $R0 = richedit control's handle
# $R1 = buffer address
# $R2 = current line number
# $R3 = sum of lines
# $R4 = current line lenght
# $R5 = current line

SendMessage $R0 ${EM_GETLINECOUNT} 0 0 $R3

System::Alloc ${NSIS_MAX_STRLEN}
Pop $R1
StrCpy $R2 0

loop:
StrCmp $R2 $R3 free
System::Call '*$R1(i ${NSIS_MAX_STRLEN})'
System::Call 'user32::SendMessageA(i R0, i ${EM_GETLINE}, i R2, i R1) i .R4'
System::Call '*$R1(&t$R4 .R5)'
IntOp $R2 $R2 + 1
MessageBox MB_YESNO "Line: $R5$\n$\nFind next?" IDYES loop

free:
System::Free $R1