 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
PhiLho
Joined: 27 Dec 2005 Posts: 6836 Location: France (near Paris)
|
Posted: Tue Aug 29, 2006 2:15 pm Post subject: Flexible Gui Up Down control |
|
|
[EDIT] numEric provided a much better version, which is referenced in the manual now. See Radio button to control number of loops and msgbox text for some reasons why it is better.
I left this because some techniques here can be interesting.
Recently, Torteth asked for more flexibility for the UpDown GUI control.
I came with a workaround that seems to be usable, but was hard-coded.
I tried to add a bit of flexibility and code-reuse.
There are still some constraints and limitations:
- These special controls must be created before any other Edit control. This limitation could be removed if we knew the ClassNN of a newly added control. Perhaps it is already possible.
[EDIT] I found how to remove this restriction! Yeah!
- I coded this only for the main GUI (no GUI number). Not a big problem, I think.
- The user can change the value to one that cannot be reached with the control. Eg., in my example, using the arrows you can get only even numbers, but if the user types an odd number, the progress will then go from one odd number to the next.
This can be actually an advantage, and it is easy to add, if necessary, code to check if the value is valid, otherwise to constrain it to legal values only.
Note that with a small hack, you can associate two up-down controls to an edit one, eg. one for coarse values, the other for finer values.
Here is the code, with a small example:
| Code: | ; Example of use
Gui Add, Edit, x10 y70 w250 h100, Just`nto test`nUp and Down`noutside a Fud.
; Current number of such controls
#fudControlNb := 0
?fudRangeLow := 0
?fudRangeHigh := 10
?fudIncrement := 0.1
?fudStartValue := 5
?fudXPos := 10
?fudYPos := 10
?fudWidth := 70
?fudVarName = firstUD
Gosub AddFlexibleUpDownControl
?fudRangeLow := -50
?fudRangeHigh := 50
?fudIncrement := 2
?fudStartValue := 0
?fudXPos := 10
?fudYPos := 40
?fudWidth := 50
?fudVarName = anotherUpDown
Gosub AddFlexibleUpDownControl
Gui Add, Button, x100 y180 w50 h25 gShowValues, OK
Gui +LastFound
guiID := WinExist()
Gui Show, w320, FlexibleGuiUpDown
Return
ShowValues:
Loop %#fudControlNb%
{
v := #fudControlList?vn?%A_Index%
GuiControlGet %v%
v := %v%
r = %r%UD%A_Index% = %v%`n
}
MsgBox %r%
Return
/*
Flexible Gui Up Down control
*/
; I prefix the volatile variables I use here with fud? and the persistant ones with #fud
; to avoid clashes with the variables of the host application.
; Also I prefix the parameters of the subroutine with ?fud.
; Alas, this makes the code quite obscure...
AddFlexibleUpDownControl:
; Store the parameters of the control
#fudControlNb += 1
#fudControlArray%#fudControlNb%?rangLow := ?fudRangeLow
#fudControlArray%#fudControlNb%?rangHigh := ?fudRangeHigh
#fudControlArray%#fudControlNb%?increment := ?fudIncrement
; Create the pseudo-buddy edit control, named as requested
Gui Add, Edit, x%?fudXPos% y%?fudYPos% w%?fudWidth% h20 v%?fudVarName%, %?fudStartValue%
px := ?fudXPos + ?fudWidth
; Create the up-down control on the right of the buddy
Gui Add, UpDown, x%px% y%?fudYPos% w12 h24 Range-1-1 -16 gUDClick v[%?fudVarName%], 0
; Store lookup information
#fudControlList?id?%?fudVarName% := #fudControlNb
#fudControlList?vn?%#fudControlNb% := ?fudVarName
Return
UDClick:
; Which up-down control was clicked?
fudVar?udVar := A_GuiControl
fudVar?udValue := %fudVar?udVar% ; -1 or 1
; Remove [ and ] to get the control name
StringTrimLeft fudVar?udVar, fudVar?udVar, 1
StringTrimRight fudVar?udVar, fudVar?udVar, 1
; Get the control ID
fudVar?controlNb := #fudControlList?id?%fudVar?udVar%
UDChange:
; Get value in the Edit control
GuiControlGet %fudVar?udVar%
; Add (or substract) the increment
fudVar?udValue := %fudVar?udVar% + fudVar?udValue * #fudControlArray%fudVar?controlNb%?increment
; Keep it within the bounds (no wrapping yet)
If (fudVar?udValue < #fudControlArray%fudVar?controlNb%?rangLow)
fudVar?udValue := #fudControlArray%fudVar?controlNb%?rangLow
Else If (fudVar?udValue > #fudControlArray%fudVar?controlNb%?rangHigh)
fudVar?udValue := #fudControlArray%fudVar?controlNb%?rangHigh
; Update the value in the Edit control
GuiControl, , %fudVar?udVar%, %fudVar?udValue%
; And reset the UpDown control to the neutral position
GuiControl, , [%fudVar?udVar%], 0
Return
~*Up::
~*Down::
; Get the variable name of the control with the focus
GuiControlGet fudVar?udVar, FocusV
fudVar?controlNb := 0
; Search if it is one of our flexible up down controls...
Loop %#fudControlNb%
{
If (fudVar?udVar = #fudControlList?vn?%A_Index%)
{
; Found!
fudVar?controlNb := A_Index
Break
}
}
If (fudVar?controlNb > 0)
{
; OK, that's one of our controls
If (A_ThisHotkey = "~*Up")
fudVar?udValue := 1
Else
fudVar?udValue := -1
Goto UDChange
}
Return
GuiClose:
GuiEscape:
ExitApp
| I hope you will find this useful. _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Last edited by PhiLho on Mon Oct 09, 2006 11:41 am; edited 2 times in total |
|
| Back to top |
|
 |
foom
Joined: 19 Apr 2006 Posts: 386
|
Posted: Tue Aug 29, 2006 8:11 pm Post subject: |
|
|
Hi philho,
Torteths thread caught my attention too since i am developing and frontend for H.264 encoding and would like to have updown controls which output floats since some of the commandline params the frontend passes to x264.exe are floats.
I apreciate your work on this but still think that this is a bunch of code and i think i might have and solution which would be easier to maintain.
Problem is that it demands to work with structures.
Now youre one of ahk's bitjugglers and might tell me whats wrong with following code
Edit:
Found the error and reworked the script. Here you go.
| Code: | #SingleInstance force
;"(ClassNN of the editcontrol which should have floats in it, found via windowspy)|(minvalue)|(maxvalue)|(steps)(`n)(NextEditsClassNN...)"
udEditList:="Edit1|10|50|0.25`nEdit2|-10|10|0.5"
;add the controls as usuall
Gui Add, Edit, w100 h20 vudedit,
Gui Add, UpDown, w30 h24 vud , 23
Gui Add, Edit, w100 h20 vudedit2,
Gui Add, UpDown, w30 h24 vud2 , 5
Gui, Show
;look for the WM_NOTIFY message
OnMessage(0x4E, "WM_NOTIFY")
return
WM_NOTIFY(wParam, lParam)
{
if (ExtractIntegerP(lParam,8,1) = -722) ; if this is true a updowncontrol has send an UDN_DELTAPOS message
{
udHwnd:=ExtractIntegerP(lparam,0,0)
iPos:=ExtractIntegerP(lparam,12,1)
iDelta:=ExtractIntegerP(lparam,16,1)
SendMessage, 0x46A,,,, ahk_id %udHwnd% ;gets the buddy of the updowncontrol that send the UDN_DELTAPOS message
if (errorlevel)
{
udEditHwnd:=errorlevel
udData:=GetudData(udEditHwnd,iDelta) ;parse the udEditList and return the new value
if udData = FAIL
Return False ;the item was not found in the udEditList
ControlSetText,, % udData , ahk_id %udEditHwnd% ;set the new value in the editcontrol
return True ; indicates that the proposed change from the updowncontrol should be discarded
}
else
return False ; don't discard the proposed change by the updowncontrol
}
}
GetudData(_udEditHwnd,_delta)
{
local udEditListItem, udEdithwnd, udEdit
Loop, Parse, udEditList, `n, `n
{
StringSplit, udEditListItem, A_LoopField,|
ControlGet, udEdithwnd, Hwnd,, %udEditListItem1%, A
if (udEdithwnd = _udEdithwnd)
{
ControlGetText, udEdit,, ahk_id %udEditHwnd%
udEdit+=udEditListItem4*_Delta
if (udEdit < udEditListItem2)
return udEditListItem2
else if (udEdit > udEditListItem3)
return udEditListItem3
else
return udEdit
}
else
continue
}
Return "FAIL"
}
GuiClose:
ExitApp
ExtractIntegerP(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 4)
{
Loop %pSize%
result += *(pSource + pOffset + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result
return -(0xFFFFFFFF - result + 1)
} |
@Chris
If you read this, notice this is again an opurtunity for a Hwnd() function like discussed here because one could simply use the associated vVarNames instead of having to look up the ClassNN with WindowSpy.
Last edited by foom on Wed Aug 30, 2006 1:38 pm; edited 1 time in total |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6836 Location: France (near Paris)
|
Posted: Wed Aug 30, 2006 1:37 pm Post subject: |
|
|
I like your way, it is good to have an alternative.
The good points:
- The controls are created in the classical way, using buddy.
- The code is indeed slightly clearer -- but of same size (if you remove the demo code in both versions).
The bad points:
- You still have to know in advance the classNN of the added controls... It is doable in GUIs, but not very friendly. Of course, it is more a limitation of AHK than a problem with your code.
- More annoying, but I suppose you can correct this: if you use the Up and Down keys in the edit control, as requested, the progress will still be 1 by 1, and starting at the initial default value...
- You parse the settings each time. I avoided this by putting them in arrays, at the cost of convoluted names... And frankly, the time spent on parsing is probably unoticeable. _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2") |
|
| Back to top |
|
 |
foom
Joined: 19 Apr 2006 Posts: 386
|
Posted: Wed Aug 30, 2006 1:43 pm Post subject: |
|
|
| PhiLho wrote: |
- More annoying, but I suppose you can correct this: if you use the Up and Down keys in the edit control, as requested, the progress will still be 1 by 1, and starting at the initial default value...
|
Ohh Snap!
Can you give me some advice?
BTW same goes for holding up or down pressed in the control which is the effekt of pressing the up or down key in the edit. I have no idea whats causing that. |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6836 Location: France (near Paris)
|
Posted: Wed Aug 30, 2006 4:02 pm Post subject: |
|
|
I think that the problem is with the mysterious (undocumented) SendMessage 0x46A.
Either it fails and errorlevel is 0 and you return false (that's what I see with WinInspector), or the GetudData fails for the same result. _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2") |
|
| Back to top |
|
 |
foom
Joined: 19 Apr 2006 Posts: 386
|
Posted: Wed Aug 30, 2006 9:09 pm Post subject: |
|
|
| PhiLho wrote: | I think that the problem is with the mysterious (undocumented) SendMessage 0x46A.
Either it fails and errorlevel is 0 and you return false (that's what I see with WinInspector), or the GetudData fails for the same result. |
No that message is just for retrieving the ud's buddy UDM_GETBUDDY.
And it doesn't fail eighter doesn't GetudData fail.
I think it has something to do with UDM_SETACCEL which i think is responsible for the numbers getting in/decremented faster/(in bigger steps) the longer you keep up or down pressed.
Is there anywhere on the web the source of the updownclass i could have a look at? Because i can't find it in the includefiles of gcc. |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6836 Location: France (near Paris)
|
Posted: Thu Aug 31, 2006 12:24 pm Post subject: |
|
|
| foom wrote: | | Is there anywhere on the web the source of the updownclass i could have a look at? | AFAIK, Windows' sources are quite secret, Microsoft hasn't completely gone the open source way...
I looked again with Winspector Spy, when using the arrow key, the WM_NOTIFY message is sent, but not managed by the OnMessage (the function isn't called). Strange. _________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2") |
|
| Back to top |
|
 |
foom
Joined: 19 Apr 2006 Posts: 386
|
Posted: Thu Aug 31, 2006 12:57 pm Post subject: |
|
|
| Maybe Chris borked something with the last update...he did somethink to fix an onmessage bug. I found another bug with onmessage. See here |
|
| 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
|