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

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * PAGEWIN.CPP
  3.  * Patron Chapter 1
  4.  *
  5.  * Window procedure for the Pages window and support functions.
  6.  * This window manages its own scrollbars and viewport and provides
  7.  * printing capabilities as well.
  8.  *
  9.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  10.  *
  11.  * Kraig Brockschmidt, Microsoft
  12.  * Internet  :  kraigb@microsoft.com
  13.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  14.  */
  15. #include "patron.h"
  16. /*
  17.  * PagesWndProc
  18.  *
  19.  * Purpose:
  20.  *  Window procedure for the Pages window.
  21.  */
  22. LRESULT APIENTRY PagesWndProc(HWND hWnd, UINT iMsg, WPARAM wParam
  23.     , LPARAM lParam)
  24.     {
  25.     PCPages         ppg;
  26.     PAINTSTRUCT     ps;
  27.     HDC             hDC;
  28.     int             iPos, iTmp;
  29.     int             iMin, iMax;
  30.     UINT            idScroll;
  31.     ppg=(PCPages)GetWindowLong(hWnd, PAGEWL_STRUCTURE);
  32.     switch (iMsg)
  33.         {
  34.         case WM_CREATE:
  35.             ppg=(PCPages)((LPCREATESTRUCT)lParam)->lpCreateParams;
  36.             SetWindowLong(hWnd, PAGEWL_STRUCTURE, (LONG)ppg);
  37.             ppg->m_hWnd=hWnd;
  38.             ppg->New();
  39.             break;
  40.         case WM_PAINT:
  41.             hDC=BeginPaint(hWnd, &ps);
  42.             //Draw only if we have a page to show.
  43.             if (0!=ppg->m_cPages)
  44.                 ppg->Draw(hDC, FALSE, FALSE);
  45.             EndPaint(hWnd, &ps);
  46.             break;
  47.         case WM_HSCROLL:
  48.         case WM_VSCROLL:
  49.             idScroll=(WM_HSCROLL==iMsg) ? SB_HORZ : SB_VERT;
  50.             iPos=GetScrollPos(hWnd, idScroll);
  51.             iTmp=iPos;
  52.             GetScrollRange(hWnd, idScroll, &iMin, &iMax);
  53.             switch (LOWORD(wParam))
  54.                 {
  55.                 case SB_LINEUP:     iPos -= 20;  break;
  56.                 case SB_PAGEUP:     iPos -=100;  break;
  57.                 case SB_LINEDOWN:   iPos += 20;  break;
  58.                 case SB_PAGEDOWN:   iPos +=100;  break;
  59.                 case SB_THUMBPOSITION:
  60.                     iPos=ScrollThumbPosition(wParam, lParam);
  61.                     break;
  62.                 //We don't want scrolling on this message.
  63.                 case SB_THUMBTRACK:
  64.                     return 0L;
  65.                 }
  66.             iPos=max(iMin, min(iPos, iMax));
  67.             if (iPos!=iTmp)
  68.                 {
  69.                 //Set the new position and scroll the window
  70.                 SetScrollPos(hWnd, idScroll, iPos, TRUE);
  71.                 if (SB_HORZ==idScroll)
  72.                     {
  73.                     ppg->m_xPos=iPos;
  74.                     ScrollWindow(hWnd, iTmp-iPos, 0, NULL, NULL);
  75.                     }
  76.                 else
  77.                     {
  78.                     ppg->m_yPos=iPos;
  79.                     ScrollWindow(hWnd, 0, iTmp-iPos, NULL, NULL);
  80.                     }
  81.                 }
  82.             break;
  83.         default:
  84.             return DefWindowProc(hWnd, iMsg, wParam, lParam);
  85.         }
  86.     return 0L;
  87.     }
  88. /*
  89.  * RectConvertMappings
  90.  *
  91.  * Purpose:
  92.  *  Converts the contents of a rectangle from device to logical
  93.  *  coordinates where the hDC defines the logical coordinates.
  94.  *
  95.  * Parameters:
  96.  *  pRect           LPRECT containing the rectangle to convert.
  97.  *  hDC             HDC describing the logical coordinate system.
  98.  *                  if NULL, uses a screen DC in MM_LOMETRIC.
  99.  *  fToDevice       BOOL TRUE to convert from uConv to device,
  100.  *                  FALSE to convert device to uConv.
  101.  *
  102.  * Return Value:
  103.  *  None
  104.  */
  105. void RectConvertMappings(LPRECT pRect, HDC hDC, BOOL fToDevice)
  106.     {
  107.     POINT   rgpt[2];
  108.     BOOL    fSysDC=FALSE;
  109.     if (NULL==pRect)
  110.         return;
  111.     rgpt[0].x=pRect->left;
  112.     rgpt[0].y=pRect->top;
  113.     rgpt[1].x=pRect->right;
  114.     rgpt[1].y=pRect->bottom;
  115.     if (NULL==hDC)
  116.         {
  117.         hDC=GetDC(NULL);
  118.         SetMapMode(hDC, MM_LOMETRIC);
  119.         fSysDC=TRUE;
  120.         }
  121.     if (fToDevice)
  122.         LPtoDP(hDC, rgpt, 2);
  123.     else
  124.         DPtoLP(hDC, rgpt, 2);
  125.     if (fSysDC)
  126.         ReleaseDC(NULL, hDC);
  127.     pRect->left=rgpt[0].x;
  128.     pRect->top=rgpt[0].y;
  129.     pRect->right=rgpt[1].x;
  130.     pRect->bottom=rgpt[1].y;
  131.     return;
  132.     }
  133. /*
  134.  * CPages::Draw
  135.  *
  136.  * Purpose:
  137.  *  Paints the current page in the pages window.
  138.  *
  139.  * Parameters:
  140.  *  hDC             HDC to draw on, could be a metafile or printer
  141.  *                  DC or any other type of DC.
  142.  *  fNoColor        BOOL indicating if we should use screen colors
  143.  *                  or printer colors (B&W).  Objects are printed
  144.  *                  as-is, however.  This is TRUE for printer DCs
  145.  *                  or print preview.
  146.  *  fPrinter        BOOL indicating if this is a printer DC in which
  147.  *                  case we eliminate some of the fancy drawing,
  148.  *                  like shadows on the page and so forth.
  149.  *
  150.  * Return Value:
  151.  *  None
  152.  */
  153. void CPages::Draw(HDC hDC, BOOL fNoColor, BOOL fPrinter)
  154.     {
  155.     RECT            rc, rcT;
  156.     UINT            uMM;
  157.     HPEN            hPen;
  158.     HBRUSH          hBrush;
  159.     HGDIOBJ         hObj1, hObj2;
  160.     COLORREF        cr;
  161.     TCHAR           szTemp[20];
  162.     UINT            cch;
  163.     SIZE            sz;
  164.     //Make sure the DC is in LOMETRIC
  165.     uMM=SetMapMode(hDC, MM_LOMETRIC);
  166.     if (!fPrinter)
  167.         {
  168.         /*
  169.          * We maintain a 6mm border around the page on the screen
  170.          * besides 12.7mm margins.  We also have to account for
  171.          * the scroll position with m_*Pos which are in pixels so
  172.          * we have to convert them.
  173.          */
  174.         SetRect(&rcT, m_xPos, m_yPos, 0, 0);
  175.         RectConvertMappings(&rcT, hDC, FALSE);
  176.         rc.left  = LOMETRIC_BORDER-rcT.left;
  177.         rc.top   =-LOMETRIC_BORDER-rcT.top;
  178.         }
  179.     else
  180.         {
  181.         /*
  182.          * We define the corner of the printed paper at a negative
  183.          * offset so rc.right and rc.bottom come out right below.
  184.          */
  185.         SetRect(&rc, -(int)m_xMarginLeft, m_yMarginTop, 0, 0);
  186.         }
  187.     rc.right=rc.left+m_cx+(m_xMarginLeft+m_xMarginRight);
  188.     rc.bottom=rc.top-m_cy-(m_yMarginTop+m_yMarginBottom);
  189.     //Draw a rect filled with the window color to show the page.
  190.     if (!fPrinter)
  191.         {
  192.         if (fNoColor)
  193.             {
  194.             //Black frame, white box for printed colors.
  195.             hPen  =CreatePen(PS_SOLID, 0, RGB(0,0,0));
  196.             hBrush=CreateSolidBrush(RGB(255, 255, 255));
  197.             }
  198.         else
  199.             {
  200.             //Normal colors on display
  201.             hPen=CreatePen(PS_SOLID, 0
  202.                 , GetSysColor(COLOR_WINDOWFRAME));
  203.             hBrush=CreateSolidBrush(GetSysColor(COLOR_WINDOW));
  204.             }
  205.         hObj1=SelectObject(hDC, hPen);
  206.         hObj2=SelectObject(hDC, hBrush);
  207.         //Paper boundary
  208.         Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom+1);
  209.         /*
  210.          * Draw a shadow on the *visual* bottom and right edges
  211.          * .5mm wide.  If the button shadow color and workspace
  212.          * colors match, then use black.  We always use black
  213.          * when printing as well.
  214.          */
  215.         if (fNoColor)
  216.             cr=RGB(0,0,0);
  217.         else
  218.             {
  219.             cr=GetSysColor(COLOR_BTNSHADOW);
  220.             if (GetSysColor(COLOR_APPWORKSPACE)==cr)
  221.                 cr=RGB(0,0,0);
  222.             }
  223.         cr=SetBkColor(hDC, cr);
  224.         SetRect(&rcT, rc.left+5, rc.bottom, rc.right+5,rc.bottom-5);
  225.         ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcT, NULL, 0, NULL);
  226.         SetRect(&rcT, rc.right, rc.top-5, rc.right+5, rc.bottom-5);
  227.         ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rcT, NULL, 0, NULL);
  228.         SetBkColor(hDC, cr);
  229.         SelectObject(hDC, hObj1);
  230.         SelectObject(hDC, hObj2);
  231.         DeleteObject(hBrush);
  232.         DeleteObject(hPen);
  233.         }
  234.     //Write the page number in the lower left corner
  235.     if (!fNoColor)
  236.         {
  237.         SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
  238.         SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
  239.         }
  240.     //Write the page number in our page font.
  241.     cch=wsprintf(szTemp, TEXT("Page %d"), m_iPageCur+1);
  242.     hObj1=SelectObject(hDC, m_hFont);
  243.     GetTextExtentPoint(hDC, szTemp, cch, &sz);
  244.     TextOut(hDC, rc.left+m_xMarginLeft
  245.         , rc.bottom+m_yMarginBottom+sz.cy, szTemp, cch);
  246.     SelectObject(hDC, hObj1);
  247.     //Rectangle to show border.
  248.     MoveToEx(hDC, rc.left+m_xMarginLeft, rc.top-m_yMarginTop, NULL);
  249.     LineTo(hDC, rc.left+m_xMarginLeft,   rc.bottom+m_yMarginBottom);
  250.     LineTo(hDC, rc.right-m_xMarginRight, rc.bottom+m_yMarginBottom);
  251.     LineTo(hDC, rc.right-m_xMarginRight, rc.top-m_yMarginTop);
  252.     LineTo(hDC, rc.left+m_xMarginLeft,   rc.top-m_yMarginTop);
  253.     SetMapMode(hDC, uMM);
  254.     return;
  255.     }
  256. /*
  257.  * CPages::UpdateScrollRanges
  258.  *
  259.  * Purpose:
  260.  *  Reset scrollbar ranges (horizontal and vertical) depending on
  261.  *  the window size and the page size.  This function may remove
  262.  *  the scrollbars altogether.
  263.  *
  264.  * Parameters:
  265.  *  None, but set m_cx, m_cy and size m_hWnd before calling.
  266.  *
  267.  * Return Value:
  268.  *  None
  269.  */
  270. void CPages::UpdateScrollRanges(void)
  271.     {
  272.     UINT        cxSB;   //Scrollbar width and height.
  273.     UINT        cySB;
  274.     UINT        cx, cy;
  275.     UINT        dx, dy;
  276.     UINT        u;
  277.     int         iMin, iMax;
  278.     RECT        rc;
  279.     BOOL        fHScroll;
  280.     BOOL        fVScroll;
  281.     BOOL        fWasThere;
  282.     GetClientRect(m_hWnd, &rc);
  283.     cx=rc.right-rc.left;
  284.     cy=rc.bottom-rc.top;
  285.     //Convert dimensions of the image in LOMETRIC to pixels.
  286.     SetRect(&rc, (m_cx+m_xMarginLeft+m_xMarginRight
  287.         +LOMETRIC_BORDER*2), (m_cy+m_yMarginTop
  288.         +m_yMarginBottom+LOMETRIC_BORDER*2), 0, 0);
  289.     RectConvertMappings(&rc, NULL, TRUE);
  290.     dx=rc.left;
  291.     dy=-rc.top;
  292.     //Assume that both scrollbars will be visible.
  293.     fHScroll=TRUE;
  294.     fVScroll=TRUE;
  295.     /*
  296.      * Determine:
  297.      *  1)  Which scrollbars are needed.
  298.      *  2)  How many divisions to give scrollbars so as to
  299.      *      only scroll as little as necessary.
  300.      */
  301.     //Scrollbar dimensions in our units.
  302.     cxSB=GetSystemMetrics(SM_CXVSCROLL);
  303.     cySB=GetSystemMetrics(SM_CYHSCROLL);
  304.     //Remove horizontal scroll if window >= cxPage+borders
  305.     if (cx >= dx)
  306.         fHScroll=FALSE;
  307.     /*
  308.      * If we still need a horizontal scroll, see if we need a
  309.      * vertical taking the height of the horizontal scroll into
  310.      * account.
  311.      */
  312.     u=fHScroll ? cySB : 0;
  313.     if ((cy-u) >= dy)
  314.         fVScroll=FALSE;
  315.     //Check if adding vert scrollbar necessitates a horz now.
  316.     u=fVScroll ? cxSB : 0;
  317.     fHScroll=((cx-u) < dx);
  318.     /*
  319.      * Modify cx,cy to reflect the new client area before scaling
  320.      * scrollbars.  We only affect the client size if there is a
  321.      * *change* in scrollbar status:  if the scrollbar was there
  322.      * but is no longer, then add to the client size; if it was
  323.      * not there but now is, then subtract.
  324.      */
  325.     //Change cx depending on vertical scrollbar change
  326.     GetScrollRange(m_hWnd, SB_VERT, &iMin, &iMax);
  327.     fWasThere=(0!=iMin || 0!=iMax);
  328.     if (fWasThere && !fVScroll)
  329.         cx+=cxSB;
  330.     if (!fWasThere && fVScroll)
  331.         cx-=cxSB;
  332.     //Change cy depending on horizontal scrollbar change
  333.     GetScrollRange(m_hWnd, SB_HORZ, &iMin, &iMax);
  334.     fWasThere=(0!=iMin || 0!=iMax);
  335.     if (fWasThere && !fHScroll)
  336.         cy+=cySB;
  337.     if (!fWasThere && fHScroll)
  338.         cy-=cySB;
  339.     /*
  340.      * Show/Hide the scrollbars if necessary and set the ranges.
  341.      * The range is the number of units of the page we cannot see.
  342.      */
  343.     if (fHScroll)
  344.         {
  345.         //Convert current scroll position to new range.
  346.         u=GetScrollPos(m_hWnd, SB_HORZ);
  347.         if (0!=u)
  348.             {
  349.             GetScrollRange(m_hWnd, SB_HORZ, &iMin, &iMax);
  350.             u=MulDiv(u, (dx-cx), (iMax-iMin));
  351.             }
  352.         SetScrollRange(m_hWnd, SB_HORZ, 0, dx-cx, FALSE);
  353.         SetScrollPos(m_hWnd, SB_HORZ, u, TRUE);
  354.         m_xPos=u;
  355.         }
  356.     else
  357.         {
  358.         SetScrollRange(m_hWnd, SB_HORZ, 0, 0, TRUE);
  359.         m_xPos=0;
  360.         }
  361.     if (fVScroll)
  362.         {
  363.         //Convert current scroll position to new range.
  364.         u=GetScrollPos(m_hWnd, SB_VERT);
  365.         if (0!=u)
  366.             {
  367.             GetScrollRange(m_hWnd, SB_VERT, &iMin, &iMax);
  368.             u=MulDiv(u, (dy-cy), (iMax-iMin));
  369.             }
  370.         SetScrollRange(m_hWnd, SB_VERT, 0, dy-cy, FALSE);
  371.         SetScrollPos(m_hWnd, SB_VERT, u, TRUE);
  372.         m_yPos=u;
  373.         }
  374.     else
  375.         {
  376.         SetScrollRange(m_hWnd, SB_VERT, 0, 0, TRUE);
  377.         m_yPos=0;
  378.         }
  379.     //Repaint to insure that changes to m_x/yPos are reflected
  380.     InvalidateRect(m_hWnd, NULL, TRUE);
  381.     return;
  382.     }