Is it possible to determine if a window has a scrolling function/interaction in AutoHotKey? - windows

For the purpose of putting more actions on fewer buttons I was hoping to detect if a window has scrolling functions. For example when a pop-up is asking you if you want to save something or not it tends to default to No. That window does not have any functionality tied to the mouse wheel action. In that scope I was planning to have the mouse wheel up and down input up or down directions. Maybe there is a way to detect if the window has scrolling enabled? Or maybe there is another work-around such as that pop-up window having a specific windows class?

Look at the GetScrollBarInfo function in the answer here How I can check if a Window has visible scrollbars using his HWND? for some useful info, but in my view, easiest is to capture window classes and fire mouse wheels accordingly, just like the example in the help for #if except you will need a correct WinTitle (use class of pop up) instead of identifying the Taskbar, and you will send tab and alt+tab in your mousewheels instead of the volume controls:
#If MouseIsOver("ahk_class Shell_TrayWnd")
WheelUp::Send {Volume_Up}
WheelDown::Send {Volume_Down}
MouseIsOver(WinTitle) {
MouseGetPos,,, Win
return WinExist(WinTitle . " ahk_id " . Win)
}
https://www.autohotkey.com/docs/commands/_If.htm
Hth,

Related

How can i draw to or add a custom button to every window of all applications?

I have seen several tools adding a custom button and/or drawing on the title bar of all windows of all applications in Windows. How is that done?
Extra points for an example in Delphi.
EDIT:
I found something for dotNET that does this:
http://www.thecodeking.co.uk/2007/09/adding-caption-buttons-to-non-client.html#.VdmioEDenqQ
How I see this job:
First of all we should be able to paint this button on the our own window caption. This procedure will be used later
This part of the program enumerates the active and visible windows
This part of the program using injection attach our dll to enumerated windows
From injected dll we can draw the button on the window caption
Inside this dll we should process the click on the button
We should have mechanism to send result to our main program
I haven't done this, so the following is what I would investigate if I were to try:
For each application / each top-level window:
Create a floating window and position it over the title bar wherever you want it to sit. Set up the parent / child relationship, but this window is part of your own process. (There are occasionally problems parenting a window from one process to one from another process, but try. I'd avoid injecting into other processes if possible.)
You can investigate the window flags to see if the window has a title bar (ie if you should add a button) via GetWindowLong with GWL_STYLE looking for WS_CAPTION. The same call will also let you see the type of caption / frame, which you can combine with GetSystemMetrics with, eg, SM_CYDLGFRAME to figure out the right size for your button on this specific window's title bar.
This window is now your button: paint, handle clicks etc as appropriate.
Make it a non-focusable window so that clicks to it don't take focus away from the window is is on the title bar of. You don't want clicking it to make the title bar change colour, for example. Do this by setting the WS_EX_NOACTIVATE window flag, something like: SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) orWS_EX_NOACTIVATE).
The main problem is to keep it positioned correctly when the window moves, is resized, etc. To do this, install a hook for the system move events. You can also hook minimize and restore via EVENT_SYSTEM_MINIMIZESTART and EVENT_SYSTEM_MINIMIZEEND. This will allow you to keep track of all windows moving around onscreen, such that you can adjust the button-window position if necessary.
That gives you a window which you can paint as a button (and respond to clicks etc), that visually is "attached" to other windows so it stays in the same place as the user drags the title bar, minimizes or maximises the app, etc, and that is in your own process without cross-process problems.

X11: input focus for popups

