ZOOMIN.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:20k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*                         Microsoft Confidential                           */
  4. /*                                                                          */
  5. /*                 Copyright (c) Microsoft Corp.  1987-1996                 */
  6. /*                           All Rights Reserved                            */
  7. /*                                                                          */
  8. /****************************************************************************/
  9. /****************************** Module Header *******************************
  10. * Module Name: zoomin.c
  11. *
  12. * Microsoft ZoomIn utility.  This tool magnifies a portion of the screen,
  13. * allowing you to see things at a pixel level.
  14. *
  15. * History:
  16. * 01/01/88                              Created.
  17. * 01/01/92                              Ported to NT.
  18. * 03/06/92                              Cleanup.
  19. *
  20. ****************************************************************************/
  21. #include "zoomin.h"
  22. CHAR szAppName[] = "ZoomIn";            // Aplication name.
  23. HINSTANCE ghInst;                       // Instance handle.
  24. HWND ghwndApp;                          // Main window handle.
  25. HANDLE ghaccelTable;                    // Main accelerator table.
  26. INT gnZoom = 4;                         // Zoom (magnification) factor.
  27. HPALETTE ghpalPhysical;                 // Handle to the physical palette.
  28. INT gcxScreenMax;                       // Width of the screen (less 1).
  29. INT gcyScreenMax;                       // Height of the screen (less 1).
  30. INT gcxZoomed;                          // Client width in zoomed pixels.
  31. INT gcyZoomed;                          // Client height in zoomed pixels.
  32. BOOL gfRefEnable = FALSE;               // TRUE if refresh is enabled.
  33. INT gnRefInterval = 20;                 // Refresh interval in 10ths of seconds.
  34. BOOL gfTracking = FALSE;                // TRUE if tracking is in progress.
  35. POINT gptZoom = {100, 100};             // The center of the zoomed area.
  36. /************************************************************************
  37. * WinMain
  38. *
  39. * Main entry point for the application.
  40. *
  41. * Arguments:
  42. *
  43. * History:
  44. *
  45. ************************************************************************/
  46. INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, INT nCmdShow)
  47. {
  48.     MSG msg;
  49.     if (!InitInstance(hInst, nCmdShow))
  50.         return FALSE;
  51.     /*     * Polling messages from event queue
  52.      */
  53.     while (GetMessage(&msg, NULL, 0, 0)) {
  54.         if (!TranslateAccelerator(ghwndApp, ghaccelTable, &msg)) {
  55.             TranslateMessage(&msg);
  56.             DispatchMessage(&msg);
  57.         }
  58.     }
  59.     return msg.wParam;
  60. }
  61. /************************************************************************
  62. * InitInstance
  63. *
  64. * Instance initialization for the app.
  65. *
  66. * Arguments:
  67. *
  68. * History:
  69. *
  70. ************************************************************************/
  71. BOOL InitInstance(
  72.     HINSTANCE hInst,
  73.     INT cmdShow)
  74. {
  75.     WNDCLASS wc;
  76.     INT dx;
  77.     INT dy;
  78.     DWORD flStyle;
  79.     RECT rc;
  80.     ghInst = hInst;
  81.     /*
  82.      * Register a class for the main application window.
  83.      */
  84.     wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  85.     wc.hIcon          = LoadIcon(hInst, "zoomin");
  86.     wc.lpszMenuName   = MAKEINTRESOURCE(IDMENU_ZOOMIN);
  87.     wc.lpszClassName  = szAppName;
  88.     wc.hbrBackground  = GetStockObject(BLACK_BRUSH);
  89.     wc.hInstance      = hInst;
  90.     wc.style          = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW;
  91.     wc.lpfnWndProc    = (WNDPROC)AppWndProc;
  92.     wc.cbWndExtra     = 0;
  93.     wc.cbClsExtra     = 0;
  94.     if (!RegisterClass(&wc))
  95.         return FALSE;
  96.     if (!(ghaccelTable = LoadAccelerators(hInst, MAKEINTRESOURCE(IDACCEL_ZOOMIN))))
  97.         return FALSE;
  98.     if (!(ghpalPhysical = CreatePhysicalPalette()))
  99.         return FALSE;
  100.     gcxScreenMax = GetSystemMetrics(SM_CXSCREEN) - 1;    gcyScreenMax = GetSystemMetrics(SM_CYSCREEN) - 1;
  101.     flStyle = WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_THICKFRAME |
  102.             WS_MINIMIZEBOX | WS_VSCROLL;
  103.     dx = 44 * gnZoom;
  104.     dy = 36 * gnZoom;
  105.     SetRect(&rc, 0, 0, dx, dy);
  106.     AdjustWindowRect(&rc, flStyle, TRUE);
  107.     ghwndApp = CreateWindow(szAppName, szAppName, flStyle,
  108.             CW_USEDEFAULT, 0, rc.right - rc.left, rc.bottom - rc.top,
  109.             NULL, NULL, hInst, NULL);
  110.     if (!ghwndApp)
  111.         return FALSE;
  112.     ShowWindow(ghwndApp, cmdShow);
  113.     return TRUE;
  114. }
  115. /************************************************************************
  116. * CreatePhysicalPalette
  117. *
  118. * Creates a palette for the app to use.  The palette references the
  119. * physical palette, so that it can properly display images grabbed
  120. * from palette managed apps.
  121. *
  122. * History:
  123. *
  124. ************************************************************************/
  125. HPALETTE CreatePhysicalPalette(VOID)
  126. {
  127.     PLOGPALETTE ppal;
  128.     HPALETTE hpal = NULL;
  129.     INT i;
  130.     ppal = (PLOGPALETTE)LocalAlloc(LPTR,
  131.             sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * NPAL);
  132.     if (ppal) {
  133.         ppal->palVersion = 0x300;
  134.         ppal->palNumEntries = NPAL;
  135.         for (i = 0; i < NPAL; i++) {
  136.             ppal->palPalEntry[i].peFlags = (BYTE)PC_EXPLICIT;
  137.             ppal->palPalEntry[i].peRed   = (BYTE)i;
  138.             ppal->palPalEntry[i].peGreen = (BYTE)0;
  139.             ppal->palPalEntry[i].peBlue  = (BYTE)0;
  140.         }
  141.         hpal = CreatePalette(ppal);
  142.         LocalFree(ppal);
  143.     }
  144.     return hpal;
  145. }
  146. /************************************************************************
  147. * AppWndProc
  148. *
  149. * Main window proc for the zoomin utility.
  150. *
  151. * Arguments:
  152. *   Standard window proc args.
  153. *
  154. * History:
  155. *
  156. ************************************************************************/
  157. LONG APIENTRY AppWndProc(
  158.     HWND hwnd,
  159.     UINT msg,
  160.     WPARAM wParam,
  161.     LPARAM lParam)
  162. {
  163.     PAINTSTRUCT ps;
  164.     HCURSOR hcurOld;
  165.     switch (msg) {
  166.         case WM_CREATE:
  167.             SetScrollRange(hwnd, SB_VERT, MIN_ZOOM, MAX_ZOOM, FALSE);
  168.             SetScrollPos(hwnd, SB_VERT, gnZoom, FALSE);
  169.             break;
  170.         case WM_TIMER:
  171.             /*
  172.              * Update on every timer message.  The cursor will be
  173.              * flashed to the hourglash for some visual feedback
  174.              * of when a snapshot is being taken.
  175.              */
  176.             hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  177.             DoTheZoomIn(NULL);
  178.             SetCursor(hcurOld);
  179.             break;
  180.         case WM_PAINT:
  181.             BeginPaint(hwnd, &ps);
  182.             DoTheZoomIn(ps.hdc);
  183.             EndPaint(hwnd, &ps);
  184.             return 0L;
  185.         case WM_SIZE:
  186.             CalcZoomedSize();
  187.             break;
  188.         case WM_LBUTTONDOWN:
  189.             ((gptZoom).x = (SHORT)LOWORD(lParam), (gptZoom).y = (SHORT)HIWORD(lParam));
  190.             ClientToScreen(hwnd, &gptZoom);
  191.             DrawZoomRect();
  192.             DoTheZoomIn(NULL);
  193.             SetCapture(hwnd);
  194.             gfTracking = TRUE;
  195.             break;
  196.         case WM_MOUSEMOVE:
  197.             if (gfTracking) {
  198.                 DrawZoomRect();
  199.                 ((gptZoom).x = (SHORT)LOWORD(lParam), (gptZoom).y = (SHORT)HIWORD(lParam));
  200.                 ClientToScreen(hwnd, &gptZoom);
  201.                 DrawZoomRect();
  202.                 DoTheZoomIn(NULL);
  203.             }
  204.             break;
  205.         case WM_LBUTTONUP:
  206.             if (gfTracking) {
  207.                 DrawZoomRect();
  208.                 ReleaseCapture();
  209.                 gfTracking = FALSE;
  210.             }
  211.             break;
  212.         case WM_VSCROLL:
  213.             switch (LOWORD(wParam)) {
  214.                 case SB_LINEDOWN:
  215.                     gnZoom++;
  216.                     break;
  217.                 case SB_LINEUP:
  218.                     gnZoom--;
  219.                     break;
  220.                 case SB_PAGEUP:
  221.                     gnZoom -= 2;
  222.                     break;
  223.                 case SB_PAGEDOWN:
  224.                     gnZoom += 2;
  225.                     break;
  226.                 case SB_THUMBPOSITION:
  227.                 case SB_THUMBTRACK:
  228.                     gnZoom = HIWORD(wParam);
  229.                     break;
  230.             }
  231.             gnZoom = BOUND(gnZoom, MIN_ZOOM, MAX_ZOOM);
  232.             SetScrollPos(hwnd, SB_VERT, gnZoom, TRUE);
  233.             CalcZoomedSize();
  234.             DoTheZoomIn(NULL);
  235.             break;
  236.         case WM_KEYDOWN:
  237.             switch (wParam) {
  238.                 case VK_UP:
  239.                 case VK_DOWN:
  240.                 case VK_LEFT:
  241.                 case VK_RIGHT:
  242.                     MoveView((INT)wParam, GetKeyState(VK_SHIFT) & 0x8000,
  243.                             GetKeyState(VK_CONTROL) & 0x8000);
  244.                     break;
  245.             }
  246.             break;
  247.         case WM_COMMAND:
  248.             switch (LOWORD(wParam)) {
  249.                 case MENU_EDIT_COPY:
  250.                     CopyToClipboard();
  251.                     break;
  252.                 case MENU_EDIT_REFRESH:
  253.                     DoTheZoomIn(NULL);
  254.                     break;
  255.                 case MENU_OPTIONS_REFRESHRATE:
  256.                     DialogBox(ghInst, (LPSTR)MAKEINTRESOURCE(DID_REFRESHRATE),
  257.                             hwnd, (WNDPROC)RefreshRateDlgProc);
  258.                     break;
  259.                 case MENU_HELP_ABOUT:
  260.                     DialogBox(ghInst, (LPSTR)MAKEINTRESOURCE(DID_ABOUT),
  261.                             hwnd, (WNDPROC)AboutDlgProc);
  262.                     break;
  263.                 default:
  264.                      break;
  265.             }
  266.             break;
  267.         case WM_CLOSE:
  268.             if (ghpalPhysical)
  269.                 DeleteObject(ghpalPhysical);
  270.             DestroyWindow(hwnd);
  271.             break;
  272.         case WM_DESTROY:
  273.             PostQuitMessage(0);
  274.             break;
  275.         default:
  276.             return DefWindowProc(hwnd, msg, wParam, lParam);
  277.     }
  278.     return 0L;
  279. }
  280. /************************************************************************
  281. * CalcZoomedSize
  282. *
  283. * Calculates some globals.  This routine needs to be called any
  284. * time that the size of the app or the zoom factor changes.
  285. *
  286. * History:
  287. *
  288. ************************************************************************/
  289. VOID CalcZoomedSize(VOID)
  290. {
  291.     RECT rc;
  292.     GetClientRect(ghwndApp, &rc);
  293.     gcxZoomed = (rc.right / gnZoom) + 1;
  294.     gcyZoomed = (rc.bottom / gnZoom) + 1;
  295. }
  296. /************************************************************************
  297. * DoTheZoomIn
  298. *
  299. * Does the actual paint of the zoomed image.
  300. *
  301. * Arguments:
  302. *   HDC hdc - If not NULL, this hdc will be used to paint with.
  303. *             If NULL, a dc for the apps window will be obtained.
  304. *
  305. * History:
  306. *
  307. ************************************************************************/
  308. VOID DoTheZoomIn(
  309.     HDC hdc)
  310. {
  311.     BOOL fRelease;
  312.     HPALETTE hpalOld = NULL;
  313.     HDC hdcScreen;
  314.     INT x;
  315.     INT y;
  316.     if (!hdc) {
  317.         hdc = GetDC(ghwndApp);
  318.         fRelease = TRUE;
  319.     }
  320.     else {
  321.         fRelease = FALSE;
  322.     }
  323.     if (ghpalPhysical) {
  324.         hpalOld = SelectPalette(hdc, ghpalPhysical, FALSE);
  325.         RealizePalette(hdc);
  326.     }
  327.     /*
  328.      * The point must not include areas outside the screen dimensions.
  329.      */
  330.     x = BOUND(gptZoom.x, gcxZoomed / 2, gcxScreenMax - (gcxZoomed / 2));
  331.     y = BOUND(gptZoom.y, gcyZoomed / 2, gcyScreenMax - (gcyZoomed / 2));
  332.     hdcScreen = GetDC(NULL);
  333.     SetStretchBltMode(hdc, COLORONCOLOR);
  334.     StretchBlt(hdc, 0, 0, gnZoom * gcxZoomed, gnZoom * gcyZoomed,
  335.             hdcScreen, x - gcxZoomed / 2,
  336.             y - gcyZoomed / 2, gcxZoomed, gcyZoomed, SRCCOPY);
  337.     ReleaseDC(NULL, hdcScreen);
  338.     if (hpalOld)
  339.         SelectPalette(hdc, hpalOld, FALSE);
  340.     if (fRelease)
  341.         ReleaseDC(ghwndApp, hdc);
  342. }
  343. /************************************************************************
  344. * MoveView
  345. *
  346. * This function moves the current view around.
  347. *
  348. * Arguments:
  349. *   INT nDirectionCode - Direction to move.  Must be VK_UP, VK_DOWN,
  350. *                        VK_LEFT or VK_RIGHT.
  351. *   BOOL fFast         - TRUE if the move should jump a larger increment.
  352. *                        If FALSE, the move is just one pixel.
  353. *   BOOL fPeg          - If TRUE, the view will be pegged to the screen
  354. *                        boundary in the specified direction.  This overides
  355. *                        the fFast parameter.
  356. *
  357. * History:
  358. *
  359. ************************************************************************/
  360. VOID MoveView(
  361.     INT nDirectionCode,
  362.     BOOL fFast,
  363.     BOOL fPeg)
  364. {
  365.     INT delta;
  366.     if (fFast)
  367.         delta = FASTDELTA;
  368.     else
  369.         delta = 1;
  370.     switch (nDirectionCode) {
  371.         case VK_UP:
  372.             if (fPeg)
  373.                 gptZoom.y = gcyZoomed / 2;
  374.             else
  375.                 gptZoom.y -= delta;
  376.             gptZoom.y = BOUND(gptZoom.y, 0, gcyScreenMax);
  377.             break;
  378.         case VK_DOWN:
  379.             if (fPeg)
  380.                 gptZoom.y = gcyScreenMax - (gcyZoomed / 2);
  381.             else
  382.                 gptZoom.y += delta;
  383.             gptZoom.y = BOUND(gptZoom.y, 0, gcyScreenMax);
  384.             break;
  385.         case VK_LEFT:
  386.             if (fPeg)
  387.                 gptZoom.x = gcxZoomed / 2;
  388.             else
  389.                 gptZoom.x -= delta;
  390.             gptZoom.x = BOUND(gptZoom.x, 0, gcxScreenMax);
  391.             break;
  392.         case VK_RIGHT:
  393.             if (fPeg)
  394.                 gptZoom.x = gcxScreenMax - (gcxZoomed / 2);
  395.             else
  396.                 gptZoom.x += delta;
  397.             gptZoom.x = BOUND(gptZoom.x, 0, gcxScreenMax);
  398.             break;
  399.     }
  400.     DoTheZoomIn(NULL);
  401. }
  402. /************************************************************************
  403. * DrawZoomRect
  404. *
  405. * This function draws the tracking rectangle.  The size and shape of
  406. * the rectangle will be proportional to the size and shape of the
  407. * app's client, and will be affected by the zoom factor as well.
  408. *
  409. * History:
  410. *
  411. ************************************************************************/
  412. VOID DrawZoomRect(VOID)
  413. {
  414.     HDC hdc;
  415.     RECT rc;
  416.     INT x;
  417.     INT y;
  418.     x = BOUND(gptZoom.x, gcxZoomed / 2, gcxScreenMax - (gcxZoomed / 2));
  419.     y = BOUND(gptZoom.y, gcyZoomed / 2, gcyScreenMax - (gcyZoomed / 2));
  420.     rc.left   = x - gcxZoomed / 2;
  421.     rc.top    = y - gcyZoomed / 2;
  422.     rc.right  = rc.left + gcxZoomed;
  423.     rc.bottom = rc.top + gcyZoomed;
  424.     InflateRect(&rc, 1, 1);
  425.     hdc = GetDC(NULL);
  426.     PatBlt(hdc, rc.left,    rc.top,     rc.right-rc.left, 1,  DSTINVERT);
  427.     PatBlt(hdc, rc.left,    rc.bottom,  1, -(rc.bottom-rc.top),   DSTINVERT);
  428.     PatBlt(hdc, rc.right-1, rc.top,     1,   rc.bottom-rc.top,   DSTINVERT);
  429.     PatBlt(hdc, rc.right,   rc.bottom-1, -(rc.right-rc.left), 1, DSTINVERT);
  430.     ReleaseDC(NULL, hdc);
  431. }
  432. /************************************************************************
  433. * EnableRefresh
  434. *
  435. * This function turns on or off the auto-refresh feature.
  436. *
  437. * Arguments:
  438. *   BOOL fEnable - TRUE to turn the refresh feature on, FALSE to
  439. *                  turn it off.
  440. *
  441. * History:
  442. *
  443. ************************************************************************/
  444. VOID EnableRefresh(
  445.     BOOL fEnable)
  446. {
  447.     if (fEnable) {
  448.         /*
  449.          * Already enabled.  Do nothing.
  450.          */
  451.         if (gfRefEnable)
  452.             return;
  453.         if (SetTimer(ghwndApp, IDTIMER_ZOOMIN, gnRefInterval * 100, NULL))
  454.             gfRefEnable = TRUE;
  455.     }
  456.     else {
  457.         /*
  458.          * Not enabled yet.  Do nothing.
  459.          */
  460.         if (!gfRefEnable)
  461.             return;
  462.         KillTimer(ghwndApp, IDTIMER_ZOOMIN);
  463.         gfRefEnable = FALSE;
  464.     }
  465. }
  466. /************************************************************************
  467. * CopyToClipboard
  468. *
  469. * This function copies the client area image of the app into the
  470. * clipboard.
  471. *
  472. * History:
  473. *
  474. ************************************************************************/
  475. VOID CopyToClipboard(VOID)
  476. {
  477.     HDC hdcSrc;
  478.     HDC hdcDst;
  479.     RECT rc;
  480.     HBITMAP hbm;
  481.     if (OpenClipboard(ghwndApp)) {
  482.         EmptyClipboard();
  483.         if (hdcSrc = GetDC(ghwndApp)) {
  484.             GetClientRect(ghwndApp, &rc);
  485.             if (hbm = CreateCompatibleBitmap(hdcSrc,
  486.                     rc.right - rc.left, rc.bottom - rc.top)) {
  487.                 if (hdcDst = CreateCompatibleDC(hdcSrc)) {
  488.                     /*
  489.                      * Calculate the dimensions of the bitmap and
  490.                      * convert them to tenths of a millimeter for
  491.                      * setting the size with the SetBitmapDimensionEx
  492.                      * call.  This allows programs like WinWord to
  493.                      * retrieve the bitmap and know what size to
  494.                      * display it as.
  495.                      */
  496.                     
  497. SetBitmapDimensionEx(hbm, (DWORD)((INT)(((DWORD)(rc.right - rc.left) * MM10PERINCH) / (DWORD)GetDeviceCaps(hdcSrc, LOGPIXELSX))), (DWORD)((INT)(((DWORD)(rc.bottom - rc.top) * MM10PERINCH) / (DWORD)GetDeviceCaps(hdcSrc, LOGPIXELSY))), NULL);
  498.                     SelectObject(hdcDst, hbm);
  499.                     BitBlt(hdcDst, 0, 0,
  500.                             rc.right - rc.left, rc.bottom - rc.top,
  501.                             hdcSrc, rc.left, rc.top, SRCCOPY);
  502.                     DeleteDC(hdcDst);
  503.                     SetClipboardData(CF_BITMAP, hbm);
  504.                 }
  505.                 else {
  506.                     DeleteObject(hbm);
  507.                 }
  508.             }
  509.             ReleaseDC(ghwndApp, hdcSrc);
  510.         }
  511.         CloseClipboard();
  512.     }
  513.     else {
  514.         MessageBeep(0);
  515.     }
  516. }
  517. /************************************************************************
  518. * AboutDlgProc
  519. *
  520. * This is the About Box dialog procedure.
  521. *
  522. * History:
  523. *
  524. ************************************************************************/
  525. BOOL APIENTRY AboutDlgProc(
  526.     HWND hwnd,
  527.     UINT msg,
  528.     WPARAM wParam,
  529.     LPARAM lParam)
  530. {
  531.     switch (msg) {
  532.         case WM_INITDIALOG:
  533.             return TRUE;
  534.         case WM_COMMAND:
  535.             EndDialog(hwnd, IDOK);
  536.             return TRUE;
  537.         default:
  538.             return FALSE;
  539.     }
  540. }
  541. /************************************************************************
  542. * RefreshRateDlgProc
  543. *
  544. * This is the Refresh Rate dialog procedure.
  545. *
  546. * History:
  547. *
  548. ************************************************************************/
  549. BOOL APIENTRY RefreshRateDlgProc(
  550.     HWND hwnd,
  551.     UINT msg,
  552.     WPARAM wParam,
  553.     LPARAM lParam)
  554. {
  555.     BOOL fTranslated;
  556.     switch (msg) {
  557.         case WM_INITDIALOG:
  558.             SendDlgItemMessage(hwnd, DID_REFRESHRATEINTERVAL, EM_LIMITTEXT,
  559.                     3, 0L);
  560.             SetDlgItemInt(hwnd, DID_REFRESHRATEINTERVAL, gnRefInterval, FALSE);
  561.             CheckDlgButton(hwnd, DID_REFRESHRATEENABLE, gfRefEnable ? 1 : 0);
  562.             return TRUE;
  563.         case WM_COMMAND:
  564.             switch (LOWORD(wParam)) {
  565.                 case IDOK:
  566.                     gnRefInterval = GetDlgItemInt(hwnd, DID_REFRESHRATEINTERVAL,
  567.                             &fTranslated, FALSE);
  568.                     /*
  569.                      * Stop any existing timers then start one with the
  570.                      * new interval if requested to.
  571.                      */
  572.                     EnableRefresh(FALSE);
  573.                     EnableRefresh(
  574.                             IsDlgButtonChecked(hwnd, DID_REFRESHRATEENABLE));
  575.                     EndDialog(hwnd, IDOK);
  576.                     break;
  577.                 case IDCANCEL:
  578.                     EndDialog(hwnd, IDCANCEL);
  579.                     break;
  580.             }
  581.             break;
  582.     }
  583.     return FALSE;
  584. }