_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 #include #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) ; }