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

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