In Depth Banner
Skip Navigation Links

Non-client mouse operations.

Previously, you saw how to modify the relationship between the client and non client areas of a control so that you could make the distinction between painting the parts of the window such as borders or system buttons that have little relationship to the content of the control or window and the content itself.  You will remember that the advantage of modifying the client size was that there was no need to compensate for window adornments when you have to draw the window content.  There is also a distinction between the client and non client areas of the window when it comes to user interaction as well.  Consider the kind of window used to display a form with a standard title bar and system buttons.   This represents a particular class of window that has a specific set of behaviors and which implies a certain standard of operation when the user sees it on screen.  For example, the user knows that the title bar, contains the name of the program or document currently being edited and that the buttons behave in a certain way. 

In your own applications, The you may wish to create a similar style of window that has a predictable behavior which is isolated from the behavior of the client area so that you can reuse this "client wrapper" in many different places.  In order to do this you need to be able to receive mouse input from the area so that you can differentiate between the user's interaction with the objects in the client area and their desire to do something with the executive, non-client, portion. 

Once again, in order to do this, we have to resort to a lower level of interaction than is provided by the standard Windows Forms controls or forms And use the WndProc method to process low-level non-client windows messages as they arrive. 

The demonstration for this article is a simple one which puts a track-bar style control in the title bar that controls the overall opacity of the form. 

Messages.

WM_NCPAINT is used to create the graphic for a slider which is embedded in the title bar as shown in figure 1.

Figure 1. The opacity slider.

The draw process chooses a rectangle into which the slider should fit without interfering with the other buttons in the title bar. A scale is drawn and a button placed according to the value of the transparency which is initially zero.

WM_NCLBUTTONDOWN is caught and a test made to see if the pointer is in the button. If it is, a semaphore is set which signifies the button has been grabbed. The button will be redrawn in a pressed state. Note that all non-client mouse values are in screen, not client positions but the usual PointToClient method will cause us problems because the client is offset within the window. To obtain an accurate position within the non-client area we just need to subtract the location of the form. For controls within a form you'll need to find the control's ultimate parent and compound all the offsets to find the correct values. This message is also used to store the pixel offset of the pointer from the left side of the button. This enables the button to be moved in synchronization with the pointer.

WM_NCMOUSEMOVE enables you to move the slider. The value is calculated according to the current size of the scale which changes with the window size. The value is applied to the window and the scale is redrawn again using the SendMessage API to send another WM_NCPAINT to the form.

WM_NCLBUTTONUP releases the button and flags the end of the operation.

Non-client operations don't always follow strict rules. For example, if the window is restored after being minimized the non-client area is repainted without using the WM_NCPAINT message. The demo overrides the OnSizeChanged to ensure that the slider is repainted.

The code for this example is shown in this listing.

You can find the Source Code files here.

This concludes this short series on Non-Client operations.

Return to Part 1.

Return to the main menu.

 

Copyright © Bob Powell 2003-2009. All rights reserved