Basically, I'm looking for a IsWindowMoving(HWND) Win32 API call. I need to know if the user is currently moving a window.
The window doesn't belong to me, so listening for WM_SYSCOMMAND / SC_MOVE or WM_MOVING isn't possible (I don't want to subclass or hook due to 32/64 interop).
You can do this with GetGUIThreadInfo - no hooking needed. Use GetWindowThreadProcessId to get the TID for your hwnd then check the GUITHREADINFO.flags and GUITHREADINFO.hwndMoveSize to see if your window is in a move / size loop.
If the window doesn't belong to you and you're not going to snoop messages, the best you can I think is get hold of a handle to that window. That limits you to whatever informational function calls exist which work on a handle. I know of no such call which can inform the user that the window is being moved.
You may be out of luck.
If you don't want to hook, subclass, or anything else like that, I think polling might be the easiest way left. Using GetWindowRect you can track the previous and current position and size of a window. Doing a delta will let you detect if the user is moving (or even resizing) the window. Since you are dealing with UI, there is no need to poll too quickly (even 2-5 times a second should be plenty).
Related
You can probably figure out why I am asking this question. Even if not, it's very simple.
My question is whether it is possible to detect the use of SetCursorPos() on one's own application, without scanning other running applications for any calls to this API.
For example, if I have my cursor in a window and I call SetCursorPos(), can this window in anyway know that the cursor placement is not directly from the mouse (raw input)?
I am not oblivious to the fact that you can 'know' whether a mouse input is raw simply by checking how the position alters; for example, if the position changes from 100(X) & 100(Y) to 500(X) and 500(Y), without moving through each individual location between these two, then with certainty, something has altered the mouse position.
If anyone of you know of a way to produce 'raw mouse input', without any application being able to tell the difference between the output from a function, and that from a mouse--if there is such a difference--then that'd suffice, too.
Of course, whenever I move my mouse, the operating system I am using detects this and then appropriately moves the cursor accordingly. In practice, I should be able to alter this low level functionality as to my will?
There is no way for a window to directly determine how the mouse was moved. External applications could be using SetCursorPos(), but they could also be using lower level functions like mouse_event() or SendInput() instead. By the time the notification reach the target window, the OS has already normalized the data and any source information is lost If you really needed to detect use of SetCursorPos() or other functions, you would have to directly hook into those functions in every running process. Alternatively, you might try registering for "Raw Input" via RegisterRawInputDevices() and see if you get a corresponding notification from the mouse hardware directy, assumine those simulating functions do not trigger Raw notifications as well.
I've just got a fresh device context (DC):
GetDC(someForeignHwnd)
Most normal people now want to paint on this. I don't. I want to display the context in my own program. Or duplicate, I wouldn't even mind the window I stole the context from beeing empty.
In my case, I want it in a TPanel in Delphi, but anything else helping me understanding goes.
Afterwards, I'll probably find the DC invalid by the time I get to display it.
My main problem is: Showing the content of another window in my own. But that isn't important. First of all, I want to know how these DC are of any use. Can I do something like the following?
Canvas.Draw(0, 0, MyNewDC);
The answer can be in Java, C, or Pascal. Is it just not possible or just a stupid idea?
While it's possible to use a device context that you retrieve via GetDC() as the SOURCE for BitBlt(), etc., you will likely not get the results that you're looking for. When you call GetDC() for a specific window, Windows essentially returns a device context for the screen, but with a clipping region set to exclude any portions of the screen where the window is not visible. For example, if there happens to be another window overlapping the source window, the portion of the source window that is covered is clipped from the device context. Therefore, you can only "retrieve" the bits that are actually visible.
You may have better luck sending a WM_PRINT or WM_PRINTCLIENT message to the window. However, not all windows respond to these messages, so this isn't a universal solution.
So yes, I find myself in the dubious position of implementing a SwitchToThisWindow call to force my window to the front. I agree, its not ideal, but its not always possible to argue against product "features" that others deem necessary.
Now, I consider SwitchToThisWindow to be a win over the AttachThreadInput hack to do a forced window switch as its less likely to deadlock, and should SwitchToThisWindow be removed, or cease to function I won't complain.
However, SwitchToThisWindow has the unfortunate side effect of pushing the current foreground window to the bottom of the z-order in addition to bringing the target window to the top when FALSE is passed for the fAltTab parameter, and not doing anything if TRUE is passed.
How can I avoid this 'push current active to z-bottom' behavior without resorting to AttachThreadInput?
Alternatively, MS can just remove AttachThreadInput as a viable workaround and I can just tell my manager that the impossible, is in fact, actually, impossible.
I don't know if this helps, but the only way i found out to bring my window to top reliably is to make the following 2 calls:
ShowWindow(myhwnd, SW_MINIMIZE);
ShowWindow(myhwnd, SW_RESTORE);
Obviously these calls only should be made, when your window currently is not the topmost one in order to avoid flickering. But this also should not have the side effect of bringing the current front window to the bottom of the z order.
When passing fAltTab=FALSE you are actually emulating Alt+Esc. So you could reverse this z-order change with SetWindowPos and its hWndInsertAfter after the SwitchToThisWindow call, but then you are back in ugly hacky-land IMHO.
The question is, do you really need keyboard focus?
Let me suggest another alternative:
If your window is minimized, restore it
Set your window to be topmost, when your window is activated remove the style again.
Call SetForegroundWindow to flash the taskbar button (Or FlashWindowEx)
This should avoid the scenario where a user is typing and ends up performing some action in your UI without even looking at the screen.
Edit:
HWND hwndFgnd=GetForegroundWindow();
SetWindowPos(hwnd,hwndFgnd,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
SetWindowPos(hwndFgnd,hwnd,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);
..will probably work if you don't want to set the topmost bit at any point (Even if your window is at the top of the z-order, you still can't legally get the focus with SetForegroundWindow)
This is a bad problem I faced too. See my solution here. It works both for Show() and ShowDialog().
I need to create a transparent overlay window, that goes above another window. The other window is from another vendor. And when the user drags that window mine needs to follow.
WS-CHILD seems like a nice idea but it cannot be combined with WS-EX-LAYERED, which I really need (for transparency). But I still can set a parent without using WS-CHILD.
Parenting does give my winproc notifications (WM-WINDOWPOSCHANGING), but only after dragging is complete, on mouse-up. To give a nice feeling i need to get those notifications (or for example WM-MOVE) continuosly while dragging.
I guess my problem is similar to docking, but the fine docking solution seen fx at CodeProjet uses WS-CHILD. ( http://www.codeproject.com/KB/toolbars/dockwnd.aspx )
I guess I could use polling but that is not what I am looking for. Also I could use ::SetWindowsHook(). But that is my final resort. I am hoping I have missed something trivial and that somebody can point me in a good direction.
Thanx
I know it is not your preferred solution, but I think you need to use a global mouse hook. Pass WH_MOUSE_LL to SetWindowsHookEx() and do nothing in the default case of your low-level mouse proc. But when you get the WM_WINDOWPOSCHANGING notification, start tracking the mouse movements and making appropriate calls to MoveWindow() or whatever.
I use a LayeredWindow for that and set the other window as parent.
This is the code I used for that:
::SetWindowLong(GetHwnd(), GWL_EXSTYLE, GetWindowLong(GetHwnd(), GWL_EXSTYLE) |WS_EX_LAYERED);
::SetLayeredWindowAttributes(GetHwnd(), RGB(255,0,255), 255, LWA_COLORKEY | LWA_ALPHA);
::SetWindowLongPtr(GetHwnd(),GWLP_HWNDPARENT,(long)GetParentHWND());
::SetWindowPos(hndOtherWindow, hndOverlayWinow, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |SWP_NOACTIVATE);
It works for my purposes. There's only one problem left: If my overlaying window loses the focus I want to set the focus, or activate the other window. Do you have an idea?
How about WM_MOVING message? You may try intercepting this message and move your window accordingly.
If you want to know when a window in another process is being moved or sized, you need to install a hook,catch the WM_MOVING and WM_SIZING messages and reflect those messages back to your controller process. Sorry it's not the answer you want! I don't blame you for wanting to avoid cross process hooks, its a bit of a pain...
In Windows, is it possible to set window A such that it is always on top of window B, yet allow other windows to work as normal and appear over the top of both, when active.
In other words, I want a parent-child relationship between two windows. Can this be done without making window A a child of window B, MDI-style? Window B isn't mine (Internet Explorer), and screws my dialog A's graphics up when I try to achieve this with SetParent.
I thought I'd cracked it with this idea from an MSDN forum post, but alas windows A is still always on top of everything, not just window B.
// Place window A on top
SetWindowPos(hWndWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
// Place window B underneath it
SetWindowPos(hWndParent, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
Is it possible?
Wouldn't creating an ownership relationship do the trick?
SetWindowLong(hwndChild, GWL_HWNDPARENT, hwndOwner)
The windows can be in different processes and you can call this from any process. This will ensure that the child window is always above the owner window. This is different than SetParent which actually creates a Parent / Child relationship. Read through this article (its from 1993 but still mostly correct) to see the distinction between ownership and parenting.
When your window's Z-order (or size or position) is changing, it should receive a WM_WINDOWPOSCHANGING message. If you process that message, you have an opportunity to modify the final Z-order (or size or position) to which the window is moved.
To illustrate, in hWndA's window procedure:
case WM_WINDOWPOSCHANGING:
DefWindowProc(hWnd, msg, wParam, lParam);
WINDOWPOS *p = (WINDOWPOS*)lParam;
p->hwndInsertAfter = hWndB;
p->flags &= ~SWP_NOZORDER;
return 0;
should insert hWndA after hWndB in the Z-order any time hWndA's position changes.
Until Vista, one way to do it would have been to use SetWindowsHookEx, and hook the WH_CBT or WH_CALLWNDPROC hook, and then take appropriate action when you detect the Z order changing. However this doesn't work with Vista (as far as I can tell from googling).
The only other solution I can think of is to set up a timer to fire every few seconds, and then when you receive a WM_TIMER, you interrogate the system using GetNextWindow to find out which window is behind yours. If it's not IE, then call SetWindowPos to position your window above IE (I assume you have a HWND for the IE window you care about - remember there can be multiple IE windows).
This will cause problems if people try to bring your window to the front - it will flip back to being just above IE. In this case, in your code you could handle WM_ACTIVATE and try to change the Z-order of IE's window so it's below your window (call SetWindowPos to move IE's window so it's above the window that is currently below your window). This solution may be fraught with problems as Windows may try to prevent you messing with the windows of another process, for security reasons. On the other hand, the MSDN docs for SetWindowPos don't explicitly mention that you can't manipulate the windows of another process. There may be obscure limitations though.
Even with this timer hack, you're going to effectively have a busy-waiting loop in your app (with the frequent WM_TIMER messages) and this is generally a bad thing to do, especially for battery life of laptops etc. (because you prevent the CPU from entering a sleep state, and so on).
I'd say there's no good way of doing this, and anything you're likely to get working will be brittle and cause problems. I strongly recommend not trying to do it. Is it possible to make your program into some kind of plug-in or toolbar for IE instead?
NB Be particularly aware that SetWindowsHookEx imposes a performance penalty at a system-wide level if you go down this route.
Maurice's answer is the best out of what's here but is missing an important step. When you call show on your window that you want as the overlay, you need to call the show method that has the parameter. You'll need to define a class that implements the IWin32Window interface and just make a new instance of that. The only thing that interface cares about is the Handle so just set that to the handle of the IE window and it should work pretty well
If the parent-child relationship is made by yourself with the SetWindowPos() function, your desire can be implemented.
Can you access the Z-order of the windows?
I cannot recall the default z-order of windows, but I think it is 1. You might be able to set IE to a -1 and your app to 0.
Try this:
// Place window A on top of window B
SetWindowPos(hWndA, hWndB, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
The second window handle parameter specifies the next window down in the Z order.
Note this doesn't actually change the window parent-child relationships - but you can simulate it.