Page 1 of 1

Movable ToolTip

Posted: 01 Jan 2018, 09:38
by rommmcek
Lately I'm often using ToolTip to display data, enlarged with ToolTipAll to be readable from a distance.
Bigger ToolTip is more likely to cover some important part of the screen, so I needed it to be movable.

Code: Select all

#NoEnv
OnMessage(0x201, "WM_LBUTTONDOWN")

Global tClass:="SysShadow,Alternate Owner,tooltips_class32,DummyDWMListenerWindow,EdgeUiInputTopWndClass,ApplicationFrameWindow,TaskManagerWindow,Qt5QWindowIcon,Windows.UI.Core.CoreWindow,WorkerW,Progman,Internet Explorer_Hidden,Shell_TrayWnd" ; HH Parent

WinGetActiveTitle, aWin
ToolTip,
(
Lorem ipsum dolor sit amet, consectetur adipiscing
elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore
eu fugiat nulla pariatur. Excepteur sint occaecat
cupidatat non proident, sunt in culpa qui officia
deserunt mollit anim id est laborum.
), 0, 0
return

WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) {
	PostMessage, 0xA1, 2 ; WM_NCLBUTTONDOWN
	KeyWait, LButton, U
	Loop { ; adapted from https://autohotkey.com/board/topic/32171-how-to-get-the-id-of-the-next-or-previous-window-in-z-order/
        ; GetWindow() returns a decimal value, so we have to convert it to hex
        ; GetWindow() processes even hidden windows, so we move down the z oder until the next visible window is found
        hwnd := Format("0x{:x}", DllCall("GetWindow", UPtr,hwnd, UInt,2) ) ; 2 = GW_HWNDNEXT
        if DllCall("IsWindowVisible", UPtr,hwnd) {
            WinGet, Ex, ExStyle, ahk_id %hwnd%
            ;if ( IsWindowCloaked(hwnd) || Ex & (0x8 | 0x80 | 0x8000000) ) ;WS_EX_TOPMOST, WS_EX_TOOLWINDOW, WS_EX_NOACTIVATE
            if (IsWindowCloaked(hwnd) || Ex & 0x8000088) ;WS_EX_TOPMOST, WS_EX_TOOLWINDOW, WS_EX_NOACTIVATE
		Continue
            WinGetClass, cClass, ahk_id %hwnd%
            if InStr(tClass, cClass, 1) ; if cClass in %tClass%
                Continue
            else break
        }
    }   WinActivate, ahk_id %hwnd%
}

IsWindowCloaked(hwnd) {
    return DllCall("dwmapi\DwmGetWindowAttribute", "ptr",hwnd, "int",14, "int*",cloaked, "int",4) >= 0
        && cloaked
}

Esc::exitapp
First Post

Re: Movable ToolTip

Posted: 01 Jan 2018, 14:22
by Delta Pythagorean
Huh. Neat.

Re: Movable ToolTip

Posted: 02 Jan 2018, 16:13
by burque505
:thumbup:
Very nice.
Regards,
burque505

Re: Movable ToolTip

Posted: 12 Oct 2019, 20:39
by lexikos
I was looking for any information about the DummyDWMListenerWindow window class (not specifically on the forum) and found this.

This list of window class checks could be optimized considerably. You could:
  • Use a window group. AutoHotkey looping through the group internally should be much more efficient than evaluating a long list of sub-expressions.
  • Use if var in MatchList or even InStr.
  • Use an associative array with class names as keys (however, I'm fairly certain class names are case-sensitive and keys are not).
Actually, you might like to know that some of those windows can be excluded more efficiently: several of them are "cloaked" rather than hidden. Some of them can (also) be excluded via the presence of the WS_EX_TOOLWINDOW ExStyle (which prevents them from having a taskbar button unless WS_EX_APPWINDOW is present) or WS_EX_NOACTIVATE.

Re: Movable ToolTip

Posted: 13 Oct 2019, 11:18
by elModo7
Might find some use for it, thanks for sharing!

Re: Movable ToolTip

Posted: 15 Oct 2019, 02:19
by rommmcek
Thanks for suggestions! First part is here not so important (accept for the embellishing the code), but the second part is very useful (not finished yet), even if there was some strange (seems no where documented) ExStyle to be found (thanks to svArtist's work).
Anyway, I posted it in OP.

Re: Movable ToolTip

Posted: 15 Oct 2019, 03:55
by lexikos

Code: Select all

IsWindowCloaked(hwnd) {
    return DllCall("dwmapi\DwmGetWindowAttribute", "ptr",hwnd, "int",14, "int*",cloaked, "int",4) ;>= 0
        ;&& cloaked
}
Your modified version of the function will not tell you if the window is cloaked. It will return 0 (success) on Windows 8 and later if the HWND is valid, or a negative value otherwise.
if (Ex = 0x108) ; || IsWindowCloaked || Ex = 0x80 || Ex = 0x8000000) ;0x108???, WS_EX_TOOLWINDOW, WS_EX_NOACTIVATE
Styles are a combination of bit flags, and can be tested with bitwise-and (e.g. (style & 0x100)). You should rarely, if ever, compare the style value directly with the equality operator. 0x108 is a combination of the very much documented styles WS_EX_WINDOWEDGE and WS_EX_TOPMOST.

Why post these changes before they are finished?

Re: Movable ToolTip

Posted: 15 Oct 2019, 12:13
by rommmcek
Thanks again!
- I modified your function because I did not understand it converts retrieved "cloaked" value to true or false, what I believe now.
- I noticed in msdn that some styles are defined multiple times, but I mixed up bitwise "add" with RegEx "or" (what a blunder!)
- I posted the code because it prevents e.g. Window spy to pop up even if it was minimized.

Now the code is finished, but not extensively tested yet! (Update in OP)

Re: Movable ToolTip

Posted: 15 Oct 2019, 12:42
by guest3456
might not be finished just yet ;)
rommmcek wrote:
01 Jan 2018, 09:38

