 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
corrupt
Joined: 29 Dec 2004 Posts: 2397
|
Posted: Thu Sep 15, 2005 5:11 am Post subject: |
|
|
I like the idea of using a variation of a control's variable name but from testing the A_GuiControl value passed does not seem to be stable/consistent at times and some controls don't seem to reference an associated variable using this method. Here's a test script: | Code: | ; Create GUI
Gui, Add, Text, vMoveAnywhere, Move your mouse anywhere in this window.
Gui, Add, Edit, w200 vMyEdit
Gui, Add, Edit, w200 vMyEdit2
Gui, Add, Button, vB1, Test Button1
Gui, Add, Button, vB2, Test Button2
Gui, Add, Text,, This is a test
Gui, Add, Text,, ... another test...
Gui, Show,, test
WinSet, Transparent, 200, test
OnMessage(0x200, "WM_MOUSEMOVE")
Return
WM_MOUSEMOVE(wParam, lParam)
{
ShowToolTips(A_GuiControl)
}
ShowToolTips(ctrlin)
{
MouseGetPos,tt_x,tt_y,, tt_ThisControl
If (!ctrlin And tt_ThisControl)
MsgBox, 16,, %ctrlin%, 0.4
Else If (ctrlin And tt_ThisControl)
MsgBox, 64,, %ctrlin%, 0.4
}
GuiClose:
ExitApp | The text control at the top doesn't seem to pick up the variable name and the edit and button controls seem a bit picky when moving the mouse from the window on to the control (sometimes a value is not returned). When the mouse is already on the edit or button control and being moved the return value seems ok... |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Thu Sep 15, 2005 3:10 pm Post subject: |
|
|
| Quote: | | the edit and button controls seem a bit picky when moving the mouse from the window on to the control (sometimes a value is not returned). | That's probably caused by the fact that the very first WM_MOUSEMOVE is only one pixel different from where the cursor was before, and hasn't quite reached the control yet. But that first message calls the function, and the function displays a MsgBox rather than something non-blocking like ToolTip. As a result, all WM_MOUSEMOVE messages received during the MsgBox are treated as unmonitored.
| corrupt wrote: | the A_GuiControl value passed does not seem to be stable/consistent at times
The text control at the top doesn't seem to pick up the variable name | OnMessage() translates the incoming message's hwnd into the corresponding control and puts that value into A_GuiControl. So when you move the mouse over a text control and perhaps a few other types, apparently the OS does not send the message to the control but rather to the parent window.
Although this could be "fixed" by adding special handling for WM_MOUSEMOVE, I think the added code size would be unjustified.
In light of this, A_GuiControl isn't as appropriate a solution as I had hoped. Eventually, there will be a way to translate a ClassNN into the GUI control's variable name, which should make a script like yours easier to write. |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2397
|
Posted: Fri Sep 16, 2005 3:19 am Post subject: |
|
|
| Thanks for the explanations Chris. Would adding a GetControlVar type command to retrieve the name of a control's associated variable name (if any) based on ClassNN (and maybe other options like based on caption, etc...) be a possibility? It might come in handy for other scripts as well... |
|
| Back to top |
|
 |
