 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
kapege.de
Joined: 07 Feb 2005 Posts: 186 Location: Munich, Germany
|
Posted: Wed Oct 26, 2005 12:41 pm Post subject: [Solved] How to send an array with SendMessage |
|
|
I've to send a message 0x404 (Statusbar "SB_SetParts").
After trying this AHK crashes badly: | Code: | | SendMessage, 0x404, 3, "10,20,30",, ahk_id %BarHWND% |
The SB_SETPARTS is as LPARAM an array expecting. How can I send one?
This wont work either:
| Code: | array1 = 1
array2 = 2
array3 = 3
SendMessage, 0x404, 3, array,, ahk_id %BarHWND% |
Who has an idea? _________________ Peter
Wisenheiming for beginners: KaPeGe (German only, sorry)
Last edited by kapege.de on Mon Feb 06, 2006 2:56 pm; edited 1 time in total |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Wed Oct 26, 2005 4:46 pm Post subject: |
|
|
| The third parameter must be a 32-bit integer. If sending 3 separate messages fails, how about putting the three binary numbers in a variable and sending its address? |
|
| Back to top |
|
 |
shimanov
Joined: 25 Sep 2005 Posts: 612
|
Posted: Wed Oct 26, 2005 5:52 pm Post subject: |
|
|
Try the following:
It uses Chris's Status Bar example with his InsertInteger function.
| Code: | Gui, +Resize
Gui, Add, Edit, x5 y5 w300 h20 vMyEdit, This is the text to display in the bar.
Gui, Add, Button, Default, Submit
Gui, Add, Text, Hidden, xxxxxxx ; Reserves space for bar; for use with "Gui Show".
Gui, Show, w310
Gui +LastFound ; For use with WinExist() below.
; WS_CHILD (0x40000000) + WS_VISIBLE (0x10000000) = 0x50000000:
BarHWND := DllCall("CreateStatusWindow", int, 0x50000000, str, "Bar's Text", UInt, WinExist(), UInt, 5555)
VarSetCapacity( parts, 4*3 )
InsertInteger( 100, parts, 0 )
InsertInteger( 200, parts, 4 )
InsertInteger( -1, parts, 8 )
; SB_SETPARTS
SendMessage, 0x404, 3, &parts,, ahk_id %BarHWND%
return
ButtonSubmit:
GuiControlGet, MyEdit
SendMessage, 0x401, 0, &MyEdit,, ahk_id %BarHWND% ; 0x401 is SB_SETTEXT
return
GuiSize: ; This allows the bar to resize along with the window.
SendMessage, 5, 0, 0,, ahk_id %BarHWND% ; 5 is WM_SIZE
return
GuiClose:
ExitApp
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; To preserve any existing contents in pDest, only pSize number of bytes starting at pOffset
; are altered in it. The caller must ensure that pDest has sufficient capacity.
{
mask := 0xFF ; This serves to isolate each byte, one by one.
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 ; Write one byte.
, UChar, (pInteger & mask) >> 8 * (A_Index - 1))
mask := mask << 8 ; Set it up for isolation of the next byte.
}
} |
|
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Wed Oct 26, 2005 6:28 pm Post subject: |
|
|
Thanks for posting that. It had been on my to-do list to research it and reply, but I'd been procrastinating to try to catch up on other work.
By the way, if anyone needs to update the text in a part of the bar other the first, update the following line in the script above. Replace the number 0 with 1 to use the second part, 2 to use the third, etc:
SendMessage, 0x401, 0, &MyEdit,, ahk_id %BarHWND% ; 0x401 is SB_SETTEXT |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Wed Oct 26, 2005 7:47 pm Post subject: |
|
|
Beautiful!
Just to be a pain in the neck, the InsertInteger function can be simplified a bit. | Code: | PutInteger(ByRef pDest, Integer, Offset = 0, Size = 4)
{ ; Dest must have enough capacity!
Loop %Size% ; Copy each byte in Integer into Dest, as binary
DllCall("RtlFillMemory", UInt, &pDest + Offset + A_Index-1, UInt, 1 ; Write one byte
, UChar, (Integer >> 8*(A_Index-1) & 0xFF) )
} |
|
|
| Back to top |
|
 |
