To access the contents, click the chapter and section titles.
Fast Track Visual C++ 6.0 Programming
(Publisher: John Wiley & Sons, Inc.)
Author(s): Steve Holzner
ISBN: 0471312908
Publication Date: 09/01/98
Chapter 6 Advanced Screen and Metafile Graphics
In this chapter, we work with some advanced graphics topics, both on the screen and in graphics metafiles. We explore screen graphics by seeing how to implement screen capturecopying a selection from the screen and copying it to the clipboard. This shows us a number of things: how to work with and copy bitmaps at a low level, how to get a device context for the entire screen, how to capture mouse events that happen outside our window, and more.
Next, we spend time solving one of the oldest problems for Windows programmersrefreshing a window when it needs to be refreshed. If the graphics in your window are complex or depend on many user actions, it can be difficult to restore them easily when the time comes to do so. Here, we use metafilesmemory or disk files that store device context actionsto provide an easy way to store whats gone into your display and restore that display as needed by replaying the metafile.
We start with screen capture, into which we put a lot of Visual C++ power.
Screen Capture
Our screen capture program, Copier, lets the user copy part or all of the screen, displays whats been copied, and allows it to be placed into the clipboard. Users need only outline the area of the screen they want to copy using the mouse, and we can capture it.
Create a new MDI project named Copier and open ClassWizard. We start by working with the mouse.
Capturing the Mouse
In the Copier program, we need to capture the mouse so that we can use the mouse even though it goes outside our programs window. When weve captured the mouse, we are able to let the user draw a box on the screen to enclose the part of the screen they want to capture.
Recent versions of Windows have some security concerns with mouse captureespecially by hostile programsso there are some new rules. Instead of letting a program capture the mouse without restriction, the program that captures the mouse must first own the mouse. Because of this, to capture the mouse, the user must first press the left mouse button in our program, then drag the mouse to the location they want to copy on the screen. While keeping the left mouse button down, they can then use the right mouse button to outline the area to capture; when they release the right mouse button, we are able to capture the area theyve outlined.
The mouse capture process begins when the left mouse button goes down, so we start by adding OnLButtonDown() to the view class.
void CCopierView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CView::OnLButtonDown(nFlags, point);
}
We begin by capturing the mouse using SetCapture().
void CCopierView::OnLButtonDown(UINT nFlags, CPoint point)
{
SetCapture(); ⇐
.
.
.
CView::OnLButtonDown(nFlags, point);
}
Now we get all mouse messages until we either release the mouse ourselves or the left mouse button goes up. Because the capture operation has started, we set a new flag, CaptureFlag, to true and add it to the view classs header.
void CCopierView::OnLButtonDown(UINT nFlags, CPoint point)
{
SetCapture();
CaptureFlag = true; ⇐
.
.
.
CView::OnLButtonDown(nFlags, point);
}
We support another flag here, DrawFlag (add that flag to the view classs header as well), which indicates whether the user is using the right mouse button to outline the area on the screen to capture (in this case we should be drawing a rectangle the user can stretch to outline that area). When the left mouse button goes down, we set DrawFlag to false.
void CCopierView::OnLButtonDown(UINT nFlags, CPoint point)
{
SetCapture();
CaptureFlag = true; ⇐
DrawFlag = false; ⇐
CView::OnLButtonDown(nFlags, point);
}
When the left mouse button goes up, the capturing process is over, so we release the mouse and set our two flags to false in OnLButtonUp().
void CCopierView::OnLButtonUp(UINT nFlags, CPoint point)
{
ReleaseCapture(); ⇐
CaptureFlag = false; ⇐
DrawFlag = false; ⇐
CView::OnLButtonUp(nFlags, point);
}
Now that weve captured the mouse, we put it to work. When the user uses the right mouse button, an area on the screen is outlined. We can stretch a rectangle over that area to indicate the capture area. To draw that rectangle outside our own window, we have to get a device context for the entire screen.
Drawing Anywhere on the Screen
When the user presses the right mouse button (and while the left mouse button is still pressed), we start drawing the outline rectangle on the screen to indicate the capture area. As soon as the right mouse button goes down, we set DrawFlag to true in OnRButtonDown().
void CCopierView::OnRButtonDown(UINT nFlags, CPoint point)
{
if(CaptureFlag){
DrawFlag = true; ⇐
.
.
.
}
CView::OnRButtonDown(nFlags, point);
}
In addition, we save the point at which the right mouse button went down, because that point marks one corner of the capture area. We call that point the anchor point.
Anchor Point
x-------------------------
| |
| |
| |
| |
| |
| |
--------------------------
How do we get this point if its outside our window? We use the special function GetMessagePos(), which returns the current location of the mouse in screen coordinates (as opposed to the point passed to us in the point parameter, which is a client coordinate). We store the anchor point in a new CPoint object that we add to the view, AnchorPoint.
void CCopierView::OnRButtonDown(UINT nFlags, CPoint point)
{
if(CaptureFlag){
DrawFlag = true;
AnchorPoint = GetMessagePos(); ⇐
}
CView::OnRButtonDown(nFlags, point);
}
This is all it takes to record the anchor point for our drawing work. When the user moves the mouse to a new location while keeping the right and left mouse buttons pressed, we record the new mouse location in OnMouseMove() and call that new location CurrentPoint.
Anchor Point
x-------------------------
| |
| |
| |
| |
| |
| |
--------------------------x CurrentPoint
After the rectangle is drawn to the current location, we call that location the previous point to prepare for additional mouse moves.
Anchor Point
x-------------------------
| |
| |
| |
| |
| |
| |
-------------------------x PreviousPoint
If the mouse moves again, there is a new current point, so we erase the rectangle that stretches from the anchor point to the previous point and redraw the rectangle from the anchor point to the new current point.
Anchor Point
x-------------------------------
| |
| |
| |
| |
| |
| |
------------------------------x CurrentPoint
|