Serenity
Joined: 08 Nov 2004 Posts: 1003
|
Posted: Tue Feb 07, 2006 8:25 am Post subject: |
|
|
I tried corrupt's tooltip script and have noticed that in other areas of windows (the taskbar for example) tooltips behave differently - they are not destroyed if the mouse is moved, but only if the control/window under the mouse changes.
I have tried to modify the example script to work in this fashion with a statusbar control, but it doesn't destroy the tooltip if the window under the mouse changes, leaving an annoying "hanging" tooltip:
| Code: | #singleinstance force
gui, +resize
gui, show, h50 w200
Gui +LastFound ; For use with WinExist() below.
; WS_CHILD (0x40000000) + WS_VISIBLE (0x10000000) = 0x50000000:
BarHWND := DllCall("CreateStatusWindow", int, 0x50000000, str, "statusbar text", UInt, WinExist(), UInt, 5555)
SetToolTips()
OnMessage(0x200, "WM_MOUSEMOVE")
return
GuiSize: ; This allows the bar to resize along with the window.
SendMessage, 5, 0, 0,, ahk_id %BarHWND% ; 5 is WM_SIZE
return
WM_MOUSEMOVE()
{
Global
MouseGetPos,,,, tt_ThisControl
CurrentTip := tt_%tt_ThisControl%
If (tt_TipShown != CurrentTip)
{
ToolTip
SetTimer, ToolTipStart, %tt_StartDelay%
}
}
SetToolTips()
{
Global
; Tooltips - User defined
tt_msctls_statusbar321 := "statusbar tooltip"
; ToolTip delays
tt_StartDelay := 1000
tt_Timeout := 4000
}
ToolTipStart:
MouseGetPos,,, tt_ChkWin, tt_ChkControl
If (tt_ChkControl = tt_ThisControl)
{
ToolTip, %CurrentTip%
tt_TipShown := CurrentTip
SetTimer, ToolTipTimeout, %tt_Timeout%
}
SetTimer, ToolTipStart, Off
Return
ToolTipTimeout:
ToolTip
SetTimer, ToolTipTimeout, Off
Return
GuiClose:
ExitApp |
_________________ "Anything worth doing is worth doing slowly." - Mae West
 |
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue Feb 07, 2006 9:53 am Post subject: |
|
|
Why use ToolTip,
with KaPeGes Statusbar, you could use the statusbar: Would that solve the problem?
| Code: | ; Create GUI
Gui, Add, Text, vMoveAnywhere, Move your mouse anywhere in this window.
Gui, Add, Edit, w200 vMyEdit
Gui, Add, Edit, w200 vMyEdit2
Gui, Add, Button, vB1, Test Button1
Gui, Add, Button, vB2, Test Button2
Gui, Add, Text,, This is a test
Gui, Add, Text,, ... another test...
Gui, Show,, test
BarHWND := SB_Segments("10,-1")
OnMessage(0x200, "WM_MOUSEMOVE")
Return
WM_MOUSEMOVE(wParam, lParam){
global BarHWND
MouseGetPos,tt_x,tt_y,, tt_ThisControl
SB_Text(BarHWND, 2, "x" tt_x " - y" tt_y " - "A_GuiControl " - " tt_ThisControl )
}
SB_Segments(segs = -1, GuiID = 1){
Gui, %GuiID%:+Lastfound ;\/(line below) WS_CHILD (0x40000000) + WS_VISIBLE (0x10000000)
BarHWND := DllCall("CreateStatusWindow", int, 0x50000000, str, "", UInt, WinExist(), UInt, 5555)
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_Text(BarHWND, seg, text){
SendMessage 0x401,% seg-1,&text,,ahk_id %BarHWND% ; 0x401 = SB_SETTEXT
}
InsertInteger(pInteger, pAddress, pSize = 4){
Loop %pSize%
DllCall("RtlFillMemory", UInt,pAddress+A_Index-1, UInt,1, UChar, pInteger >> 8*A_Index-8 & 0xFF )
}
GuiClose:
ExitApp |
_________________ Ciao
toralf  |
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue Feb 07, 2006 9:56 am Post subject: |
|
|
Depending on tt_x, tt_y, A_GuiControl and tt_ThisControl you could disply different text in the statusbar. _________________ Ciao
toralf  |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Tue Feb 07, 2006 10:33 am Post subject: |
|
|
@Serenity: If I recall correctly, you have to use NC messages (nonclient) to receive events outside the client area of the window.
If you add: | Code: | | OnMessage(0x84, "WM_MOUSEMOVE") ;"WM_NCHITTEST" | to your code, the tooltip will be dismissed when the cursor goes on the border.
Alas, that's not enough if the mouse moves too fast to generate a WM_NCHITTEST notification on the border.
I think that when you display the tooltip, you must capture the mouse, to get mouse events even outside the window. That's usually used by color pickers, screen capture applications, etc.
Or, in our case, to detect that the mouse has gone outside the window, in which case we just dismiss the tooltip and release the capture.
I fear that mouse capture at API level is outside the field of AutoHotkey (needing to process at window procedure level), but I can be wrong. Some highly talented AHK programmers already shown wonders...
@toralf: the statusbar can be an alternative, indeed, although that's not quite the same thing (immediate information right on the eye's focus vs. remembering to take a look at the status bar; or, on the other hand, intrusive obnoxious (but that may be disabled) redundant information vs. information to look only on demand).
But the point of Serenity being to show a tooltip on the status bar, your answer doesn't work  |
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue Feb 07, 2006 10:42 am Post subject: |
|
|
It was meant more as a workaround. I use several commercial software at work that do not use ToolTip but the Statusbar for info. I guess it is more a philiosophy.
Instead of capturing the mouse, you may use a global timer that removes "WhichToolTip" every x seconds. _________________ Ciao
toralf  |
|
| Back to top |
|
 |
