home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / msj / msjv4_6 / prtsc / prtsc2.c < prev   
Encoding:
C/C++ Source or Header  |  1988-06-18  |  14.3 KB  |  444 lines

  1. /*
  2.  * WINDOWS SCREEN CAPTURE - DYNAMIC LIBRARY
  3.  *
  4.  * LANGUAGE : Microsoft C 5.0
  5.  * SDK      : Windows 2.03 SDK
  6.  * MODEL    : small
  7.  * STATUS   : operational
  8.  *
  9.  * 05/06/88 1.00 - Kevin P. Welch - initial creation.
  10.  *
  11.  */
  12.  
  13. #include <windows.h>
  14. #include <string.h>
  15. #include "prtsc.h"
  16.  
  17. /* global data */
  18. BOOL     bMono;                  /* convert to monochrome? */
  19. WORD     wArea;                  /* current capture area */
  20. WORD     wColors;                /* number of system colors */
  21. HWND     hWndDOS;                /* handle to DOS session */
  22. HANDLE   hInstance;              /* library instance handle */
  23. FARPROC  lpfnDOSWnd;             /* DOS session function */
  24. FARPROC  lpfnOldHook;            /* old hook function */
  25.  
  26. /* */
  27.  
  28. /*
  29.  * PrtScInit( hLibInst, wDataSegment, wHeapSize, lpszCmdLine ) : BOOL
  30.  *
  31.  *    hLibInst       library instance handle
  32.  *    wDataSegment   library data segment
  33.  *    wHeapSize      default heap size
  34.  *    lpszCmdLine    command line arguments
  35.  *
  36.  * This function performs all the initialization necessary to use
  37.  * the screen capture dynamic library.  It is assumed that no local
  38.  * heap is used, hence no call to LocalInit.  A non-zero value is
  39.  * returned if the initialization was sucessful.
  40.  *
  41.  */
  42.  
  43. BOOL PASCAL PrtScInit( hLibInst, wDataSegment, wHeapSize, lpszCmdLine )
  44.    HANDLE      hLibInst;
  45.    WORD        wDataSegment;
  46.    WORD        wHeapSize;
  47.    LPSTR       lpszCmdLine;
  48. {
  49.    extern BOOL       bMono;
  50.    extern WORD       wArea;
  51.    extern WORD       wColors;
  52.    extern HWND       hWndDOS;
  53.    extern HANDLE     hInstance;
  54.    extern FARPROC    lpfnDOSWnd;
  55.    extern FARPROC    lpfnNewHook;
  56.  
  57.    HDC      hDC;                    /* handle to temporary DC */
  58.    HWND     hWndFocus;              /* window who has focus */
  59.    char     szClassName[32];        /* temporary class name */
  60.  
  61.    /* initialization - <Alt><PrtSc> active */
  62.    bMono = FALSE;
  63.    wArea = CAPTURE_WINDOW;
  64.    hInstance = hLibInst;
  65.  
  66.    lpfnOldHook = SetWindowsHook( WH_KEYBOARD, (FARPROC)PrtScHook );
  67.    
  68.    hWndFocus = GetFocus();
  69.  
  70.    hDC = GetDC( hWndFocus );
  71.    wColors = GetDeviceCaps( hDC, NUMCOLORS );
  72.    ReleaseDC( hWndFocus, hDC );
  73.  
  74.    /* search for MS-DOS session */
  75.    hWndDOS = GetWindow( hWndFocus, GW_HWNDFIRST );
  76.    while ( hWndDOS ) {
  77.       
  78.       /* check class name */
  79.       GetClassName( hWndDOS, szClassName, sizeof(szClassName) );
  80.       if ( !lstrcmp(szClassName,"Session") ) {
  81.       
  82.          /* inform user that things are happening! */
  83.          MSGBOX( hWndDOS, "<Alt><PrtSc> now available!" );
  84.  
  85.          /* add our menu item to MS-DOS Session */
  86.          ChangeMenu( 
  87.             GetSubMenu( GetMenu(hWndDOS), 2 ),
  88.             NULL, 
  89.             "Screen Ca&pture...",
  90.             CMD_CAPTURE,
  91.             MF_APPEND|MF_CHECKED
  92.          );
  93.          
  94.          /* hook into the MS-DOS Session */
  95.          lpfnDOSWnd = (FARPROC)SetWindowLong(
  96.                hWndDOS,
  97.                GWL_WNDPROC,
  98.                (LONG)PrtScFilterFn
  99.             );
  100.       
  101.          /* normal return */
  102.          return( TRUE );
  103.             
  104.       }
  105.       
  106.       /* get next window handle */
  107.       hWndDOS = GetWindow( hWndDOS, GW_HWNDNEXT );
  108.    
  109.    }
  110.    
  111.    /* abnormal return */
  112.    return( FALSE );
  113.  
  114. }
  115.  
  116. /* */
  117.  
  118. /*
  119.  *
  120.  * PrtScFilterFn( hWnd, wMessage, wParam, lParam ) : LONG FAR PASCAL
  121.  *
  122.  *    hWnd        window handle
  123.  *    wMessage    message number
  124.  *    wParam      additional message information
  125.  *    lParam      additional message information
  126.  *
  127.  * This window function processes all the messages received by the
  128.  * MS-DOS Session window.  When the user selects the Screen Capture...
  129.  * menu option this function displays the screen capture control
  130.  * panel.  All other messages are passed on to the window without
  131.  * modification!
  132.  *
  133.  */
  134.  
  135. LONG FAR PASCAL PrtScFilterFn( hWnd, wMessage, wParam, lParam )
  136.    HWND        hWnd;
  137.    WORD        wMessage;
  138.    WORD        wParam;
  139.    LONG        lParam;
  140. {
  141.  
  142.    /* trap appropriate messages */
  143.    switch( wMessage )
  144.       {
  145.    case WM_COMMAND : /* user command - check for our message */
  146.       if ( wParam == CMD_CAPTURE ) {
  147.          DialogBox( hInstance, "PrtSc", hWndDOS, PrtScDlgFn );
  148.          return( 0L );
  149.       }     
  150.       break;
  151.    case WM_DESTROY : /* window being destroyed - unhook everything */
  152.       if ( wArea ) {
  153.          wArea = CAPTURE_OFF;
  154.          UnhookWindowsHook( WH_KEYBOARD, (FARPROC)PrtScHook );
  155.       }
  156.       SetWindowLong( hWndDOS, GWL_WNDPROC, (LONG)lpfnDOSWnd );
  157.       break;
  158.    default : /* something else - ignore it! */
  159.       break;
  160.    }
  161.    
  162.    /* pass message on to window */
  163.    return(  CallWindowProc(lpfnDOSWnd,hWndDOS,wMessage,wParam,lParam) );
  164.  
  165. }
  166.  
  167. /* */
  168.  
  169. /*
  170.  * PrtScDlgFn( hDlg, wMessage, wParam, lParam ) : BOOL;
  171.  *
  172.  *    hDlg        handle to dialog box
  173.  *    wMessage    message ID
  174.  *    wParam      short parameter
  175.  *    lParam      long parameter
  176.  *
  177.  * This function processes all the messages which relate to the
  178.  * PrtSc dialog box.  This function inserts or removes the keyboard
  179.  * hook function depending on the user's selection.
  180.  *
  181.  */
  182.  
  183. BOOL FAR PASCAL PrtScDlgFn( hDlg, wMessage, wParam, lParam )
  184.    HWND        hDlg;
  185.    WORD        wMessage;
  186.    WORD        wParam;
  187.    LONG        lParam;
  188. {
  189.    
  190.    /* process messages */
  191.    switch( wMessage )
  192.       {
  193.    case WM_INITDIALOG : /* initialize dialog box */
  194.       CheckDlgButton( hDlg, DLGSC_MONOCHROME, bMono );
  195.       EnableWindow( GetDlgItem(hDlg,DLGSC_MONOCHROME), (wColors>2) );
  196.       CheckRadioButton( hDlg, DLGSC_OFF, DLGSC_SCREEN, DLGSC_OFF+wArea );
  197.       break;
  198.    case WM_COMMAND : /* window command */
  199.       
  200.       /* process sub-message */
  201.       switch( wParam )
  202.          {
  203.       case DLGSC_OFF : /* turn screen capture off */
  204.          if ( wArea ) {
  205.             wArea = CAPTURE_OFF;
  206.             UnhookWindowsHook( WH_KEYBOARD, (FARPROC)PrtScHook );
  207.             EnableWindow( GetDlgItem(hDlg,DLGSC_MONOCHROME), FALSE );
  208.          }
  209.          CheckMenuItem( GetMenu(hWndDOS), CMD_CAPTURE, MF_UNCHECKED );
  210.          break;
  211.       case DLGSC_CLIENT : /* capture client area of active window */
  212.       case DLGSC_WINDOW : /* capture active window */
  213.       case DLGSC_SCREEN : /* capture entire screen */
  214.          if ( !wArea ) {
  215.             lpfnOldHook = SetWindowsHook( WH_KEYBOARD, (FARPROC)PrtScHook );
  216.             EnableWindow( GetDlgItem(hDlg,DLGSC_MONOCHROME), (wColors>2) );
  217.          }
  218.          wArea = wParam - DLGSC_OFF;
  219.          CheckMenuItem( GetMenu(hWndDOS), CMD_CAPTURE, MF_CHECKED );
  220.          break;
  221.       case DLGSC_MONOCHROME : /* capture image in monochrome */
  222.          bMono = !bMono;
  223.          break;
  224.       case IDOK :
  225.          EndDialog( hDlg, TRUE );
  226.          break;
  227.       default : /* ignore everything else */
  228.          break;
  229.       }
  230.       
  231.       break;
  232.    default : /* message not processed */
  233.       return( FALSE );
  234.       break;
  235.    }
  236.    
  237.    /* normal return */
  238.    return( TRUE );
  239.    
  240. }
  241.  
  242. /* */
  243.  
  244. /*
  245.  * PrtScHook( nCode, wParam, lParam ) : WORD
  246.  *
  247.  *    nCode       process message?
  248.  *    wParam      virtual key code
  249.  *    lParam      misc key parameters
  250.  *
  251.  * This function is called whenever the user presses any key.
  252.  * The <Alt><PrtSc> keychord is trapped, and a bitmap copy of the
  253.  * desired portion of the screen is copied to the clipboard.  This
  254.  * area can be the client area of the currently active window,
  255.  * the entire active window, or the entire display.
  256.  *
  257.  * The return value is FALSE if the message should be processed by
  258.  * Windows; the return value is TRUE if the message should
  259.  * be discarded.
  260.  *
  261.  */
  262.  
  263. WORD FAR PASCAL PrtScHook( nCode, wParam, lParam )
  264.    int         nCode;
  265.    WORD        wParam;
  266.    LONG        lParam;
  267. {
  268.    extern BOOL       bMono;            /* convert to monochrome? */
  269.    extern WORD       wArea;            /* area to capture */
  270.    extern FARPROC    lpfnOldHook;      /* old keyboard hook */
  271.    
  272.    WORD        uWidth;                 /* width of bitmap */
  273.    WORD        uHeight;                /* height of bitmap */
  274.    WORD        wDiscard;               /* return value */
  275.    POINT       ptClient;               /* client point */
  276.    RECT        rcWindow;               /* window rectangle */
  277.    HDC         hScreenDC;              /* handle to screen DC */
  278.    HDC         hMemoryDC;              /* handle to memory DC */
  279.    HWND        hActiveWnd;             /* handle to active window */
  280.    HBITMAP     hOldBitmap;             /* handle to old bitmap */
  281.    HBITMAP     hMemoryBitmap;          /* handle to memory bitmap */
  282.    
  283.    if (nCode == HC_ACTION) {
  284.    
  285.       /*
  286.        * This check traps the <Alt><PrtSc> keychord using bit 29
  287.        * for the <Alt> key and bit 31 for the key being released.
  288.        *
  289.        * Note that on old AT keyboards the PrtSc key was on the
  290.        * multiply key above the numeric keypad.  Although newer
  291.        * keyboard layouts have the PrtSc key elsewhere, the PrtSc
  292.        * key is still identified by the VK_MULTIPLY ID code.
  293.        */
  294.       
  295.       if ((wParam==VK_MULTIPLY) && ((lParam&0xA0000000)==0xA0000000)) {
  296.          
  297.          /* set return value so Windows will not process message */
  298.          wDiscard = TRUE;
  299.          
  300.          /* retrieve top-level active window */
  301.          hActiveWnd = GetFocus();
  302.          while ( (GetWindowLong(hActiveWnd,GWL_STYLE)&WS_CHILD) == WS_CHILD )
  303.             hActiveWnd = GetParent( hActiveWnd );
  304.          
  305.          /* continue if window visible */
  306.          if ( IsWindowVisible(hActiveWnd) ) {
  307.             
  308.             switch( wArea )
  309.                {
  310.             case CAPTURE_CLIENT :
  311.                
  312.                /* retrieve client area dimensions */
  313.                GetClientRect( hActiveWnd, &rcWindow );
  314.                
  315.                /* convert client coordinates to screen */
  316.                ptClient.x = rcWindow.left;
  317.                ptClient.y = rcWindow.top;
  318.                ClientToScreen( hActiveWnd, &ptClient );
  319.                
  320.                rcWindow.left = ptClient.x;
  321.                rcWindow.top = ptClient.y;
  322.                ptClient.x = rcWindow.right;
  323.                ptClient.y = rcWindow.bottom;
  324.                ClientToScreen( hActiveWnd, &ptClient );
  325.                
  326.                rcWindow.right = ptClient.x;
  327.                rcWindow.bottom = ptClient.y;
  328.                
  329.                break;
  330.             case CAPTURE_WINDOW : 
  331.                
  332.                /* retrieve dimensions of active window */
  333.                GetWindowRect( hActiveWnd, &rcWindow );
  334.                
  335.                break;
  336.             case CAPTURE_SCREEN :
  337.                
  338.                /* retrieve dimensions of entire screen */
  339.                rcWindow.top = 0;
  340.                rcWindow.left = 0;
  341.                rcWindow.right = SCREEN_WIDTH;
  342.                rcWindow.bottom = SCREEN_HEIGHT;
  343.                
  344.                break;
  345.             }
  346.             
  347.             /*
  348.              * Note that the window boundaries need to be
  349.              * adjusted as part of the window may not be
  350.              * visible on the screen.  This eliminates the
  351.              * problem of a partially defined bitmap.
  352.              *
  353.              */
  354.             
  355.             /* adjust boundaries to screen clipping region */
  356.             if (rcWindow.right > SCREEN_WIDTH)
  357.                rcWindow.right = SCREEN_WIDTH;
  358.             
  359.             if (rcWindow.bottom > SCREEN_HEIGHT)
  360.                rcWindow.bottom = SCREEN_HEIGHT;
  361.             
  362.             if (rcWindow.left < 0)
  363.                rcWindow.left = 0;
  364.             
  365.             if (rcWindow.top < 0)
  366.                rcWindow.top = 0;
  367.             
  368.             /* compute display size of window */
  369.             uWidth = rcWindow.right - rcWindow.left;
  370.             uHeight = rcWindow.bottom - rcWindow.top;
  371.             
  372.             /* open clipboard */
  373.             if ( OpenClipboard(hActiveWnd) ) {
  374.                
  375.                /* empty clipboard */
  376.                EmptyClipboard();
  377.                
  378.                /* create screen DC & compatible memory DC's */
  379.                hScreenDC = CreateDC( "DISPLAY", NULL, NULL, NULL );
  380.                hMemoryDC = hScreenDC ?
  381.                            CreateCompatibleDC(hScreenDC) : NULL;
  382.                
  383.                /* create color or monochrome bitmap */
  384.                if (hMemoryDC && hScreenDC) {             
  385.                   hMemoryBitmap = CreateCompatibleBitmap(
  386.                      bMono ? hMemoryDC : hScreenDC,
  387.                      uWidth,
  388.                      uHeight
  389.                   );
  390.                } else
  391.                   hMemoryBitmap = NULL;
  392.                
  393.                if ( hMemoryBitmap ) {
  394.                   
  395.                   /* select bitmap & copy bits */
  396.                   hOldBitmap = SelectObject( hMemoryDC, hMemoryBitmap );
  397.                   BitBlt(
  398.                      hMemoryDC,              /* dest DC */
  399.                      0,                      /* X upper left */
  400.                      0,                      /* Y upper left */
  401.                      uWidth,                 /* dest width */
  402.                      uHeight,                /* dest height */
  403.                      hScreenDC,              /* source DC */
  404.                      rcWindow.left,          /* source X upper left */
  405.                      rcWindow.top,           /* source Y upper left */
  406.                      SRCCOPY                 /* ROP code */
  407.                   );
  408.                   SelectObject( hMemoryDC, hOldBitmap );
  409.                   SetClipboardData( CF_BITMAP, hMemoryBitmap );
  410.                   
  411.                } else
  412.                   MSGBOX( hWndDOS, "Insufficient memory!" );
  413.                
  414.                /* close clipboard */
  415.                CloseClipboard();
  416.                
  417.                /* delete DCs */
  418.                if ( hMemoryDC )
  419.                   DeleteDC( hMemoryDC );
  420.                if ( hScreenDC )
  421.                   DeleteDC( hScreenDC );
  422.                   
  423.             } else 
  424.                MSGBOX( hWndDOS, "Unable to open clipboard!" );
  425.     
  426.          } else 
  427.             MSGBOX( hWndDOS, "Active window is iconic!" );
  428.             
  429.       } else      
  430.          wDiscard = FALSE;
  431.          
  432.    } else 
  433.       wDiscard = (WORD)DefHookProc(
  434.          nCode,
  435.          wParam,
  436.          lParam,
  437.          (FARPROC FAR *)&lpfnOldHook
  438.       );
  439.    
  440.    /* return value */
  441.    return( wDiscard );
  442.    
  443. }
  444.