shimanov
Joined: 25 Sep 2005 Posts: 612
|
Posted: Wed Oct 26, 2005 9:04 pm Post subject: |
|
|
| Chris wrote: | | Thanks for posting that. |
Just bringing together the disparate [existing] pieces to realize the puzzle, for the community and my own benefit. |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Thu Oct 27, 2005 12:22 am Post subject: |
|
|
| Laszlo wrote: | | Just to be a pain in the neck, the InsertInteger function can be simplified a bit. | Simplification is good because although it might make the function less understandable, I think the performance benefit is well worth it in this case. I'll try to apply your change to InsertInteger in the help file. Thanks. |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Thu Oct 27, 2005 1:42 am Post subject: |
|
|
Here is the odd couple, with testcases. | Code: | z = AAAA
PutInt(z,55,0,1) ; AAAA -> 7AAA
MsgBox % GetUint(z,0,1) "`n" z
PutInt(ByRef pDest, Integer, Offset = 0, Size = 4)
{ ; Dest must have enough capacity!
Loop %Size% ; Copy each byte in Integer into the Dest, as binary
DllCall("RtlFillMemory", UInt, &pDest + Offset + A_Index-1, UInt, 1 ; Write one byte
, UChar, (Integer >> 8*(A_Index-1) & 0xFF) )
}
GetUInt(ByRef pSource, Offset = 0, Len = 4)
{
Loop %Len%
result += *(&pSource+Offset+A_Index-1) << 8*(A_Index-1)
return result ; += works w/o init
} |
|
|
| Back to top |
|
 |
kapege.de
Joined: 07 Feb 2005 Posts: 186 Location: Munich, Germany
|
Posted: Thu Oct 27, 2005 1:16 pm Post subject: |
|
|
Thanx pals for your help!
Now I'm looking forward to complete my set of functions to control the status bar.  _________________ Peter
Wisenheiming for beginners: KaPeGe (German only, sorry) |
|
| Back to top |
|
 |