Thalon
Joined: 12 Jul 2005 Posts: 640
|
Posted: Tue Feb 07, 2006 10:51 am Post subject: |
|
|
Hehe,
I wanted to add some help-texts in a statusbar in one of the next days (because I found a sample script), but now I have to do less work in getting it working
Thx 2 KaPeGe and toralf!
By-the-way:
I like Status-Bar-Info. They do inform me about new topics and for advanced user they are not disturbing. I think it's a nice solution, and faster than tooltips!
Thalon _________________ AHK-Icon-Changer
AHK-IRC
deutsches Forum
SacredVault |
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue Feb 07, 2006 12:33 pm Post subject: |
|
|
| PhiLho wrote: | | Code: | | OnMessage(0x84, "WM_MOUSEMOVE") ;"WM_NCHITTEST" |
| Wouldn't it be better to use: WM_NCMouseLeave?
Unfortunately I do not know the HexCode, and I do not know how to find it. _________________ Ciao
toralf  |
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue Feb 07, 2006 12:42 pm Post subject: |
|
|
Found it: | Code: | | OnMessage(0x2A2, "WM_NCMOUSELEAVE") |
@Chris, maybe this could be added to the doc (list of windows messages)? _________________ Ciao
toralf  |
|
| Back to top |
|
 |
