How to set window top of any topmost window? - c++

I prefer set Taskbar to hide, but still want show clock all the time. I make a small clock (80x41px) lay at bottom-right corner of screen. I make it Topmost [edit: with Timer]:
SetWindowPos(hwnd, HWND_TOPMOST, r.right - width, r.bottom - height, 0, 0, SWP_NOSIZE);
// r is my window's rect
When I click to TaskBar, my clock still on top of it. But when I play some fullscreen game it hide my clock. May be they use a special method.
My question is there is any way to show my window on top of every top-most window, even active top-most window? I don't need my app get keyboard or mouse input, just lay there to display time.
I know my question is quite specific as I write this clock for myself. I searched google but don't find any web pages can solve this (this question ask the same, but it want to get mouse event, and the answer say no, but I hope a window that doesn't need input maybe a special case).
Any help would be appreciated!
Edit
Incase impossible, How about draw a rectangle on top of screen? As I don't need get input, this maybe a replace solution. Is that possible?

It's not very elegant, but I've solved this before by constantly setting the window to HWND_TOPMOST on a one-second timer.

Is it within the own process?
As a general rule, a process can only expect to set the foreground window if that process is already the foreground process. (Microsoft documents the restrictions in the SetForegroundWindow() MSDN entry.)

Related

What is the difference of MouseInputs and KeyInputs (To get the window in the foreground)