Code: Select all

if (Ex&0x8=0x8 || IsWindowCloaked || Ex&0x80=0x80 || Ex&0x8000000=0x8000000)
i'm not sure if those bitwise ANDs should also have = operators, at least i've never seen it done like that before

and it doesn't look like you're calling the function either. shouldn't it be:

Code: Select all

if (Ex&0x8 || IsWindowCloaked(hwnd) || ...

Re: Movable ToolTip

Posted: 15 Oct 2019, 15:12
by rommmcek
Thank You!
First fault was due to very little experience, but tested and it was working.
Second was pure typo and after update just being not attentive when doing copy paste.
Updated OP.

Off Topic:
Now I'll try to cloak a window, and hope, you'll be still around to commet my probably not working attempt...
Looks like Dll is dealing with structures, from which I can barely read, but not write into it...
Spoiler

Re: Movable ToolTip

Posted: 15 Oct 2019, 20:21
by guest3456
your code above doesn't work for me on win10. does it work for you? the gui is still visible for me.

the only example i could find from microsoft on how to use this is here:
https://docs.microsoft.com/en-us/windows/win32/directcomp/how-to--animate-the-bitmap-of-a-layered-child-window

Code: Select all

BOOL fCloak = TRUE;
DwmSetWindowAttribute(pDemoApp->m_hwndLayeredChild,
    DWMWA_CLOAK,
    &fCloak,
    sizeof(fCloak));
DWMWA_CLOAK is 13 so that is correct, then i guess we need to pass a boolean true/false, but MSDN for SetWindowAttribute says we need to pass a pointer. you passed 1, but probably we need to pass the address of a var containing 1.

this works for me:

Code: Select all

SetWindowCloaked(hwnd) {
  static DWMWA_CLOAK := 13
  myBoolSize := VarSetCapacity(myBool, 4)
  ;msgbox myBoolSize=%myBoolSize%     ; shows 6 for me, not 4, strange
  myBool := true
  Return DllCall("Dwmapi\DwmSetWindowAttribute", Ptr, hwnd, UInt, DWMWA_CLOAK, UInt, &myBool, UInt, myBoolSize)
}

Re: Movable ToolTip

Posted: 16 Oct 2019, 03:45
by lexikos
guest3456 wrote:i'm not sure if those bitwise ANDs should also have = operators, at least i've never seen it done like that before
It may be done in languages where int is not implicitly convertible to bool, or in other languages just for clarity. One may also want to test whether multiple bits are all set or all not set, or some specific combination. For instance, (Ex & 0x8000088) = 0x8000088 would tell us whether all three of the styles 0x8000000, 0x80 and 0x8 are set. In this case we probably just want to know if any of the three are set, so (Ex & 0x8000088) will suffice (it will be non-zero if any of the three styles are set, and zero if none of them are set). You can also write (Ex & 0x8000088) != 0 for clarity (or to get a proper boolean result), or (Ex & 0x8000088) = 0 if you want to know that none of them are set.

I recently used this code to determine whether a window is either hidden (lacks WS_VISIBLE) or disabled (has WS_DISABLED):

Code: Select all

if ((style & (WS_VISIBLE | WS_DISABLED)) != WS_VISIBLE)
Spoiler

Re: Movable ToolTip

Posted: 16 Oct 2019, 07:53
by rommmcek
OMG! This was very instructive to me!
@guest3456 No, my code didn't work for me (Win10). You probably interpreted the struck line as a negation of the second part of the sentence. In fact it was vice versa! I.e. I gave up.
I was both, so near to success and to the other side so far away! As lexikos explained, sometimes DllCall() requires profound understanding of the struct. Experienced guys like you can get around it (your code works) others (like me) obviously not!
Here is my final "cloak" example
For me it is important to learn and that the code works (now tested with cloaked window too)!
Mistery revealed thanks to svArtist with a "little" help of lexikos and active interest of guest3456!
Thanks to all of you!

P.s.: Updated OP, (Edit: Fixed unfortunate copy paste typo in OP; Edit2: Removing HH Parent from the tClass list in the OP)