I have my own custom painted caption bar for a window. I have also painted a bitmap on this bar which I want to know when someone hovers over it with the mouse cursor. I have handled the WM_NCMOUSEMOVE message but this seems to only be triggered over the borders and not my caption area itself.
How can I detect when the mouse is over a certain area of the caption bar?
This is with Visual C++ 2010.
Update:
I have worked out the problem to an extent. I (deliberately) do not have the WS_CAPTION style set on the window and instead I handle the WM_NCCALCSIZE and manually adjust the size of the non-client area - shifting it down by 20 pixels in this case. This means that the area that I am "forcing" as a non-client area does not get WM_NCMOUSEMOVE messages but neither does it get WM_MOUSEMOVE messages either. One way round it is to force the WM_CAPTION style, get rid of my custom code on WM_NCCALCSIZE but this isn't ideal. Is there a way round it?
Update2:
It is the same problem with WM_NCHITTEST messages. The area does not get these triggered unless I have WS_CAPTION style set which I don't want. Also it is somehow affecting the client area in that it no longer gets WM_LBUTTONDOWN messages.
I am not quite positive what you mean, but I think you are saying you want to check for a certain section of the caption bar being moused over. if so, then maybe try tracking window size and position, and then check to see if, relative to your window position and size, that section of the bar would be moused over (in pixels). This is the only way I can think of that doesn't use OS specific functions, which I try my best to avoid.
Related
It seems that my window is flickering whenever I move and window and resize at the same time. This usually occurs when sizing is done from the left side of the window.
Why does this flickering happen? In other words, what is the OS doing when you reposition a window?
Note: I do not experience flickering when resizing from the right side which means the window is not necessarily moving its origin X and Y.
Resizing a window under Windows involves several messages sent between the OS and the window's handler (the lpfnWndProc member of WNDCLASSEX structure used to register the window's class). You can discover them by yourself using some message monitoring tool. Spy++ that comes with Visual Studio is one such tool.
One interesting message is WM_NCCALCSIZE: this message, called during window resizing, can generate two rectangles (when WVR_VALIDRECTS flag is set): source and target specifying what content of the old window's client area can be "reused" at the new window's position. By default it's assumed that the top-left corner is a pivot:
resizing the left or top border causes the old window's content to get copied to preserve the pivot;
resizing the right ot bottom border copies nothing because the top-left corner of the window did not move.
This default copying can cause flicker, if it does not correspond to the way you position visuals during repaint. For example, everything that is displayed relative to the right or bottom border will be misplaced after resize from the left or top border: these objects will get moved unnecessarily leaving strange mix of old and new things after such resize, because only non-copied pixels will be repainted. If you try to cure the mess with InvalidateRect during, say, WM_SIZE you will get the flicker (the time interval where things are misplaced is very short but it still exists).
The easiest way to disable this behavior is by setting the CS_HREDRAW and CS_VREDRAW Class Styles for your window.
A 2018 update.
The WM_NCCALCSIZE WVR_VALIDRECTS trick is still a good way from preventing Windows XP/Vista/7 SetWindowPos from doing a needless BitBlt that causes the flickering.
However, Microsoft did it again and on Windows 8/10, the DWM window manager adds another layer of BitBlt on top of the legacy SetWindowPos BitBlt which can cause the same problem and is harder to work around.
For an explanation of why the unwanted BitBlt causes flickering, as well as sample code of the WM_NCCALCSIZE WVR_VALIDRECTS trick and some code ideas for how to prevent Windows 8/10 Aero from doing the same, please see:
How to smooth ugly jitter/flicker/jumping when resizing windows, especially dragging left/top border (Win 7-10; bg, bitblt and DWM)?
I'd like to make a captionless window that covers the entire desktop, but still shows the task bar. What is the best way to do this?
I can detect where the taskbar is and just resize my window to exclude it, but then I need to know when the user changes the size / position of the task bar.
Or, is there a combination of window styles or something else that will make sure my window is always behind the task bar?
Set your window placement using the return value from SystemParametersInfo, passing SPI_GETWORKAREA as a parameter.
Retrieves the size of the work area on the primary display monitor.
The work area is the portion of the screen not obscured by the system
taskbar or by application desktop toolbars. The pvParam parameter must
point to a RECT structure that receives the coordinates of the work
area, expressed in virtual screen coordinates.
Maximise a window with no caption/border.
I noticed Firefox 4, Opera and Chrome, and IE 7/8 put buttons and controls in the title/caption bar, how is this done?
Thanks
http://img199.imageshack.us/img199/3307/slayerf.png
alt text http://img199.imageshack.us/img199/3307/slayerf.png
What they probably do is turn the caption bar off entirely (by excluding the WS_CAPTION window style), add a glass area to the top of the window, and then draw their own controls.
See http://msdn.microsoft.com/en-us/magazine/cc163435.aspx for more on glass.
Probably they simply handle the WM_NCPAINT message and draw part of the non-client area (which includes the borders and the caption bar) by themselves; they will also handle WM_NCLBUTTONDOWN, WM_NCHITTEST and other WM_NC* messages to emulate the behavior of a button on the caption bar.
Or at least, this was the way it was commonly done before Aero; I don't know how much it changed this kind of things.
Yes, you can do that.. you have use window hooks, insert your dll in remote process and run the function of dll remotely. here is full fledged article dealing with it :-
http://www.codeproject.com/KB/threads/winspy.aspx
I want to allow a user to drag my Win32 window around only inside the working area of the desktop. In other words, they shouldn't be able to have any part of the window extend outside the monitor(s) nor should the window overlap the taskbar.
I'd like to do it in a way that does cause any stuttering. Handling WM_MOVE messages and calling MoveWindow() to reposition the window if it goes off works, but I don't like the flickering effect that's caused by MoveWindow().
I also tried handling WM_MOVING which prevents the need to call MoveWindow() by altering the destination rectangle before the move actually happens. This resolves the flickering problem, but another issue I run into is that the cursor some times gets aways from the window when a drag occurs allowing the user to drag the window around while the cursor is not even inside the window.
How do I constrain my window without running into these issues?
Windows are, ultimately, positioned via the SetWindowPos API.
SetWindowPos starts by validating its parameters by sending the window being sized or moved a WM_WINDOWPOSCHANGING message, and then a WM_WINDOWPOSCHANGED message notifying the window proc of the changed size and/or position.
DefWindowProc handling of these messages is to, in turn, send WM_GETMINMAXINFO and then WM_SIZE or WM_MOVE messages.
Anyway, handle WM_WINDOWPOSCHANGING to filter both user, and code, based attempts to position a window out of bounds.
Keep in mind that users with multi-monitor setups may have a desktop that extends into negative x- and y-coordinates, or that is not rectangular. Also, some users use alternative window managers such as LiteStep, which implement virtual desktops by moving them off-screen; if you try to fight this, your application will break for these users.
You can do this by handling the WM_MOVING message and changing the RECT pointed to by the lParam.
lParam: Pointer to a RECT structure with the current position of the window, in screen coordinates. To change the position of the drag rectangle, an application must change the members of this structure.
you may also want to handle WM_ENTERSIZEMOVE to know when the window is beginning to move, and WM_EXITSIZEMOVE
WM_GETMINMAXINFO is what you seem to be looking for.
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.