Good day everybody.
It is so that one with SendInputs to send keys only has to call SetForegroundWindow() in order to bring the window into the foreground. This also works without problems.
Now it is so that one could think that with the mouse inputs the same procedure can be applied. But this was not possible. First you had to use the function AttachThreadInput() to get the window really in the foreground.
It is very confusing that it works with keys simply but with the mouse so cumbersome to be done. Can someone explain to me briefly why this is so?
Sorry for the title and the bad english, unfortunately, no other words have occurred to me.
Since it is too much code, I simply show the relevant for my question.
Keys:
if(SetForegroundWindow(window[id]))
{
//SENDINPUT for key, works without any problems. (Not with Mouse)
}
Mouse:
AttachThreadInput(dwCurID, dwMyID, TRUE);
SetWindowPos(window, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
SetWindowPos(window, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
SetForegroundWindow(window);
AttachThreadInput(dwCurID, dwMyID, FALSE);
//The Window is now on foreground, now use SendInput for Mouse. This way works
So I wonder really why not both works in the way of the key example. So the reason I know since the window is not really in the foreground and this is necessary for the MouseInputs. One might think that it would also be necessary for the Keyevents. Hence my confusion.
I wish you happy day!
If I understand the question correctly ... Yes, the keyboard and mouse input models are different.
But I think the real issue is that calling SetForegroundWindow on the window of another application is complicated. Windows has a long list of rules of when you can and cannot set the foreground window. (The intent is to make it hard for programs to push their windows in the user's face when the user wants to do something else.) What seems to work when you're testing might not actually work reliably in real life. For example, some of the rules depend on whether the current foreground window is owned by a process attached to a debugger. My guess is that you got lucky when you tested the keyboard case and you found a way around the rules when you worked on the mouse case.
Keyboard input is directed to the window with the keyboard focus. The window with keyboard focus is either the foreground window or a child of the foreground window. So to direct keyboard messages with SendInput to a particular application, you only have to make sure it has focus, which you can do by bringing its window to the foreground.
If you succeed, then the window you just brought to the foreground will make sure the window focus is set appropriate (e.g., by calling SetFocus on one of its children). If you were to try to call SetFocus yourself, on a window that belonged to another thread or process, you would first have to use AttachThreadInput just as you've done in the case for the mouse. (This is explained in SetFocus.)
Mouse input is (generally) directed to the window under the mouse, even if that window is not the foreground window. The big exception is when a window has "captured" the mouse, then all mouse input goes to that window, even if the mouse is over a different window. But the other exception is also the mouse scroll wheel messages, which seem to follow the window with keyboard focus.
I'm not entirely sure why (or whether) it's important to set the foreground window to send mouse input, unless it's because you're trying to make sure it gets the mouse scroll wheel messages.

Create a window using the WS_EX_NOACTIVATE flag ,but it can't be dragged until I release the mouse

I have created a window using the WS_EX_NOACTIVATE flag and it works great as far as not taking focus when you click the window. However when I drag the window or try to resize it, it doesn't redraw the window as your are moving and resizing it, only at the very end once you release the mouse button. Is there a way around this? I would like to see the window as I am resizing it. I have searched many documents, but I still don't find the resolution...
If you need a window that doesn't take focus when clicked, but can still be interacted with, you need to handle the WM_MOUSEACTIVATE, and return MA_NOACTIVATE.
Additional information and fully working sample code has been published by Raymond Chen. See How can I have a window that rejects activation but still receives pointer input?
It's a Windows bug. You need to call SetWindowPos(hwnd, 0, x, y, width, height, 0) on WM_MOVING. The coordinates to set are given to you in lParam which is a RECT*.
Note that doing this will activate the owned window and deactivate the owner, which is not what you want (and SWP_NOACTIVATE has no effect either).
To avoid that, you need to set WS_CHILD on the owned window. But set it after you created the window, via SetWindowLong(), otherwise your owned window will get clipped, like any child window.
And, as you probably already figured out, this only works for windows with WS_EX_TOOLWINDOW ex style. I wasn't able to make the owned window stay deactivated with any other style combination that doesn't include WS_EX_TOOLWINDOW.
That's winapi for you :(

Draw moving icon that is top most all the time like mouse cursor and work for full screen apps

I need to draw an icon that moves approximately in sync with mouse cursor and is always on top of all windows.
OS: Windows 7
I have a solutions that work to some extend by drawing my icon in a top most transparent window. There are some major drawbacks in this solution since that top most window interferes with other top most windows and some full screen apps do not work correctly. Examples are start menu and task bar that will overlay my window if I do not regulary set it to be top most. For some full screen applications performance of updating position of window with icon hugely drops and it does not follow mouse smoothly.
There is another method that I came across where an icon is drawn directly to the device context of desktop Draw mouse pointer icon?. This solution has a drawback that there seems to be no good way of how to remove "trail", especially if desktop content changes quickly.
So my question: is there an ultimate solution that does not have the above mentioned problems?
Is it possible to draw above all windows in the "layer" of mouse cursor? Or make a second mouse cursor with my custom icon that I will control (I know that widows can display two independently controlled mouse cursors like CPNMouse)?
Can someone point me to the right direction?
Thanks!
Use a top-most window with transparency set via WS_EX_LAYERED / UpdateLayeredWindow.
If you set the WS_EX_TRANSPARENT style as well then the window won't intercept mouse input.

Creating a Transparent Child window on top of non-transparent Parent Window (win32)

I have a program which is not written by me. I dont have its source and the developer of that program is developing independently. He gives me the HWND and HINSTANCE handles of that program.
I have created a child window ON his window, using win32 api.
First thing I need is to make this child window have transparency on some area and opaque on other area(like a Heads up display(HUD) for a game), so that the user may see things in both windows.
The second thing that I need is to direct all the input to the parent window. My child window needs no input.
I know that WS_EX_TRANSPARENT only makes the child draw at the end like in painters algorithm.
I cant use WS_EX_LAYERED because its a child window.
p.s.
I have looked everywhere but didn't find any solution though there were similar questions around the internet.
Actually this is a HUD like thing for that game. I can't draw directly on parent window because of the complexity with multi-threads any many other reasons.
-- EDIT ---------------------------
I am still working on it. I am trying different ways with what you all suggested. Is there a way to combine directX and SetWindowRgn() function or directx with BitBlt() function? I think that will do the trick. Currently I am testing all the stuff as a child window and a Layered window.
You can use WS_EX_LAYERED for child windows from Windows 8 and up.
To support earlier versions of windows, just create a level layered window as a popup (With no chrome) and ensure its positioned over the game window at the appropriate location. Most users don't move the windows they are working with all the time, so, while you will need to monitor for the parent window moving, and re position the HUD, this should not be a show stopper.
Not taking focus (in the case of being a child window) or activation (in the case of being a popup) is more interesting, but still quite do-able:- The operating system does not actually automatically assign either focus, or activation, to a clicked window - the Windows WindowProc always takes focus, or activation, by calling SetFocus, or some variant of SetActiveWindow or SetForegroundWindow on itself. The important thing here is, if you consume all mouse and non client mouse messages without passing them on to DefWindowProc, your HUD will never steal activation or keyboard focus from the Game window as a result of a click.
As a popup window, or a window on another thread, you might have to manually handle any mouse messages that your window proc does get, and post them to the game window. Otherwise, responding to WM_NCHITTEST with HTTRANSPARENT (a similar effect to that which WS_EX_TRANSPARENT achieves) can get the system to keep on passing the mouse message down the stack until it finds a target.
OK friends, finally I did some crazy things to make it happen. but its not very efficient, like using DirectX directly for drawing.
What I dis:
Used (WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_ TOOLWINDOW) and () on CreateWindowEx
After creating the window, removed (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE) from window styles, and also removed (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE | WS_EX_APPWINDOW) from extended window styles.
This gives me a window with no borders and its also now shown in the taskbar. also the hittest is passed to whatever that is behind my window.
Subclassed the window procedure of the other window and got the
WM_CLOSE,WM_DESTROY, to send the WM_CLOSE or WM_DESTROY respectively to my window
WM_SIZE,WM_MOVE, to resize and move my window according to the other window
WM_LBUTTONUP,WM_RBUTTONUP,WM_MBUTTONUP, to make my window brought to the top, and still keep focus on the other window, so that my window doesn't get hidden behind the other window
Made the DirectX device have two passes:
In the first pass it draws all the elements in black on top of a white background and copy the backbuffer data to an another surface (so it give a binary image of black & white).
In the second pass it draws the things normally.
Another thread is created to keep making the window transparency by reading that black & white surface, using the SetWindowRgn() function.
This is working perfectly, the only thing is it's not very good at making things transparent.
And the other issue is giving alpha blending to the drawn objects.
But you can easily set the total alpha (transparency) using the SetLayeredWindowAttributes() function.
Thanks for all the help you guys gave, all the things you guys told me was used and they guided me, as you can see. :)
The sad thing is we decided not to use this method because of efficiency problems :(
But I learned a lot of things, and it was an awesome experience. And that's all that matters to me :)
Thank You :)
You can make a hole in the parent window using SetWindowRgn.
Also, just because it is not your window doesn't mean you can't make it a layered window.
http://msdn.microsoft.com/en-us/library/ms997507.aspx
Finally, you can take control of another window by using subclassing - essentially you substitute your Wndproc in place of theirs, to handle the messages you wish to handle, then pass the remainder to their original wndproc.

Can I change the thickness of the border of a window with MFC?

Normally, the thickness of a window is 4 pixels, which can be retrieved by GetSystemMetrics method. Can I change its value, for example 2 pixels?
Thank you very much!
Simple answer: No. Not for a specific window.
Complicated answer: The border is drawn as part of the "non-client" region of the window. This is all handled (under the hood) by the default processing (i.e. DefWindowProc), along with the caption, minimize, maximize buttons, etc. You can override this by handling the WM_NCPAINT message. You'll then be responsible for drawing the entire non-client area of your window. You'll also want to handle the WM_NCCALCSIZE message, so that Windows knows how much of the remaining space to give to your client area.
Alternatively, you can set the border style of your window to none. This will allow Windows to draw the caption for you, although it'll probably look slightly different. Unfortunately, by doing this, you lose the drag-to-resize functionality. For that, you'll need to handle the WM_NCHITTEST message.