How To Use Win32 API to Draw a Dragging Rectangle on Screen DC (135865)
The information in this article applies to:
- Microsoft Platform Software Development Kit (SDK) 1.0
This article was previously published under Q135865 SUMMARY
This article shows by example how to have your application draw a dragging
rectangle on an arbitrary area of the screen. This action is known as
"rubber banding." Utilities that perform screen capture, zooming, and so on
are typical examples of such applications. Due to the change in behavior of
the SetCapture API in win32, the standard technique used for rubber banding
on the screen DC in 16-bit Windows no longer works under Windows NT and
Windows95. This article explores alternate methods you can use to perform
rubber banding in win32.
MORE INFORMATION16-bit Method for Rubber Banding Won't Work in Win32-Based Applications
In 16-bit Windows, an application called the SetCapture API prior to
starting the rubber banding. This then directed all further mouse input to
the application's capture window. This allowed the user to click anywhere
on the desktop including the client area of other running applications and
start the drag action. Because SetCapture directs all mouse input to the
capture window, it is then a simple matter for the application to draw a
rubber banding rectangle as the user moves the mouse.
However, the Win32 implementation of the SetCapture API has changed so that
the 16-bit method fails. SetCapture no longer directs all mouse input to an
application's capture window. If an application calls SetCapture and the
user then clicks another application or the desktop (an application by
itself) to activate it, subsequent mouse messages are no longer directed to
the capture window. The only mouse messages that a capture window receives
are those generated when the application's thread is active. This is
applicable to a 16-bit application running under Windows NT or Windows 95
as well as a newly written 32-bit application. There are two ways for a
Win32-based application to perform rubber banding.
Method One: How to Perform Rubber Banding in Win32-Based Applications
In this method, the application imposes a restriction on the user as to how
the dragging action is done. For example, the application might display a
small window and require the user to depress the mouse button in the client
area of the window to indicate the beginning of the rubber banding mode and
drag the mouse, without releasing the mouse button, to whichever part of
the desktop the user wants to capture. Upon reaching the appropriate anchor
point, the user presses a key on the keyboard (for example, the CTRL key)
and drags the mouse to perform the actual rubber banding. Note that during
the entire process, the user keeps the mouse button depressed, so other
applications are not activated, and all the mouse messages are therefore
directed to the capture window.
The following sample code illustrates how this might be implemented:
// Some global declarations.
BOOL bDrag;
BOOL bDraw;
POINT ptCurrent, ptNew;
// Inside the capture window procedure.
case WM_LBUTTONDOWN:
SetCapture(hwnd);
bDrag = TRUE; // Set flag to check for key down in mouse move
// message.
case WM_MOUSEMOVE:
if (bDrag)
{
if ( keyFlags & MK_CONTROL ) // CTRL key down.
{
bDraw = TRUE; // Start actual drawing from next move message.
ptCurrent.x = ptNew.x = x; // Store the first point after.
ptCurrent.y = ptNew.y = y; // Converting to screen
// coordinates.
ClientToScreen (hwnd,&ptCurrent);
ClientToScreen (hwnd,&ptNew);
bDrag = FALSE;
}
}
else if ( bDraw )
{
// Draw two rectangles in the screen DC to cause rubber banding.
HDC hdc = CreateDC ( TEXT("DISPLAY"), NULL, NULL, NULL );
SetROP2(hdc, R2_NOTXORPEN );
// Draw over and erase the old rectangle.
Rectangle ( hdc, ptCurrent.x, ptCurrent.y, ptNew.x, ptNew.y );
ptNew.x = x;
ptNew.y = y;
ClientToScreen (hwnd,&ptNew);
// Draw the new rectangle.
Rectangle ( hdc, ptCurrent.x, ptCurrent.y, ptNew.x, ptNew.y );
DeleteDC ( hdc );
}
case WM_LBUTTONUP:
if ( bDraw )
{
// Don't leave orphaned rectangle on desktop; erase last
// rectangle.
HDC hdc;
bDrag = FALSE;
bDraw = FALSE;
ReleaseCapture();
hdc = CreateDC ( TEXT("DISPLAY"), NULL, NULL, NULL );
SetROP2(hdc, R2_NOTXORPEN );
Rectangle ( hdc, ptCurrent.x, ptCurrent.y, ptNew.x, ptNew.y );
DeleteDC ( hdc );
// At this point the application has the coordinates of the rubber
// banding rectangle.
} else if ( bDrag)
{
// The user released the mouse button without ever pressing CTRL
// key.
bDraw = FALSE;
bDrag = FALSE;
ReleaseCapture();
}
The drawback to this approach is that the rubber banding action may
not be intuitive. The user is required to use a key in addition to the
mouse now, whereas in 16-bit Windows this could have been accomplished with
the mouse alone.
Method Two: How to Perform Rubber Banding in Win32-Based Applications
Another way to do rubber banding in win32 consistent with the 16-bit method
is to create a popup window that covers the entire desktop and has the
WS_EX_TRANSPARENT style bit set. This window can be created with no title
bar or borders and is active only for the time period of the rubber
banding. It is destroyed upon completion of the rubber banding - when the
user releases the mouse button. This popup window becomes the capture
window and the rubber banding logic would then simply be applied on the
client area DC of the popup window.
Modification Type: | Minor | Last Reviewed: | 7/11/2005 |
---|
Keywords: | kbhowto kbInput KB135865 |
---|
|