For some fun and self-education, I'm tinkering with writing my own X11 toolkit. Here's something that's stumping me.
I have a traditional combo box display element, a typical combo box with a dropdown popup list, like all popular toolkits have.
For the dropdown popup list, I'm creating a new window, a child of the root window, appropriately positioned below the main combo-box display element.
The dropdown popup list is a window in its own full right, that implements keyboard-based navigation, to select the individual entries in the dropdown list.
So, I'm using SetInputFocus to set the input focus to the popup after it opens.
What I find is that when I do that, the window manager then redraws the frame of the main window to indicate that it no longer has input focus. Which is technically true, but I don't see the same results with the more mainstream toolkits, where, in the comparable situation, the main window's frame shows that it still has input focus.
For the pop-up window, in addition to setting override-redirect, I'm also doing everything I can think of, to tell the window manager what's going on: setting the window group leader ID in the popup window's WM_HINTS, setting WM_TRANSIENT_FOR, and setting _NET_WM_WINDOW_TYPE to _NET_WM_WINDOW_TYPE_COMBO; none of that seems to work (I verified that the properties are approriately set, via xprop).
It seems like I have to keep the input focus in the combo box window, and forward keypress and keyrelease events to the display elements in the dropdown popup, which feels clunky. Am I overlooking some property that would tell the window manager that the popup's input focus is linked to the main window's (besides the ones that I've mentioned), that would keep the main window's frame drawn to show that it has input focus, when the input focus is actually in the popup?
Most X11 override-redirect exclusive popup windows (menus, combo boxes, ...) grab the keyboard and/or pointer with either passive or active grab.
See XGrabKey, XGrabKeyboard, XGrabButton, XGrabPointer in the X11 programming manual.
Or maybe don't, because the manual is totally unclear about what the heck these functions are and how they can be used. Search the interwebs for usage examples, probably in other widget libraries. Unfortunately I don't know of a simple informative example offhand.
It is not necessary to call XSetInputFocus at all because all keyboard and/or pointer events are reported to the grabbing clients.

How to stop event propagation despite WS_EX_NOACTIVATE?

I have a semi-transparent form (using AlphaBlend) that acts as an overlay. For the user to still be able to interact with the window below I have set WS_EX_NOACTIVATE on my form so all right and left clicks go through to the other window.
However I have a few clickable labels on my form. Clicking those and performing the appropriate action works fine since despite the WS_EX_NOACTIVATE flag the OnClick methods are called, but the click will (obviousely) also propagate to the other window, which I do not want in this case.
So, does anyone know how to "stop" the click being sent through to the window below in case I already handled it in my form ? Basically I would like being able to chose whether the click "belongs to me" and does not get propagated or whether the window below mine receives it.
As Rob explained, WS_EX_NOACTIVATE is not relevant here. Most likely you used WS_EX_TRANSPARENT and that made your window transparent to mouse clicks.
To get finer grained control of mouse click transparency, handle the WM_NCHITTEST message in your top level window. Return HTTRANSPARENT for regions that you want to be "click through". Otherwise return, for example, HTCLIENT.
Wm_ex_NoActivate should be irrelevant here. That just controls whether your window receives the input focus. Indeed, if you start with a scratch program and do nothing but change the extended window style, you'll see that when you click within the bounds of that program's window, the clicks are handled in the usual way, except that the window is never activated; programs behind that window do not receive any click events.
Therefore, to make your label controls eat click events instead of forwarding them to the windows behind them, you need to find out what you did to make them start forwarding those messages and simply stop doing that, whatever that is.

Hiding mouse cursor in multiscreen setup

I am trying to hide the mouse cursor using win32 API ShowCursor(FALSE), but on a multiscreen setup when the mouse gets to the other screen I don't get any mouse updates in windows.
Is there any way I can prevent this?
This is for a fullscreen video game and I don't seem to find any windows api that can do something like this.
From what I understand, your problem is not in hiding the mouse cursor, but in constraining it to your window?
In that case, the ClipCursor function should do the job.
{
RECT windowRect;
GetWindowRect(hWnd, &windowRect);
ClipCursor(&windowRect);
}
For a border-less full-screen window, it should be fine to do that once. You would need to repeat that step if your window's position or size ever changes or the window loses focus.
For game programming, there are likely better methods though, such as DirectInput, which provides an exclusive mouse handling mode (tutorials available) and does all that for you on a lower-level basis.
There are some discussions available about the different ways to handle this, for instance this one on the MSDN forums.
If, on the other hand, you want the cursor to be able to leave your window, and only hide it while it's over your window, you should handle the WM_SETCURSOR message and use SetCursor to hide the cursor.
case WM_SETCURSOR:
SetCursor(NULL);
return TRUE;

How to get the foreground window on Windows?

Windows API has a method called GetForegroundWindow.
But it considers the Desktop as a foreground window when you click on it.
We all know that when it happens the previous foreground window isn't superposed by it.
How to get the real foreground window handle?
I think you're overengineering your solution. If your application window is not the foreground window when you receive an update, then flash the window. The point of flashing is to capture the user's attention, and you have no way to determine if you have their attention programmatically.
It seems like what you really want to know is: "Is the portion of my window that changes currently visible to the user?" That's quite a complex question to answer, and even if you answer it correctly, you have no way to know if the user will notice the change.
Both the "desktop" (Explorers desktop listview on top of the real desktop window) and the taskbar are real windows where the user might be "working" (Tab'ing around, using menus etc)
If you want to find the "real" foreground window that bad you have find it yourself, your best bet is going for the window at the top of the z-order, maybe something like:
... enumfunc(hwnd,...)
{
if (GetClassName(hwnd)!= "Shell_TrayWnd")
{
if (IsWindowEnabled(hwnd) && IsWindowVisible(hwnd) && GetWindow(hwnd,GW_OWNER)==NULL)
{
DoSomethingWithRealForegroundWindow(hwnd)
return FALSE
}
}
}
EnumWindows(enumfunc,0)
TaskSwitchXP is a open source alt-tab replacement, it probably has a better algorithm that you can use...

Resources