lnkprev.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 15k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*++
  2. Copyright (c) 1992  Microsoft Corporation
  3. Module Name:
  4.     preview.c
  5. Abstract:
  6.     This module contains the code for console preview window
  7. Author:
  8.     Therese Stowell (thereses) Feb-3-1992 (swiped from Win3.1)
  9. Revision History:
  10. --*/
  11. #include "shellprv.h"
  12. #pragma hdrstop
  13. #include "lnkcon.h"
  14. /* ----- Equates ----- */
  15. LONG CnslAspectScale( LONG n1, LONG n2, LONG m );
  16. void CnslAspectPoint( LPCONSOLEPROP_DATA pcpd, RECT* rectPreview, POINT* pt);
  17. VOID
  18. UpdatePreviewRect( LPCONSOLEPROP_DATA pcpd )
  19. /*++
  20.     Update the global window size and dimensions
  21. --*/
  22. {
  23.     POINT MinSize;
  24.     POINT MaxSize;
  25.     POINT WindowSize;
  26.     PFONT_INFO lpFont;
  27.     HMONITOR hMonitor;
  28.     MONITORINFO mi;
  29.     /*
  30.      * Get the font pointer
  31.      */
  32.     lpFont = &pcpd->FontInfo[pcpd->CurrentFontIndex];
  33.     /*
  34.      * Get the window size
  35.      */
  36.     MinSize.x = (GetSystemMetrics(SM_CXMIN)-pcpd->NonClientSize.x) / lpFont->Size.X;
  37.     MinSize.y = (GetSystemMetrics(SM_CYMIN)-pcpd->NonClientSize.y) / lpFont->Size.Y;
  38.     MaxSize.x = GetSystemMetrics(SM_CXFULLSCREEN) / lpFont->Size.X;
  39.     MaxSize.y = GetSystemMetrics(SM_CYFULLSCREEN) / lpFont->Size.Y;
  40.     WindowSize.x = max(MinSize.x, min(MaxSize.x, pcpd->lpConsole->dwWindowSize.X));
  41.     WindowSize.y = max(MinSize.y, min(MaxSize.y, pcpd->lpConsole->dwWindowSize.Y));
  42.     /*
  43.      * Get the window rectangle, making sure it's at least twice the
  44.      * size of the non-client area.
  45.      */
  46.     pcpd->WindowRect.left = pcpd->lpConsole->dwWindowOrigin.X;
  47.     pcpd->WindowRect.top = pcpd->lpConsole->dwWindowOrigin.Y;
  48.     pcpd->WindowRect.right = WindowSize.x * lpFont->Size.X + pcpd->NonClientSize.x;
  49.     if (pcpd->WindowRect.right < pcpd->NonClientSize.x * 2) {
  50.         pcpd->WindowRect.right = pcpd->NonClientSize.x * 2;
  51.     }
  52.     pcpd->WindowRect.right += pcpd->WindowRect.left;
  53.     pcpd->WindowRect.bottom = WindowSize.y * lpFont->Size.Y + pcpd->NonClientSize.y;
  54.     if (pcpd->WindowRect.bottom < pcpd->NonClientSize.y * 2) {
  55.         pcpd->WindowRect.bottom = pcpd->NonClientSize.y * 2;
  56.     }
  57.     pcpd->WindowRect.bottom += pcpd->WindowRect.top;
  58.     /*
  59.      * Get information about the monitor we're on
  60.      */
  61.     hMonitor = MonitorFromRect(&pcpd->WindowRect, MONITOR_DEFAULTTONEAREST);
  62.     mi.cbSize = sizeof(mi);
  63.     GetMonitorInfo(hMonitor, &mi);
  64.     pcpd->xScreen = mi.rcWork.right - mi.rcWork.left;
  65.     pcpd->yScreen = mi.rcWork.bottom - mi.rcWork.top;
  66.     /*
  67.      * Convert window rectangle to monitor relative coordinates
  68.      */
  69.     pcpd->WindowRect.right  -= pcpd->WindowRect.left;
  70.     pcpd->WindowRect.left   -= mi.rcWork.left;
  71.     pcpd->WindowRect.bottom -= pcpd->WindowRect.top;
  72.     pcpd->WindowRect.top    -= mi.rcWork.top;
  73.     /*
  74.      * Update the display flags
  75.      */
  76.     if (WindowSize.x < pcpd->lpConsole->dwScreenBufferSize.X) {
  77.         pcpd->PreviewFlags |= PREVIEW_HSCROLL;
  78.     } else {
  79.         pcpd->PreviewFlags &= ~PREVIEW_HSCROLL;
  80.     }
  81.     if (WindowSize.y < pcpd->lpConsole->dwScreenBufferSize.Y) {
  82.         pcpd->PreviewFlags |= PREVIEW_VSCROLL;
  83.     } else {
  84.         pcpd->PreviewFlags &= ~PREVIEW_VSCROLL;
  85.     }
  86. }
  87. VOID
  88. InvalidatePreviewRect(HWND hWnd, LPCONSOLEPROP_DATA pcpd)
  89. /*++
  90.     Invalidate the area covered by the preview "window"
  91. --*/
  92. {
  93.     RECT rectWin;
  94.     RECT rectPreview;
  95.     /*
  96.      * Get the size of the preview "screen"
  97.      */
  98.     GetClientRect(hWnd, &rectPreview);
  99.     /*
  100.      * Get the dimensions of the preview "window" and scale it to the
  101.      * preview "screen"
  102.      */
  103.     rectWin.left   = pcpd->WindowRect.left;
  104.     rectWin.top    = pcpd->WindowRect.top;
  105.     rectWin.right  = pcpd->WindowRect.left + pcpd->WindowRect.right;
  106.     rectWin.bottom = pcpd->WindowRect.top + pcpd->WindowRect.bottom;
  107.     CnslAspectPoint( pcpd, &rectPreview, (POINT*)&rectWin.left);
  108.     CnslAspectPoint( pcpd, &rectPreview, (POINT*)&rectWin.right);
  109.     /*
  110.      * Invalidate the area covered by the preview "window"
  111.      */
  112.     InvalidateRect(hWnd, &rectWin, FALSE);
  113. }
  114. VOID
  115. PreviewPaint(
  116.     PAINTSTRUCT* pPS,
  117.     HWND hWnd,
  118.     LPCONSOLEPROP_DATA pcpd
  119.     )
  120. /*++
  121.     Paints the font preview.  This is called inside the paint message
  122.     handler for the preview window
  123. --*/
  124. {
  125.     RECT rectWin;
  126.     RECT rectPreview;
  127.     HBRUSH hbrFrame;
  128.     HBRUSH hbrTitle;
  129.     HBRUSH hbrOld;
  130.     HBRUSH hbrClient;
  131.     HBRUSH hbrBorder;
  132.     HBRUSH hbrButton;
  133.     HBRUSH hbrScroll;
  134.     HBRUSH hbrDesktop;
  135.     POINT ptButton;
  136.     POINT ptScroll;
  137.     HDC hDC;
  138.     HBITMAP hBitmap;
  139.     HBITMAP hBitmapOld;
  140.     COLORREF rgbClient;
  141.     /*
  142.      * Get the size of the preview "screen"
  143.      */
  144.     GetClientRect(hWnd, &rectPreview);
  145.     /*
  146.      * Get the dimensions of the preview "window" and scale it to the
  147.      * preview "screen"
  148.      */
  149.     rectWin = pcpd->WindowRect;
  150.     CnslAspectPoint( pcpd, &rectPreview, (POINT*)&rectWin.left);
  151.     CnslAspectPoint( pcpd, &rectPreview, (POINT*)&rectWin.right);
  152.     /*
  153.      * Compute the dimensions of some other window components
  154.      */
  155.     ptButton.x = GetSystemMetrics(SM_CXSIZE);
  156.     ptButton.y = GetSystemMetrics(SM_CYSIZE);
  157.     CnslAspectPoint( pcpd, &rectPreview, &ptButton);
  158.     ptButton.y *= 2;       /* Double the computed size for "looks" */
  159.     ptScroll.x = GetSystemMetrics(SM_CXVSCROLL);
  160.     ptScroll.y = GetSystemMetrics(SM_CYHSCROLL);
  161.     CnslAspectPoint( pcpd, &rectPreview, &ptScroll);
  162.     /*
  163.      * Create the memory device context
  164.      */
  165.     hDC = CreateCompatibleDC(pPS->hdc);
  166.     hBitmap = CreateCompatibleBitmap(pPS->hdc,
  167.                                      rectPreview.right,
  168.                                      rectPreview.bottom);
  169.     hBitmapOld = SelectObject(hDC, hBitmap);
  170.     /*
  171.      * Create the brushes
  172.      */
  173.     hbrBorder  = CreateSolidBrush(GetSysColor(COLOR_ACTIVEBORDER));
  174.     hbrTitle   = CreateSolidBrush(GetSysColor(COLOR_ACTIVECAPTION));
  175.     hbrFrame   = CreateSolidBrush(GetSysColor(COLOR_WINDOWFRAME));
  176.     hbrButton  = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
  177.     hbrScroll  = CreateSolidBrush(GetSysColor(COLOR_SCROLLBAR));
  178.     hbrDesktop = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));
  179.     rgbClient  = GetNearestColor(hDC, ScreenBkColor(pcpd));
  180.     hbrClient  = CreateSolidBrush(rgbClient);
  181.     /*
  182.      * Erase the clipping area
  183.      */
  184.     FillRect(hDC, &(pPS->rcPaint), hbrDesktop);
  185.     /*
  186.      * Fill in the whole window with the client brush
  187.      */
  188.     hbrOld = SelectObject(hDC, hbrClient);
  189.     PatBlt(hDC, rectWin.left, rectWin.top,
  190.            rectWin.right - 1, rectWin.bottom - 1, PATCOPY);
  191.     /*
  192.      * Fill in the caption bar
  193.      */
  194.     SelectObject(hDC, hbrTitle);
  195.     PatBlt(hDC, rectWin.left + 3, rectWin.top + 3,
  196.            rectWin.right - 7, ptButton.y - 2, PATCOPY);
  197.     /*
  198.      * Draw the "buttons"
  199.      */
  200.     SelectObject(hDC, hbrButton);
  201.     PatBlt(hDC, rectWin.left + 3, rectWin.top + 3,
  202.            ptButton.x, ptButton.y - 2, PATCOPY);
  203.     PatBlt(hDC, rectWin.left + rectWin.right - 4 - ptButton.x,
  204.            rectWin.top + 3,
  205.            ptButton.x, ptButton.y - 2, PATCOPY);
  206.     PatBlt(hDC, rectWin.left + rectWin.right - 4 - 2 * ptButton.x - 1,
  207.            rectWin.top + 3,
  208.            ptButton.x, ptButton.y - 2, PATCOPY);
  209.     SelectObject(hDC, hbrFrame);
  210.     PatBlt(hDC, rectWin.left + 3 + ptButton.x, rectWin.top + 3,
  211.            1, ptButton.y - 2, PATCOPY);
  212.     PatBlt(hDC, rectWin.left + rectWin.right - 4 - ptButton.x - 1,
  213.            rectWin.top + 3,
  214.            1, ptButton.y - 2, PATCOPY);
  215.     PatBlt(hDC, rectWin.left + rectWin.right - 4 - 2 * ptButton.x - 2,
  216.            rectWin.top + 3,
  217.            1, ptButton.y - 2, PATCOPY);
  218.     /*
  219.      * Draw the scrollbars
  220.      */
  221.     SelectObject(hDC, hbrScroll);
  222.     if (pcpd->PreviewFlags & PREVIEW_HSCROLL) {
  223.         PatBlt(hDC, rectWin.left + 3,
  224.                rectWin.top + rectWin.bottom - 4 - ptScroll.y,
  225.                rectWin.right - 7, ptScroll.y, PATCOPY);
  226.     }
  227.     if (pcpd->PreviewFlags & PREVIEW_VSCROLL) {
  228.         PatBlt(hDC, rectWin.left + rectWin.right - 4 - ptScroll.x,
  229.                rectWin.top + 1 + ptButton.y + 1,
  230.                ptScroll.x, rectWin.bottom - 6 - ptButton.y, PATCOPY);
  231.         if (pcpd->PreviewFlags & PREVIEW_HSCROLL) {
  232.             SelectObject(hDC, hbrFrame);
  233.             PatBlt(hDC, rectWin.left + rectWin.right - 5 - ptScroll.x,
  234.                    rectWin.top + rectWin.bottom - 4 - ptScroll.y,
  235.                    1, ptScroll.y, PATCOPY);
  236.             PatBlt(hDC, rectWin.left + rectWin.right - 4 - ptScroll.x,
  237.                    rectWin.top + rectWin.bottom - 5 - ptScroll.y,
  238.                    ptScroll.x, 1, PATCOPY);
  239.         }
  240.     }
  241.     /*
  242.      * Draw the interior window frame and caption frame
  243.      */
  244.     SelectObject(hDC, hbrFrame);
  245.     PatBlt(hDC, rectWin.left + 2, rectWin.top + 2,
  246.            1, rectWin.bottom - 5, PATCOPY);
  247.     PatBlt(hDC, rectWin.left + 2, rectWin.top + 2,
  248.            rectWin.right - 5, 1, PATCOPY);
  249.     PatBlt(hDC, rectWin.left + 2, rectWin.top + rectWin.bottom - 4,
  250.            rectWin.right - 5, 1, PATCOPY);
  251.     PatBlt(hDC, rectWin.left + rectWin.right - 4, rectWin.top + 2,
  252.            1, rectWin.bottom - 5, PATCOPY);
  253.     PatBlt(hDC, rectWin.left + 2, rectWin.top + 1 + ptButton.y,
  254.            rectWin.right - 5, 1, PATCOPY);
  255.     /*
  256.      * Draw the border
  257.      */
  258.     SelectObject(hDC, hbrBorder);
  259.     PatBlt(hDC, rectWin.left + 1, rectWin.top + 1,
  260.            1, rectWin.bottom - 3, PATCOPY);
  261.     PatBlt(hDC, rectWin.left + 1, rectWin.top + 1,
  262.            rectWin.right - 3, 1, PATCOPY);
  263.     PatBlt(hDC, rectWin.left + 1, rectWin.top + rectWin.bottom - 3,
  264.            rectWin.right - 3, 1, PATCOPY);
  265.     PatBlt(hDC, rectWin.left + rectWin.right - 3, rectWin.top + 1,
  266.            1, rectWin.bottom - 3, PATCOPY);
  267.     /*
  268.      * Draw the exterior window frame
  269.      */
  270.     SelectObject(hDC, hbrFrame);
  271.     PatBlt(hDC, rectWin.left, rectWin.top,
  272.            1, rectWin.bottom - 1, PATCOPY);
  273.     PatBlt(hDC, rectWin.left, rectWin.top,
  274.            rectWin.right - 1, 1, PATCOPY);
  275.     PatBlt(hDC, rectWin.left, rectWin.top + rectWin.bottom - 2,
  276.            rectWin.right - 1, 1, PATCOPY);
  277.     PatBlt(hDC, rectWin.left + rectWin.right - 2, rectWin.top,
  278.            1, rectWin.bottom - 1, PATCOPY);
  279.     /*
  280.      * Copy the memory device context to the screen device context
  281.      */
  282.     BitBlt(pPS->hdc, 0, 0, rectPreview.right, rectPreview.bottom,
  283.            hDC, 0, 0, SRCCOPY);
  284.     /*
  285.      * Clean up everything
  286.      */
  287.     SelectObject(hDC, hbrOld);
  288.     SelectObject(hDC, hBitmapOld);
  289.     DeleteObject(hbrBorder);
  290.     DeleteObject(hbrFrame);
  291.     DeleteObject(hbrTitle);
  292.     DeleteObject(hbrClient);
  293.     DeleteObject(hbrButton);
  294.     DeleteObject(hbrScroll);
  295.     DeleteObject(hbrDesktop);
  296.     DeleteObject(hBitmap);
  297.     DeleteDC(hDC);
  298. }
  299. #define LPCS_INDEX 0
  300. #define PCPD_INDEX sizeof(PVOID)
  301. LRESULT
  302. PreviewWndProc(
  303.     HWND hWnd,
  304.     UINT wMessage,
  305.     WPARAM wParam,
  306.     LPARAM lParam
  307.     )
  308. /*
  309.  * PreviewWndProc
  310.  *      Handles the preview window
  311.  */
  312. {
  313.     PAINTSTRUCT ps;
  314.     LPCREATESTRUCT lpcs;
  315.     RECT rcWindow;
  316.     LPCONSOLEPROP_DATA pcpd;
  317.     int cx;
  318.     int cy;
  319.     switch (wMessage) {
  320.     case WM_CREATE:
  321.         lpcs = (LPCREATESTRUCT)LocalAlloc( LPTR, SIZEOF( CREATESTRUCT ) );
  322.         if (lpcs)
  323.         {
  324.             CopyMemory( (PVOID)lpcs, (PVOID)lParam, SIZEOF( CREATESTRUCT ) );
  325.             SetWindowLongPtr( hWnd, LPCS_INDEX, (LONG_PTR)lpcs );
  326.         }
  327.         else
  328.             return 0;
  329.         break;
  330.     case CM_PREVIEW_INIT:
  331.         pcpd = (LPCONSOLEPROP_DATA)lParam;
  332.         SetWindowLongPtr( hWnd, PCPD_INDEX, (LONG_PTR)pcpd );
  333.         /*
  334.          * Figure out space used by non-client area
  335.          */
  336.         SetRect(&rcWindow, 0, 0, 50, 50);
  337.         AdjustWindowRect(&rcWindow, WS_OVERLAPPEDWINDOW, FALSE);
  338.         pcpd->NonClientSize.x = rcWindow.right - rcWindow.left - 50;
  339.         pcpd->NonClientSize.y = rcWindow.bottom - rcWindow.top - 50;
  340.         /*
  341.          * Compute the size of the preview "window"
  342.          */
  343.         UpdatePreviewRect( pcpd );
  344.         /*
  345.          * Scale the window so it has the same aspect ratio as the screen
  346.          */
  347.         lpcs = (LPCREATESTRUCT)GetWindowLongPtr( hWnd, LPCS_INDEX );
  348.         cx = lpcs->cx;
  349.         cy = CnslAspectScale( pcpd->yScreen, pcpd->xScreen, cx);
  350.         if (cy > lpcs->cy) {
  351.             cy = lpcs->cy;
  352.             cx = CnslAspectScale(pcpd->xScreen, pcpd->yScreen, cy);
  353.         }
  354.         MoveWindow(hWnd, lpcs->x, lpcs->y, cx, cy, TRUE);
  355.         break;
  356.     case WM_PAINT:
  357.         pcpd = (LPCONSOLEPROP_DATA)GetWindowLongPtr( hWnd, PCPD_INDEX );
  358.         BeginPaint(hWnd, &ps);
  359.         if (pcpd)
  360.             PreviewPaint(&ps, hWnd, pcpd);
  361.         EndPaint(hWnd, &ps);
  362.         break;
  363.     case CM_PREVIEW_UPDATE:
  364.         pcpd = (LPCONSOLEPROP_DATA)GetWindowLongPtr( hWnd, PCPD_INDEX );
  365.         if (pcpd)
  366.         {
  367.             InvalidatePreviewRect(hWnd, pcpd);
  368.             UpdatePreviewRect( pcpd );
  369.             /*
  370.              * Make sure the preview "screen" has the correct aspect ratio
  371.              */
  372.             GetWindowRect(hWnd, &rcWindow);
  373.             cx = rcWindow.right - rcWindow.left;
  374.             cy = CnslAspectScale(pcpd->yScreen, pcpd->xScreen, cx);
  375.             if (cy != rcWindow.bottom - rcWindow.top) {
  376.                 SetWindowPos(hWnd, NULL, 0, 0, cx, cy, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
  377.             }
  378.         
  379.             InvalidatePreviewRect(hWnd, pcpd);
  380.         }
  381.         break;
  382.     case WM_DESTROY:
  383.         lpcs = (LPCREATESTRUCT)GetWindowLongPtr( hWnd, LPCS_INDEX );
  384.         if (lpcs)
  385.             LocalFree( lpcs );
  386.         break;
  387.     default:
  388.         return DefWindowProc(hWnd, wMessage, wParam, lParam);
  389.     }
  390.     return 0L;
  391. }
  392. /*  CnslAspectScale
  393.  *      Performs the following calculation in LONG arithmetic to avoid
  394.  *      overflow:
  395.  *          return = n1 * m / n2
  396.  *      This can be used to make an aspect ration calculation where n1/n2
  397.  *      is the aspect ratio and m is a known value.  The return value will
  398.  *      be the value that corresponds to m with the correct apsect ratio.
  399.  */
  400. LONG
  401. CnslAspectScale(
  402.     LONG n1,
  403.     LONG n2,
  404.     LONG m)
  405. {
  406.     LONG Temp;
  407.     Temp = n1 * m + (n2 >> 1);
  408.     return Temp / n2;
  409. }
  410. /*  CnslAspectPoint
  411.  *      Scales a point to be preview-sized instead of screen-sized.
  412.  */
  413. void
  414. CnslAspectPoint(
  415.     LPCONSOLEPROP_DATA pcpd,
  416.     RECT* rectPreview,
  417.     POINT* pt
  418.     )
  419. {
  420.     pt->x = CnslAspectScale(rectPreview->right, pcpd->xScreen, pt->x);
  421.     pt->y = CnslAspectScale(rectPreview->bottom, pcpd->yScreen, pt->y);
  422. }