You have probably noticed that the use of the mouse in Windows is very common. Most functions can be accessed via mouse motions and mouse clicking. In fact, Windows users are more interested in using the mouse to maneuver through Windows than they are in using keyboard commands. It would seem prudent, therefore, for you to gain at least a basic knowledge of how mouse events are handled within Visual C++.
As was previously stated, Windows communicates by sending out messages. In our case, we are interested in the WM_MOUSEMOVE message. This indicates that the mouse has been moved. There are a number of flags that come with that message to tell you what other keys might have been depressed when the mouse was moved. Table 15.7 summarizes these flags.
Flag | Purpose |
---|---|
MK_LBUTTON | Indicates that the left mouse button was clicked. |
MK_RBUTTON | Indicates that the right mouse button was clicked. |
MK_MBUTTON | Indicates that the middle mouse button was clicked. |
MK_SHIFT | Indicates that the shift key was clicked |
MK_CONTROL | Indicates that the control key was clicked |
The other item we will need to examine is the CclientDC. This provides access to what is called the device context. The device context allows us to manipulate the screen to do simple drawings. It is a class that you create an instance of in order to give you access to the device context. Its constructor takes a single parameter. That parameter is the keyword this. Recall that this refers to the current instance of a class you are in. Let’s look at an example that utilizes the CClientDC and mouse functions to do a simple drawing. This should help you become acquainted with mouse events.
Step 1: Start Visual C++ and run the app wizard to create a basic dialog application with the default values, except for the name, which should be example15_04.
Step 2: Open the class wizard (Figure 15.23). On the first tab in the messages box, choose WM_MOUSEMOVE. Now click add function, then click OK. Then click the Edit Code button.
Figure 15.23: Adding functions for MOUSEMOVE.
Step 3: Add the following code.
if((nFlags & MK_LBUTTON) == MK_LBUTTON) { CClientDC dc(this);//device context with this dialog //class as a reference. dc.SetPixel(point.x,point.y,RGB(0,0,0)); }// end of if
At this point you have a working, if somewhat uninteresting, piece of code. You should notice the if statement. It is using a single ampersand (&), which is a bitwise AND operation. You see the nFlags is a variable that holds an integer representing whatever button is currently being clicked. The bitwise AND operation compares this to the MK_LBUTTON integer value to see if that is the button that is being clicked. You can run the code now. A dotted line will follow as you move the mouse around the screen, as you see in Figure 15.24.
Figure 15.24: The first implementation of MOUSEMOVE.
However, now we would like to beef this up a bit.
Step 5: Replace the code you had originally in the onMouseMove function with the following code.
// Check to see if the left mouse button is down if ((nFlags & MK_LBUTTON) == MK_LBUTTON) { // Get the Device Context CClientDC dc(this); // Draw the pixel // dc.SetPixel(point.x, point.y, RGB(0, 0, 0)); // Create a new pen CPen lpen(PS_SOLID, 16, RGB(255, 0, 0)); // Use the new pen dc.SelectObject(&lpen); // Draw a line from the previous point to the // current point dc.MoveTo(m_X, m_Y); dc.LineTo(point.x, point.y); // Save the current point as the previous point m_X= point.x; m_Y = point.y; } CDialog::OnMouseMove(nFlags, point);
When you run the application this time, you will be able to draw wide, solid lines, like those shown in Figure 15.26.
Figure 15.25: Adding member variables.