This utility helps you get your foot in the Window 3.0 programming door
February 01, 1991
URL:http://www.drdobbs.com/windows/screen-capturing-for-windows-30/184408495
Copyright © 1991, Dr. Dobb's Journal
Jim is the author of C Programming For MIDI, MIDI Sequencing In C (M&T Books), and articles for Electronic Musician magazine. He can be reached via CompuServe (73220,324).
Snap3 is a program that allows you to grab any part of a Windows 3.0 application screen and paste it to the clipboard. Once in the clipboard, you can use the Write or Word for Windows Paste command to paste the image directly into your documents. Not only is the program a handy tool, but understanding how it works is a good introduction into the sometimes mysterious world of Windows 3 programming.
I use Snap3 to grab representative images from the running program I'm documenting, adding the image to the manual as I write. The utility can also be used to create help screens by letting you cut and paste images from the program into your help source file, created with Windows. (For more information on the Microsoft Help compiler, refer to "Building an Efficient Help System" by Leo Notenboom and Michael Vose [DDJ, June 1990]).
The idea for Snap3 came from a similar public domain program called "Snap" available on the CompuServe MSWIN forum. Because Snap is a Windows 2.x program, it generates those nasty warning messages every time you run it in Windows 3.0 Standard or 386 Enhanced Mode. I decided to write a 3.0 version, and cut the program down to the bare essentials.
When you run the program, a window (see Figure 1) with two menu items will appear, the first item being "Start Capture." When this item is clicked, the mouse cursor turns to a crosshair which you can move to the upper left of the screen area you want to capture. By pressing the left mouse button and dragging the mouse down, you will "draw" a rectangle on the screen. You stretch the rectangle to encompass the area you want to capture and then release the button. The graphics image captured shows up in Snap3's window. The other key function is "Clear Buffer," which clears the Snap3 window and empties the clipboard. Snap3 also has an About function and a simple Help screen.
From a programmer's point of view, all Snap3 is doing is grabbing a bitmap off of the screen and pasting it to the Windows clipboard that is common to all Windows applications. The captured bitmap is then available for a Paste operation from Word For Windows, Paintbrush, or other similar applications. You can also see the image by clicking open Windows' clipboard viewer.
The Snap3 program is broken up into four files. The NMAKE file (Listing One) calls the C compiler (cl), the resource compiler (rc), and the linker (link) to build the finished program. All Windows programs have a definition file that provides basic information as to the program's name and organization. SNAP3.DEF (Listing Two) is an example of the simplest possible DEF file. The resource file SNAP3.RC (Listing Three) gives the name of the program's icon and defines the program menu. Following normal Windows programming practice, the menu items are numbered based on #define statements in the header file SNAP3.H (Listing Four ). The header file also includes the function prototypes. The actual program code is in SNAP3.C (Listing Five). There are only three functions. The WinMain( ) function loads the program icon that was created using the SDK Paint application that comes with the Windows 3.0 SDK.
The SNAP3.C WndProc( ) function contains all of the program logic. Capturing starts when you select the Start Capture menu item, generating a IDM_START message, changing the cursor to IDC_CROSS. Once capturing starts, WM_MOUSEMOVE messages cause the rectangular region captured by the mouse to be outlined. The function OutlineBlock( ) at the end of the listing does the drawing. One sneaky thing here is that the outline rectangle's lines are drawn with the logical R2_NOT operator (function SetROP2( )). This causes drawing the lines in the same place twice to erase the lines. Windows includes a number of built-in functions for dealing with bitmap images. These work at a fairly high level, freeing you from having to worry about how the pixel data is stored or manipulated. SNAP3 uses several of these functions to do the capture of the screen image.
The transfer of the image to the clipboard happens when you release the mouse button, generating a WM_LBUTTONUP message. A memory area for the bitmap is created using CreateCompatibleBitmap( ). StretchBlt( ) copies from the screen device to the memory device. Then SetClipboardData( ) alerts Windows that the clipboard should now look to the bitmap memory area for its data.
If Snap3 is not minimized down to an icon, it will display the captured image in its window. Any time a WM_PAINT message is received, it copies the clipboard bitmap (if any) to the Snap3 window area. The Windows function StretchBlt( ) does the copying of the bitmap to the screen image.
_SCREEN CAPTURING FOR WINDOWS 3.0_ by Jim Conger
[LISTING ONE]
ALL: snap3.exe snap3.obj : snap3.c cl -AS -c -DLINT_ARGS -Gsw -Oat -W2 -Zped snap3.c snap3.res: snap3.rc snap3.ico rc -r snap3.rc snap3.exe : snap3.obj snap3.def snap3.res link /NOD snap3, , ,libw slibcew, snap3.def rc snap3.res[LISTING TWO]
NAME SNAP3 DESCRIPTION 'snap3 program for windows bitmap capture to clipboard' EXETYPE WINDOWS STUB 'WINSTUB.EXE' CODE PRELOAD MOVEABLE DATA PRELOAD MOVEABLE MULTIPLE HEAPSIZE 1024 STACKSIZE 4096 EXPORTS WndProc[LISTING THREE]
/* snap3.rc */ #include "snap3.h" snap3 ICON snap3.ico snap3 MENU BEGIN MENUITEM "&Start Capture" IDM_START MENUITEM "&Clear Buffer", IDM_CLEAR MENUITEM "&About", IDM_ABOUT MENUITEM "\a&Help", IDM_HELP END[LISTING FOUR]
/* snap3.h */ #define IDM_START 1 /* menu item id values */ #define IDM_CLEAR 2 #define IDM_ABOUT 3 #define IDM_HELP 4 /* function prototypes */ long FAR PASCAL WndProc (HWND, unsigned, WORD, LONG) ; void OutlineBlock (HWND hWnd, POINT beg, POINT end) ;[LISTING FIVE]
/* snap3.C -- Screen Capture to clipboard -- jim conger */ #include <windows.h> #include <stdlib.h> #include "snap3.h" int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow) { static char szAppName [] = "snap3" ; HWND hWnd ; MSG msg ; WNDCLASS wndclass ; if (!hPrevInstance) { wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, szAppName) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = szAppName ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) return FALSE ; } hWnd = CreateWindow (szAppName, "Snap3", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, GetSystemMetrics (SM_CXSCREEN) / 2, 8 * GetSystemMetrics (SM_CYMENU), NULL, NULL, hInstance, NULL) ; ShowWindow (hWnd, nCmdShow) ; UpdateWindow (hWnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } long FAR PASCAL WndProc (HWND hWnd, unsigned iMessage, WORD wParam, LONG lParam) { static BOOL bCapturing = FALSE, bBlocking = FALSE, bStarted = FALSE ; static POINT beg, end, oldend ; static short xSize, ySize ; static HANDLE hInstance ; HDC hDC, hMemDC ; BITMAP bm ; HBITMAP hBitmap ; HICON hIcon ; PAINTSTRUCT ps ; switch (iMessage) { case WM_CREATE: /* get program instance when window is created */ hInstance = GetWindowWord (hWnd, GWW_HINSTANCE) ; break ; case WM_COMMAND: /* one of the menu items has been clicked */ switch (wParam) { case IDM_START: /* the start capture item */ bCapturing = TRUE ; bBlocking = bStarted = FALSE ; SetCapture (hWnd) ; /* grab mouse */ SetCursor (LoadCursor (NULL, IDC_CROSS)) ; CloseWindow (hWnd) ; /* minimize window */ break ; case IDM_CLEAR: /* clears screen and clipboard */ OpenClipboard (hWnd) ; EmptyClipboard () ; CloseClipboard () ; InvalidateRect (hWnd, NULL, TRUE) ; /* forces paint */ break ; case IDM_ABOUT: /* show about box */ MessageBox (hWnd, "Snap3 - Windows screen capture to clipboard. \nJim Conger 1990.", "Snap3 About", MB_OK) ; break ; case IDM_HELP: MessageBox (hWnd, "After you click the Start Capture menu item, move the mouse to the upper left of the area you want to copy to the clipboard. Hold down the left mouse button while you drag the mouse to the lower right of the area. Once you release the mouse button, the area is sent to the clipboard and shown in Snap3's window.", "Snap3 Help", MB_OK) ; break ; } case WM_LBUTTONDOWN: /* starting capturing screen */ if (bCapturing) { if (bStarted) { bBlocking = TRUE ; oldend = beg = MAKEPOINT (lParam) ; OutlineBlock (hWnd, beg, oldend) ; SetCursor (LoadCursor (NULL, IDC_CROSS)) ; } else bStarted = TRUE ; } break ; case WM_MOUSEMOVE: /* show area as rectangle on screen */ if (bBlocking) { end = MAKEPOINT (lParam) ; OutlineBlock (hWnd, beg, oldend) ; /* erase old outline */ OutlineBlock (hWnd, beg, end) ; /* draw new one */ oldend = end ; } break ; case WM_LBUTTONUP: /* capture and send to clipboard */ if (bBlocking) { bBlocking = bCapturing = FALSE ; SetCursor (LoadCursor (NULL, IDC_ARROW)) ; ReleaseCapture () ; /* free mouse */ end = MAKEPOINT (lParam) ; OutlineBlock (hWnd, beg, oldend) ; /* erase area outline */ xSize = abs (beg.x - end.x) ; ySize = abs (beg.y - end.y) ; hDC = GetDC (hWnd) ; hMemDC = CreateCompatibleDC (hDC) ; hBitmap = CreateCompatibleBitmap (hDC, xSize, ySize) ; if (hBitmap) { SelectObject (hMemDC, hBitmap) ; StretchBlt (hMemDC, 0, 0, xSize, ySize, hDC, beg.x, beg.y, end.x - beg.x, end.y - beg.y, SRCCOPY) ; OpenClipboard (hWnd) ; EmptyClipboard () ; SetClipboardData (CF_BITMAP, hBitmap) ; /* copy to */ CloseClipboard () ; /* clipboard */ InvalidateRect (hWnd, NULL, TRUE) ; /* request paint*/ } else MessageBeep (0) ; DeleteDC (hMemDC) ; ReleaseDC (hWnd, hDC) ; } ShowWindow (hWnd, SW_RESTORE) ; /* un-minimize window */ break ; case WM_PAINT: /* display contents of clipboard if bitmap */ hDC = BeginPaint (hWnd, &ps) ; if (IsIconic (hWnd)) /* if window is iconic, show icon */ { hIcon = LoadIcon (hInstance, "snap3") ; if (hIcon != NULL) DrawIcon (hDC, 1, 1, hIcon) ; } else /* if not, show clipboard contents */ { OpenClipboard (hWnd) ; if (hBitmap = GetClipboardData (CF_BITMAP)) /* if bitmap */ { hMemDC = CreateCompatibleDC (hDC) ; SelectObject (hMemDC, hBitmap) ; GetObject (hBitmap, sizeof (BITMAP), (LPSTR) &bm) ; SetStretchBltMode (hDC, COLORONCOLOR) ; StretchBlt (hDC, 0, 0, xSize, ySize, hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY) ; DeleteDC (hMemDC) ; } CloseClipboard () ; } EndPaint (hWnd, &ps) ; break ; case WM_DESTROY: PostQuitMessage (0) ; break ; default: return DefWindowProc (hWnd, iMessage, wParam, lParam) ; } return 0L ; } /* OutlineBlock() writes a rectangle on screen given two corner points. R2_NOT style is used, so drawing twice on the same location erases outline. */ void OutlineBlock (HWND hWnd, POINT beg, POINT end) { HDC hDC ; hDC = CreateDC ("DISPLAY", NULL, NULL, NULL) ; ClientToScreen (hWnd, &beg) ; /* convert to screen units */ ClientToScreen (hWnd, &end) ; SetROP2 (hDC, R2_NOT) ; /* use logical NOT brush */ MoveTo (hDC, beg.x, beg.y) ; /* draw rectangle */ LineTo (hDC, end.x, beg.y) ; LineTo (hDC, end.x, end.y) ; LineTo (hDC, beg.x, end.y) ; LineTo (hDC, beg.x, beg.y) ; DeleteDC (hDC) ; }
Copyright © 1991, Dr. Dobb's Journal
Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.