home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap07 / patron / pagewin.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  13KB  |  491 lines

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