kapege.de
Joined: 07 Feb 2005 Posts: 186 Location: Munich, Germany
|
Posted: Mon Feb 06, 2006 2:55 pm Post subject: |
|
|
Now here is my complete set of functions to the Statusbar:
| Code: |
; SB_Segments: Initiates a Status Bar and divides it into segments. Depends on "VarSetCapacity" and "InsertInteger".
; Usage: You put the positions of your segments into a string like this "10,20,100,200,-1". The numbers determins the right edge of the segment, "-1" means 'make a final segment filling the remaining space until the rightmost border'
; If the string is empty ("") you'll only see the size grip (see sample below)
; Sample: SB_Segments("20,44,200,350,450,-1")
; To get the correct GUI for a status bar you should have to do a 'Gui +LastFound' before calling 'SB_Segments'
; To resize the Statusbar with the Gui:
; guisize:
; SendMessage, 5, 0, 0,, ahk_id %BarHWND% ; 5 is WM_SIZE
; return
SB_Segments(segs)
{
global BarHWND
; WS_CHILD (0x40000000) + WS_VISIBLE (0x10000000) = 0x50000000:
BarHWND := DllCall("CreateStatusWindow", int, 0x50000000, str, "", UInt, WinExist(), UInt, 5555)
if (segs = "") {
VarSetCapacity(parts, 4) ; Create 'parts' and make it 4 Byte times n segments large
SendMessage, 0x404, 1, &parts,, ahk_id %BarHWND% ; Sends the number of segments and its positions to the status bar
return, BarHWND
} else {
n = 0
loop, Parse, segs, CSV ; How many segments are needed -> n
n++
VarSetCapacity( parts, 4*n ) ; Create 'parts' and make it 4 Byte times n segments large
loop, Parse, segs, CSV ; Fill the var 'parts' with content (the postitons)
InsertInteger( A_LoopField, parts, 4 * ( A_Index - 1 ) ) ; Reserves 4 Bytes per run in the string "parts"
SendMessage, 0x404, %n%, &parts,, ahk_id %BarHWND% ; Sends the number of segments and its positions to the status bar
return, BarHWND
}
}
; SB_Icon: Adds an icon to a specific segment within a status bar
; SEG is the number of the segment (the first segment is 1, the second 2...)
; NAME is the filename of the graphic to show
; Sample: SB_Icon(1, "icon.ico") This puts the file 'icon.ico' into the first segment of your status bar
SB_Icon(seg, name)
{
global BarHWND
seg-- ; subs 1 from the segment, because it starts with zero
hicon := DllCall("LoadImage", UInt, NULL, Str, name, UInt, 1, Int, 16, Int, 16, UInt, 0x10|0x2000)
if hicon
SendMessage, 0x40F, seg, hicon,, ahk_id %BarHWND% ; 0x40F is SB_SETICON
return
}
; SB_Text: Puts a text into a segment of your status bar
; SEG is the number of the segment (the first segment is 1, the second 2...)
; TEXT is the text to display. Put it into doublequotes
; Sample: SB_Text(1,"Hello World!")
SB_Text(seg, text)
{
global BarHWND
seg--
SendMessage, 0x401, %seg%, &text,, ahk_id %BarHWND% ; 0x401 is SB_SETTEXT
return
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; To preserve any existing contents in pDest, only pSize number of bytes starting at pOffset
; are altered in it. The caller must ensure that pDest has sufficient capacity.
{
mask := 0xFF ; This serves to isolate each byte, one by one.
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 & mask) >> 8 * (A_Index - 1))
mask := mask << 8 ; Set it up for isolation of the next byte.
}
}
; ----- Sample with empty bar (shows only the size grip)
#singleinstance force
gui, +resize
gui, show, h50 w200
; add statusbar control:
gui, +lastfound
SB_Segments("")
return
guisize:
SendMessage, 5, 0, 0,, ahk_id %BarHWND% ; 5 is WM_SIZE
return
|
I put the code here to link it with the wiki. _________________ Peter
Wisenheiming for beginners: KaPeGe (German only, sorry) |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 4016 Location: Pittsburgh
|
Posted: Mon Feb 06, 2006 11:42 pm Post subject: |
|
|
Nice and easy to use! I added it to my tools box.
I cannot resist... you can save a few lines: | Code: | Gui +Resize
Gui Show, h50 w200
BarHWND := SB_Segments("20,44,99,-1")
SB_Icon(BarHWND, 2, "XX.ICO") ; <-- put here your icon file
SB_Text(BarHWND, 2, "OK?")
Return
SB_Segments(segs) ; Create Status Bar for Last GUI, divide it into segments, return its handle
{ ; segs = right-edge positions of segments in string "10,20,-1" (-1 = right border)
Gui +Lastfound ; \/ WS_CHILD (0x40000000) + WS_VISIBLE (0x10000000)
BarHWND := DllCall("CreateStatusWindow", int, 0x50000000, str, "", UInt, WinExist(), UInt, 5555)
IfEqual segs,, SetEnv segs,-1
StringReplace segs,segs,`,,`,,UseErrorLevel
n := ErrorLevel + 1 ; # segments
VarSetCapacity( parts, 4*n ) ; Reserve 4 Bytes for each segment
Loop Parse, segs, `, ; Fill the var 'parts' with the positions
InsertInteger( A_LoopField, &parts + 4*A_Index-4 )
SendMessage 0x404,%n%,&parts,,ahk_id %BarHWND% ; Send number of segments, positions to status bar
Return BarHWND
}
SB_Icon(BarHWND, seg, file) ; Add icon from 'file' to segment 'seg' = 0,1.. in the status bar
{
hicon := DllCall("LoadImage", UInt, NULL, Str, file, UInt, 1, Int, 16, Int, 16, UInt, 0x2010)
If hicon
SendMessage 0x40F,seg,hicon,,ahk_id %BarHWND% ; 0x40F = SB_SETICON
}
SB_Text(BarHWND, seg, text) ; Add 'text' to segment 'seg' = 0,1.. in the status bar
{
SendMessage 0x401,%seg%,&text,,ahk_id %BarHWND% ; 0x401 = SB_SETTEXT
}
InsertInteger(pInteger, pAddress, pSize = 4)
{ ; Copy bytes in pInteger into pAddress as raw binary data
Loop %pSize%
DllCall("RtlFillMemory", UInt,pAddress+A_Index-1, UInt,1, UChar, pInteger >> 8*A_Index-8 & 0xFF )
}
GuiSize: ; Called when the GUI is resized
SendMessage 5,0,0,,ahk_id %BarHWND% ; 5 = WM_SIZE
Return |
|
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue Feb 07, 2006 8:42 am Post subject: |
|
|
I would suggest to extend the SB_Segments(segs) to contain a GUIID which defaults to 1, so you could use it for multiple GUIs | Code: | SB_Segments(segs, GuiID=1) {
Gui, %GuiID%:+Lastfound |
_________________ Ciao
toralf  |
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue Feb 07, 2006 9:02 am Post subject: |
|
|
And if you set a default for segs (e.g. SB_Segments(segs = -1, GuiID = 1)) you can even leave out the line "IfEqual segs,, SetEnv segs,-1"
BTW: Nice mod, laszlo. I'll use it, put it to my tool box as well. Thanks KaPeGe for the research and your work. _________________ Ciao
toralf  |
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue Feb 07, 2006 9:15 am Post subject: |
|
|
And another mod: If you put "% seg-1" (instead of just "%seg%" or "seg") into the SendMessage commands for Image and Text, the segments start to count from 1. Which might be ease the handling of the functions, since in AHK normally everything starts with 1 and not with 0. _________________ Ciao
toralf  |
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue Feb 07, 2006 10:36 am Post subject: |
|
|
And BTW: KaPeGe, please post your code (maybe with the improvements) in the script and fucntions section. It is very dufficult to find in this topic, I lost it and just found it again.
I searched for it since I discovered a problem. Please try this code: | Code: | Gui, 1:+Resize
Gui, 1:Add, Button, vB2, Test Button2
Gui, 1:Add, Text,, This is a test
Gui, 1:Add, Text,, ... another test...
Gui, 1:Show, ;h300
BarHWND := SB_Segments("50,50,-1")
SB_Text(BarHWND, 1, "OK?")
Return
GuiSize:
SendMessage 5,0,0,,ahk_id %BarHWND%
Return
SB_Segments(segs = -1, GuiID = 1){
Gui, %GuiID%:+Lastfound
BarHWND := DllCall("CreateStatusWindow", int, 0x50000000, str, "", UInt, WinExist(), UInt, 5555)
StringReplace segs,segs,`,,`,,UseErrorLevel
n := ErrorLevel + 1
VarSetCapacity( parts, 4*n )
Loop Parse, segs, `,
InsertInteger( A_LoopField, &parts + 4*A_Index-4 )
SendMessage 0x404,%n%,&parts,,ahk_id %BarHWND%
Return BarHWND
}
SB_Text(BarHWND, seg, XXXtextXXX){
SendMessage 0x401,% seg-1,&XXXtextXXX,,ahk_id %BarHWND%
}
InsertInteger(pInteger, pAddress, pSize = 4){
Loop %pSize%
DllCall("RtlFillMemory", UInt,pAddress+A_Index-1, UInt,1, UChar, pInteger >> 8*A_Index-8 & 0xFF )
} | The test "... another test... " gets permanently shown in the Statusbar, even if you resize the GUI. If you set a hight for the GUI (e.g. h300) so that the text is not below the statusbar it works ok.
Is there a way around that? The only solution I can think of is to enlarge the GUI prior to adding a Statusbar. _________________ Ciao
toralf  |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|