PhiLho
Joined: 27 Dec 2005 Posts: 6721 Location: France (near Paris)
|
Posted: Tue Feb 07, 2006 12:46 pm Post subject: |
|
|
| toralf wrote: | | Wouldn't it be better to use: WM_NCMouseLeave? | Perhaps in this case WM_MOUSELEAVE would be better.
Both need to call TrackMouseEvent function to be generated.
I have no time to test it, but somebody else can get a look...
[EDIT] MSDN, and therefore me, was wrong, and toralf was right to try anyway (below). As Winspector Spy shows, Windows indeed generates a WM_NCMOUSELEAVE notification when the mouse leaves the status bar, even if not calling the TrackMouseEvent function before. I don't know if this is specific to WinXP.
Note that if you move the mouse down very fast, the WM_NCMOUSELEAVE notification may not be generated, thought. Perhaps this is related to WM_NCHITTEST, ie. the mouse need to be detected above a border to generate this message.
| toralf wrote: | | Unfortunately I do not know the HexCode, and I do not know how to find it. | I found in this forum good links to 3rd party API viewers. There is also the API-Guide, which give informations on Windows' API functions, and gives examples in Visual Basic on how to use them. The good point of these examples is that they gather the needed constants/structures at one point... Search TrackMouseEvent in it as a starting point, the example treats exactly the case we are discuting.
| toralf wrote: | | Instead of capturing the mouse, you may use a global timer that removes "WhichToolTip" every x seconds. | The given script already does that, but the hanging tooltip (until it is automatically dismissed) isn't very nice.
Last edited by PhiLho on Wed Feb 08, 2006 9:33 am; edited 3 times in total |
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue Feb 07, 2006 1:04 pm Post subject: |
|
|
I will post my combined code for info in the statusbar here, so you have all together.
What it does:
- It increases the size of the GUI and adds a statusbar, so that nothing is hidden
- Shows info in the statusbar when you move the mouse in the window
- if the mouse leaves the window it shows "outside", this is triggerd via OnMessage(9 and via a Timer as backup solution if window didn't get the message
It can be seen that the v-Label can't be used in this case for Text controls.
| Code: | Gui, 1:+Resize
Gui, 1:Add, Button, vBtn2, Test Button2
Gui, 1:Add, Edit, vEdtTest, This is a test
Gui, 1:Add, Text, vTxtTest, ... another test...
Gui, 1:Show, w400
BarHWND1 := SB_Segments("30,100,-1")
SB_Text(BarHWND1, 1, "OK?")
OnMessage(0x200, "WM_MOUSEMOVE")
OnMessage(0x2A2, "WM_NCMOUSELEAVE")
SetTimer, CheckIfMouseIsOutsideGui,250
Return
GuiSize:
SendMessage 5,0,0,,ahk_id %BarHWND1% ; 5 = WM_SIZE
Return
CheckIfMouseIsOutsideGui:
MouseGetPos,,,MouseOverWindow,
Gui, 1:+Lastfound
If (MouseOverWindow <> WinExist())
WM_NCMOUSELEAVE()
return
WM_NCMOUSELEAVE(){
global BarHWND1
SB_Text(BarHWND1, 2, "outside")
SB_Text(BarHWND1, 3, "")
}
WM_MOUSEMOVE(wParam, lParam, msg, hwnd){
global BarHWND1
MouseGetPos,MouseX,MouseY,, MouseOverControl
SB_Text(BarHWND1, 2, "x" MouseX " y" MouseY)
SB_Text(BarHWND1, 3, hwnd " - " msg " - " wParam " - " lParam " - " MouseOverControl " - " A_GuiControl)
}
SB_Segments(segs = -1, GuiID = 1){
Gui, %GuiID%:+Lastfound
WinGetPos, , , , GuiHeight
Gui, %GuiID%:Show, % "h" GuiHeight -10
BarHWND := DllCall("CreateStatusWindow", int, 0x50000000, str, "", UInt, WinExist(), UInt, 5555)
IfEqual segs,0, SetEnv segs,
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, text){
SendMessage 0x401,% seg-1,&text,,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 )
} |
_________________ Ciao
toralf  |
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Tue Feb 07, 2006 1:28 pm Post subject: |
|
|
one can even combine the two OnMessage() functions: | Code: | ;Statusbar Messages (e.g. like tips to controls)
OnMessage(0x200, "UpdateStatusBarText") ;WM_MOUSEMOVE
OnMessage(0x2a2, "UpdateStatusBarText") ;WM_NCMOUSELEAVE
SetTimer, CheckIfMouseIsOutsideGui,250
Return
CheckIfMouseIsOutsideGui:
MouseGetPos,,,MouseOverWindow,
Gui, 1:+Lastfound
If (MouseOverWindow <> WinExist())
UpdateStatusBarText("","","0x2a2","")
return
UpdateStatusBarText(wParam, lParam, msg, hwnd){
global BarHWND1
If (msg = 0x200){
MouseGetPos,MouseX,MouseY,, MouseOverControl
SB_Text(BarHWND1, 2, "x" MouseX " y" MouseY)
SB_Text(BarHWND1, 3, hwnd " - " msg " - " wParam " - " lParam " - " MouseOverControl " - " A_GuiControl)
}Else If (msg = 0x2a2){
SB_Text(BarHWND1, 2, "outside")
SB_Text(BarHWND1, 3, msg)
}
}
|
I wonder why I can't specify default values for wParam, lParam, msg and hwnd in UpdateStatusBarText()?!? When I do it (e.g. hwnd=1) the statusbar isn't updated. Chris, is this by design? _________________ Ciao
toralf  |
|
| Back to top |
|
 |
Chris Site Admin
Joined: 02 Mar 2004 Posts: 10467
|
Posted: Tue Feb 07, 2006 2:41 pm Post subject: |
|
|
| toralf wrote: | | ...why I can't specify default values for wParam, lParam, msg and hwnd in UpdateStatusBarText()?!? | It's because those values are always present, so having a default value wouldn't make sense unless you're calling the function both normally and via OnMessage. It didn't seem worth the code size to support that, which is documented: "Failure occurs when FunctionName ... has any ByRef or optional parameters."
| Quote: | | Chris, maybe [WM_NCMOUSELEAVE] could be added to the doc | Thanks; I've done so. |
|
| 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
|