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 / chap13 / patron / pagewin.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  16KB  |  582 lines

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