home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / msj / msjv4_6 / spyglass / spyglass.c next >
Encoding:
C/C++ Source or Header  |  1989-11-07  |  15.8 KB  |  548 lines

  1. /*
  2.  * WINDOWS SPYGLASS - SOURCE CODE
  3.  *
  4.  * LANGUAGE      : Microsoft C5.1
  5.  * MODEL         : small
  6.  * ENVIRONMENT   : Microsoft Windows 2.1 SDK
  7.  * STATUS        : operational
  8.  *
  9.  * This module contains the window mainline and all other
  10.  * related source code for the sypglass application.
  11.  *
  12.  *    (C) Copyright 1988
  13.  *
  14.  *    Kevin P. Welch
  15.  *    Eikon Systems, Inc
  16.  *    989 East Hillsdale Blvd, Suite 260
  17.  *    Foster City, California 94404
  18.  *    415-349-4664
  19.  *
  20.  * 08/31/88 1.00 - Kevin P. Welch - initial creation.
  21.  *
  22.  */
  23.  
  24. #include <windows.h>
  25. #include <memory.h>
  26. #include "spyglass.h"
  27.  
  28. /* global data definitions */
  29. HANDLE   hCursor;          
  30. BOOL     bCapture;
  31. HWND     hWndNext;
  32. HDC      hScreenDC;
  33. RECT     rMagGlass;
  34. RECT     rSpyGlass;
  35. WORD     wEnlargement;
  36.  
  37. /* */
  38.  
  39. /*
  40.  * WinMain( hInstance, hPrevInstance, lpszCmd, wCmdShow ) : VOID
  41.  *
  42.  *    hInstance      current instance handle
  43.  *    hPrevInstance  previous instance handle
  44.  *    lpszCmd        current command line
  45.  *    wCmdShow       initial show window parameter
  46.  *
  47.  * This function is responsible for registering and creating
  48.  * the spyglass window.  Once the window has been created, it is
  49.  * also responsible for retrieving and dispatching all the
  50.  * messages related to the spyglass window.
  51.  *
  52.  */
  53.  
  54. VOID PASCAL WinMain(
  55.    HANDLE      hInstance,
  56.    HANDLE      hPrevInstance,
  57.    LPSTR       lpszCmd,
  58.    WORD        wCmdShow )
  59. {
  60.    /* local variables */
  61.    MSG         Msg;
  62.    HWND        hWnd;
  63.    WNDCLASS    WndClass;
  64.  
  65.    /* define desktop class */
  66.    memset( &WndClass, 0, sizeof(WNDCLASS) );
  67.    WndClass.lpszClassName =   (LPSTR)"SpyGlass";
  68.    WndClass.hCursor =         LoadCursor( NULL, IDC_ARROW );
  69.    WndClass.lpszMenuName =    (LPSTR)NULL;
  70.    WndClass.style =           CS_HREDRAW | CS_VREDRAW;
  71.    WndClass.lpfnWndProc =     SpyGlassWndFn;
  72.    WndClass.hInstance =       hInstance;
  73.    WndClass.hIcon =           LoadIcon( hInstance, "SpyGlassIcon" );
  74.    WndClass.hbrBackground =   (HBRUSH)(COLOR_BACKGROUND + 1);
  75.  
  76.    if ( (hPrevInstance) || (RegisterClass(&WndClass)) ) {
  77.  
  78.       /* create main window */
  79.       hWnd = CreateWindow(
  80.             "SpyGlass",              /* class name */
  81.             "SpyGlass",              /* caption */
  82.             SPYGLASS_STYLE,          /* style */
  83.             SPYGLASS_XPOS,           /* x position */
  84.             SPYGLASS_YPOS,           /* y position */
  85.             SPYGLASS_WIDTH,          /* width */
  86.             SPYGLASS_HEIGHT,         /* height */
  87.             (HWND)NULL,              /* parent window */
  88.             (HMENU)NULL,             /* menu */
  89.             hInstance,               /* application */
  90.             (LPSTR)NULL              /* other data */
  91.          );
  92.  
  93.       /* continue if successful */
  94.       if ( hWnd ) {
  95.       
  96.          /* display window */
  97.          ShowWindow( hWnd, wCmdShow );                  
  98.  
  99.          /* process messages */
  100.          while ( GetMessage((LPMSG)&Msg,NULL,0,0) ) {
  101.             TranslateMessage( (LPMSG)&Msg );
  102.             DispatchMessage( (LPMSG)&Msg );
  103.          }
  104.  
  105.          /* normal exit */
  106.          exit( Msg.wParam );  
  107.  
  108.       } else
  109.          WARNING( NULL, "Unable to create SpyGlass window!" );
  110.  
  111.    } else
  112.       WARNING( NULL, "Unable to register SpyGlass window!" );
  113.  
  114. }
  115.  
  116. /* */
  117.  
  118. /*
  119.  * SpyGlassWndFn( hWnd, wMessage, wParam, lParam ) : LONG
  120.  *
  121.  *    hWnd        window handle
  122.  *    wMessage    message number
  123.  *    wParam      additional message information
  124.  *    lParam      additional message information
  125.  *
  126.  * This window function processes all the messages related to
  127.  * the SpyGlass window.  Note that most of the operations
  128.  * performed by this function are done in screen coordinates.
  129.  *
  130.  */
  131.  
  132. LONG FAR PASCAL SpyGlassWndFn( hWnd, wMessage, wParam, lParam )
  133.    HWND        hWnd;
  134.    WORD        wMessage;
  135.    WORD        wParam;
  136.    LONG        lParam;
  137. {
  138.    /* local variables */
  139.    LONG        lResult;    
  140.  
  141.    /* initialization */
  142.    lResult = FALSE;
  143.    
  144.    /* process each message */
  145.    switch( wMessage )
  146.       {
  147.    case WM_CREATE : /* window being created */
  148.       {
  149.          HMENU    hSysMenu;
  150.       
  151.          /* intialization */
  152.          bCapture = FALSE;
  153.          wEnlargement = SC_8X;
  154.       
  155.          /* put ourselves in the viewer chain */
  156.          hWndNext = SetClipboardViewer( hWnd );
  157.  
  158.          /* add enlargement items to system menu */
  159.          hSysMenu = GetSystemMenu( hWnd, FALSE );
  160.  
  161.          ChangeMenu( hSysMenu, NULL, NULL, NULL, MF_SEPARATOR|MF_APPEND );
  162.          ChangeMenu( hSysMenu, NULL, "&1x Zoom", SC_1X, MF_APPEND );
  163.          ChangeMenu( hSysMenu, NULL, "&2x Zoom", SC_2X, MF_APPEND );
  164.          ChangeMenu( hSysMenu, NULL, "&4x Zoom", SC_4X, MF_APPEND );
  165.          ChangeMenu( hSysMenu, NULL, "&8x Zoom", SC_8X, MF_APPEND );
  166.          ChangeMenu( hSysMenu, NULL, "1&6x Zoom", SC_16X, MF_APPEND );
  167.  
  168.          CheckMenuItem( hSysMenu, wEnlargement, MF_CHECKED );
  169.       
  170.       }
  171.       break;
  172.    case WM_SYSCOMMAND : /* system command */
  173.  
  174.       /* process sub-message */
  175.       switch( wParam )
  176.          {
  177.       case SC_1X : /* change enlargement factor */
  178.       case SC_2X :
  179.       case SC_4X :
  180.       case SC_8X :
  181.       case SC_16X :
  182.          {
  183.             HMENU    hSysMenu;
  184.          
  185.             hSysMenu = GetSystemMenu( hWnd, FALSE );
  186.             CheckMenuItem( hSysMenu, wEnlargement, MF_UNCHECKED );
  187.             wEnlargement = wParam;
  188.             CheckMenuItem( hSysMenu, wEnlargement, MF_CHECKED );
  189.          }
  190.          break;
  191.       default :
  192.          lResult = DefWindowProc( hWnd, wMessage, wParam, lParam );
  193.          break;
  194.       }     
  195.       
  196.       break;
  197.    case WM_LBUTTONDOWN : /* mouse button down */
  198.    
  199.       /* start tracking if capture is off */
  200.       if ( bCapture == FALSE ) {
  201.  
  202.          POINT    ptWindow;
  203.          
  204.          /* start tracking mouse & hide cursor */
  205.          bCapture = TRUE;
  206.  
  207.          SetCapture( hWnd );
  208.          hCursor = SetCursor( NULL );
  209.  
  210.          /* retrieve viewport coordinates */
  211.          GetClientRect( hWnd, &rSpyGlass );
  212.  
  213.          /* redefine viewport in screen coordinates */
  214.          ptWindow.x = rSpyGlass.left;
  215.          ptWindow.y = rSpyGlass.top;
  216.          ClientToScreen( hWnd, &ptWindow );
  217.          rSpyGlass.left = ptWindow.x;
  218.          rSpyGlass.top = ptWindow.y;
  219.          rSpyGlass.right += rSpyGlass.left;
  220.          rSpyGlass.bottom += rSpyGlass.top;
  221.  
  222.          /* define magnifying glass - origin at mouse location */
  223.          ClientToScreen( hWnd, (LPPOINT)&lParam );
  224.  
  225.          rMagGlass.top = HIWORD(lParam);
  226.          rMagGlass.left = LOWORD(lParam);
  227.          rMagGlass.right = rMagGlass.left +
  228.                (WIDTH(rSpyGlass) / wEnlargement);
  229.          rMagGlass.bottom = rMagGlass.top +
  230.                (HEIGHT(rSpyGlass) / wEnlargement);
  231.  
  232.          /* display initial magnifying glass */
  233.          hScreenDC = CreateDC( "DISPLAY", NULL, NULL, NULL );
  234.  
  235.          SetROP2( hScreenDC, R2_NOT );
  236.          SetBkMode( hScreenDC, TRANSPARENT );
  237.  
  238.          Rectangle(
  239.             hScreenDC,
  240.             rMagGlass.left - 1,
  241.             rMagGlass.top - 1,
  242.             rMagGlass.right + 1,
  243.             rMagGlass.bottom + 1
  244.          );
  245.  
  246.       }
  247.  
  248.       break;
  249.    case WM_RBUTTONDOWN : /* right button clicked */
  250.  
  251.       /* grab screen image if capture is on */
  252.       if ( bCapture ) {
  253.       
  254.          BOOL     bIntersect;
  255.          RECT     rIntersect;
  256.  
  257.          /* determine viewport & magnifying glass intersect */
  258.          bIntersect = (BOOL)IntersectRect(
  259.                                  &rIntersect,
  260.                                  &rMagGlass,
  261.                                  &rSpyGlass
  262.                               );
  263.  
  264.          /* erase magnifying glass if intersection */
  265.          if ( bIntersect )
  266.             Rectangle(
  267.                hScreenDC,
  268.                rMagGlass.left - 1,
  269.                rMagGlass.top - 1,
  270.                rMagGlass.right + 1,
  271.                rMagGlass.bottom  + 1
  272.             );
  273.  
  274.          /* perform stretch or bit-blt - depending on enlargement */
  275.          if ( wEnlargement > 1 ) 
  276.             StretchBlt(
  277.                hScreenDC,
  278.                rSpyGlass.left,
  279.                rSpyGlass.top,
  280.                WIDTH(rSpyGlass),
  281.                HEIGHT(rSpyGlass),
  282.                hScreenDC,
  283.                rMagGlass.left,
  284.                rMagGlass.top,
  285.                WIDTH(rMagGlass),
  286.                HEIGHT(rMagGlass),
  287.                SRCCOPY
  288.             );
  289.          else
  290.             BitBlt(
  291.                hScreenDC,
  292.                rSpyGlass.left,
  293.                rSpyGlass.top,
  294.                WIDTH(rSpyGlass),
  295.                HEIGHT(rSpyGlass),
  296.                hScreenDC,
  297.                rMagGlass.left,
  298.                rMagGlass.top,
  299.                SRCCOPY
  300.             );
  301.  
  302.          /* restore magnifying glass if intersection */
  303.          if ( bIntersect )
  304.             Rectangle(
  305.                hScreenDC,
  306.                rMagGlass.left - 1,
  307.                rMagGlass.top - 1,
  308.                rMagGlass.right + 1,
  309.                rMagGlass.bottom  + 1
  310.             );
  311.  
  312.       } 
  313.  
  314.       break;
  315.    case WM_MOUSEMOVE : /* mouse being moved */
  316.       
  317.       /* move magnifying glass if capture is on */
  318.       if ( bCapture ) {
  319.       
  320.          BOOL     bIntersect;
  321.          RECT     rIntersect;
  322.  
  323.          /* convert mouse location to screen coordinates */
  324.          ClientToScreen( hWnd, (LPPOINT)&lParam );
  325.          
  326.          /* determine if viewport & magnifying glass intersect */
  327.          bIntersect = (BOOL)IntersectRect( 
  328.                                  &rIntersect,
  329.                                  &rMagGlass,
  330.                                  &rSpyGlass
  331.                               );
  332.  
  333.          /* erase old magnifying glass */
  334.          Rectangle(
  335.             hScreenDC,
  336.             rMagGlass.left - 1,
  337.             rMagGlass.top - 1,
  338.             rMagGlass.right + 1,
  339.             rMagGlass.bottom  + 1
  340.          );
  341.       
  342.          /* calculate new magnifying glass position */
  343.          rMagGlass.right -= rMagGlass.left;
  344.          rMagGlass.bottom -= rMagGlass.top;
  345.  
  346.          rMagGlass.top = HIWORD(lParam);
  347.          rMagGlass.left = LOWORD(lParam);
  348.  
  349.          rMagGlass.right += rMagGlass.left;
  350.          rMagGlass.bottom += rMagGlass.top;
  351.  
  352.          /* display new magnifying glass if no intersection */
  353.          if ( !bIntersect )
  354.             Rectangle(
  355.                hScreenDC,
  356.                rMagGlass.left - 1,
  357.                rMagGlass.top - 1,
  358.                rMagGlass.right + 1,
  359.                rMagGlass.bottom  + 1
  360.             );
  361.  
  362.          /* capture screen image if right button depressed */
  363.          if ( wParam&MK_RBUTTON ) {
  364.             if ( wEnlargement > 1 ) 
  365.                StretchBlt(
  366.                   hScreenDC,
  367.                   rSpyGlass.left,
  368.                   rSpyGlass.top,
  369.                   WIDTH(rSpyGlass),
  370.                   HEIGHT(rSpyGlass),
  371.                   hScreenDC,
  372.                   rMagGlass.left,
  373.                   rMagGlass.top,
  374.                   WIDTH(rMagGlass),
  375.                   HEIGHT(rMagGlass),
  376.                   SRCCOPY
  377.                );
  378.             else
  379.                BitBlt(
  380.                   hScreenDC,
  381.                   rSpyGlass.left,
  382.                   rSpyGlass.top,
  383.                   WIDTH(rSpyGlass),
  384.                   HEIGHT(rSpyGlass),
  385.                   hScreenDC,
  386.                   rMagGlass.left,
  387.                   rMagGlass.top,
  388.                   SRCCOPY
  389.                );
  390.  
  391.          }
  392.  
  393.          /* restore magnifying glass if intersection */
  394.          if ( bIntersect )
  395.             Rectangle(
  396.                hScreenDC,
  397.                rMagGlass.left - 1,
  398.                rMagGlass.top - 1,
  399.                rMagGlass.right + 1,
  400.                rMagGlass.bottom  + 1
  401.             );
  402.  
  403.       }
  404.  
  405.       break;
  406.    case WM_LBUTTONUP : /* mouse button up */
  407.  
  408.       /* stop tracking if capture is on */
  409.       if ( bCapture ) {
  410.  
  411.          HDC         hMemoryDC;
  412.          HBITMAP     hOldBitmap;
  413.          HBITMAP     hMemoryBitmap;
  414.       
  415.          /* turn off capture & restore cursor */
  416.          ReleaseCapture();
  417.          SetCursor( hCursor );
  418.  
  419.          /* erase magnifying glass */
  420.          Rectangle(
  421.             hScreenDC,
  422.             rMagGlass.left - 1,
  423.             rMagGlass.top - 1,
  424.             rMagGlass.right + 1,
  425.             rMagGlass.bottom + 1
  426.          );
  427.  
  428.          /* copy viewport image to clipboard */
  429.          hMemoryDC = CreateCompatibleDC( hScreenDC );
  430.          if ( hMemoryDC ) {
  431.  
  432.             hMemoryBitmap = CreateCompatibleBitmap(
  433.                                  hScreenDC,
  434.                                  WIDTH(rSpyGlass), 
  435.                                  HEIGHT(rSpyGlass)
  436.                               );
  437.  
  438.             if ( hMemoryBitmap ) {
  439.                
  440.                hOldBitmap = SelectObject( hMemoryDC, hMemoryBitmap );
  441.                BitBlt(
  442.                   hMemoryDC,
  443.                   0,
  444.                   0,
  445.                   WIDTH(rSpyGlass),
  446.                   HEIGHT(rSpyGlass),
  447.                   hScreenDC,
  448.                   rSpyGlass.left,
  449.                   rSpyGlass.top,
  450.                   SRCCOPY
  451.                );
  452.                
  453.                SelectObject( hMemoryDC, hOldBitmap );
  454.                
  455.                if ( OpenClipboard(hWnd) ) {
  456.                   EmptyClipboard();
  457.                   SetClipboardData( CF_BITMAP, hMemoryBitmap );
  458.                   CloseClipboard();
  459.                } else {
  460.                   DeleteObject( hMemoryBitmap );
  461.                   WARNING( hWnd, "Unable to open clipboard!" );
  462.                }
  463.  
  464.             } else
  465.                WARNING( hWnd, "Insufficient memory for bitmap!" );
  466.  
  467.             /* mark capture off & delete DC */
  468.             bCapture = FALSE;
  469.             DeleteDC( hMemoryDC );
  470.  
  471.          } else
  472.             WARNING( hWnd, "Insufficient memory to copy bitmap!" );
  473.  
  474.          /* delete screen display context */
  475.          DeleteDC( hScreenDC );
  476.  
  477.       } 
  478.       
  479.       break;
  480.    case WM_PAINT : /* paint the display window */
  481.  
  482.       {
  483.          PAINTSTRUCT    Ps;
  484.          BITMAP         Bm;
  485.          HBITMAP        hBitmap;
  486.          HDC            hMemoryDC;
  487.          HDC            hDisplayDC;
  488.  
  489.          hDisplayDC = BeginPaint( hWnd, &Ps );
  490.          if ( OpenClipboard(hWnd) ) {
  491.             if ( hBitmap = GetClipboardData(CF_BITMAP) ) {
  492.                hMemoryDC = CreateCompatibleDC( hDisplayDC );
  493.                SelectObject( hMemoryDC, hBitmap );
  494.                GetObject( hBitmap, sizeof(BITMAP), (LPSTR)&Bm );
  495.                BitBlt(
  496.                   hDisplayDC,
  497.                   0,
  498.                   0,
  499.                   Bm.bmWidth,
  500.                   Bm.bmHeight,
  501.                   hMemoryDC,
  502.                   0,
  503.                   0,
  504.                   SRCCOPY
  505.                );
  506.                DeleteDC( hMemoryDC );
  507.             }
  508.             CloseClipboard();
  509.          }
  510.          EndPaint( hWnd, &Ps );
  511.       }
  512.       
  513.       break;
  514.    case WM_DRAWCLIPBOARD : /* clipboard contents changing */
  515.       
  516.       /* pass the message down the chain */
  517.       if ( hWndNext )
  518.          SendMessage( hWndNext, wMessage, wParam, lParam );
  519.  
  520.       /* force repaint of display */
  521.       if ( bCapture == FALSE )
  522.          InvalidateRect( hWnd, NULL, TRUE );
  523.  
  524.       break;
  525.    case WM_CHANGECBCHAIN : /* clipboard chain changing */
  526.  
  527.       /* re-link viewer chain */
  528.       if ( wParam == hWndNext )
  529.          hWndNext = LOWORD(lParam);
  530.       else
  531.          if ( hWndNext )
  532.             SendMessage( hWndNext, wMessage, wParam, lParam );
  533.  
  534.       break;
  535.    case WM_DESTROY : /* destroy window */
  536.       ChangeClipboardChain( hWnd, hWndNext );
  537.       PostQuitMessage( 0 );
  538.       break;
  539.    default : /* send to default */
  540.       lResult = DefWindowProc( hWnd, wMessage, wParam, lParam );
  541.       break;
  542.    }
  543.    
  544.    /* return normal result */
  545.    return( lResult );
  546.  
  547. }
  548.