6.3.3 Showing a Graphics Selection

As the user makes the selection, your application must provide feedback about his or her progress. For the application to do this, you can draw a border around the selection rectangle by using the LineTo function upon receiving each new WM_MOUSEMOVE message. To prevent the application from losing information already on the screen, draw a line that inverts the screen rather than drawing over it. You can do this by using the SetROP2 function to set the binary raster mode to R2_NOT, as in the following example:

case WM_MOUSEMOVE:
    {
        RECT rectClient;
        int  NextX;
        int  NextY;

        if (fTrack) {
            NextX = LOWORD(lParam);
            NextY = HIWORD(lParam);

            /* Do not draw outside the window's client area. */

            GetClientRect(hwnd, &rectClient);

            if (NextX < rectClient.left)
                NextX = rectClient.left;
            else
                if (NextX >= rectClient.right)
                    NextX = rectClient.right - 1;
            if (NextY < rectClient.top)
                NextY = rectClient.top;
            else
                if (NextY >= rectClient.bottom)
                    NextY = rectClient.bottom - 1;

            /*
             * If the mouse position has changed, then clear the
             * previous rectangle and draw the new one.
             */

            if (NextX != PrevX || NextY != PrevY) {
                hdc = GetDC(hwnd);
                SetROP2(hdc, R2_NOT); /* erases previous box */
                MoveTo(hdc, OrgX, OrgY);
                LineTo(hdc, OrgX, PrevY);
                LineTo(hdc, PrevX, PrevY);
                LineTo(hdc, PrevX, OrgY);
                LineTo(hdc, OrgX, OrgY);

                /* Get the current mouse position. */

                PrevX = NextX;
                PrevY = NextY;
                MoveTo(hdc, OrgX, OrgY); /* draws new box */
                LineTo(hdc, OrgX, PrevY);
                LineTo(hdc, PrevX, PrevY);
                LineTo(hdc, PrevX, OrgY);
                LineTo(hdc, OrgX, OrgY);
                ReleaseDC(hwnd, hdc);
            }
        }
    }
    break;

The application processes the WM_MOUSEMOVE message only if the fTrack variable is TRUE (that is, if a selection is in progress). The purpose of the WM_MOUSEMOVE processing is to remove the border around the previous rectangle and draw a new border around the rectangle described by the current and original positions. Since the border is the inverse of what was originally on the screen, inverting again restores it completely. The first four LineTo functions remove the previous border; the next four draw a new border. Before drawing the new border, the application updates the PrevX and PrevY values by assigning them the current values contained in the lParam parameter.