home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / src / os2 / ownerdrw.cpp < prev    next >
C/C++ Source or Header  |  2002-06-04  |  13KB  |  415 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name:        msw/ownerdrw.cpp
  3. // Purpose:     implementation of wxOwnerDrawn class
  4. // Author:      David Webster
  5. // Modified by:
  6. // Created:     10/12/99
  7. // RCS-ID:      $Id: OWNERDRW.CPP,v 1.14 2002/05/21 04:20:43 DW Exp $
  8. // Copyright:   (c) David Webster
  9. // Licence:     wxWindows license
  10. ///////////////////////////////////////////////////////////////////////////////
  11.  
  12. #ifdef __GNUG__
  13. #pragma implementation
  14. #endif
  15.  
  16. // For compilers that support precompilation, includes "wx.h".
  17. #include "wx/wxprec.h"
  18.  
  19. #ifndef WX_PRECOMP
  20.   #include "wx/window.h"
  21.   #include "wx/msw/private.h"
  22.   #include "wx/font.h"
  23.   #include "wx/bitmap.h"
  24.   #include "wx/dcmemory.h"
  25.   #include "wx/menu.h"
  26.   #include "wx/utils.h"
  27. #endif
  28.  
  29. #if wxUSE_OWNER_DRAWN
  30.  
  31. #include "wx/ownerdrw.h"
  32. #include "wx/menuitem.h"
  33.  
  34.  
  35. // ============================================================================
  36. // implementation of wxOwnerDrawn class
  37. // ============================================================================
  38.  
  39. //
  40. // ctor
  41. // ----
  42. //
  43. wxOwnerDrawn::wxOwnerDrawn(
  44.   const wxString&                   rsStr
  45. , bool                              bCheckable
  46. , bool                              bMenuItem
  47. )
  48. : m_strName(rsStr)
  49. {
  50.     m_bCheckable   = bCheckable;
  51.     m_bOwnerDrawn  = FALSE;
  52.     m_nHeight      = 0;
  53.     m_nMarginWidth = ms_nLastMarginWidth;
  54.     if (wxNORMAL_FONT)
  55.         m_font = *wxNORMAL_FONT;
  56. } // end of wxOwnerDrawn::wxOwnerDrawn
  57.  
  58. size_t wxOwnerDrawn::ms_nDefaultMarginWidth = 15;
  59.  
  60. size_t wxOwnerDrawn::ms_nLastMarginWidth = ms_nDefaultMarginWidth;
  61.  
  62. //
  63. // Drawing
  64. // -------
  65. //
  66.  
  67. bool wxOwnerDrawn::OnMeasureItem(
  68.   size_t*                           pWidth
  69. , size_t*                           pHeight
  70. )
  71. {
  72.     wxMemoryDC                      vDC;
  73.  
  74.     vDC.SetFont(GetFont());
  75.  
  76.     wxString                        sStr = wxStripMenuCodes(m_strName);
  77.  
  78.     vDC.GetTextExtent( sStr
  79.                       ,(long *)pWidth
  80.                       ,(long *)pHeight
  81.                      );
  82.  
  83.     (*pHeight) = (*pHeight) + 2;
  84.     m_nHeight = *pHeight;        // remember height for use in OnDrawItem
  85.     return TRUE;
  86. } // end of wxOwnerDrawn::OnMeasureItem
  87.  
  88. // draw the item
  89. bool wxOwnerDrawn::OnDrawItem(
  90.   wxDC&                             rDC
  91. , const wxRect&                     rRect
  92. , wxODAction                        eAction
  93. , wxODStatus                        eStatus
  94. )
  95. {
  96.     //
  97.     // We do nothing on focus change
  98.     //
  99.     if (eAction == wxODFocusChanged )
  100.         return TRUE;
  101.  
  102.     //
  103.     // Select the font and draw the text
  104.     // ---------------------------------
  105.     //
  106.  
  107.     CHARBUNDLE                      vCbnd;
  108.     HPS                             hPS= rDC.GetHPS();
  109.     wxColour                        vColBack;
  110.     wxColour                        vColText;
  111.     COLORREF                        vRef;
  112.     RECTL                           vRect = {rRect.x + 4, rRect.y + 1, rRect.x + (rRect.width - 2), rRect.y + rRect.height};
  113.  
  114.     memset(&vCbnd, 0, sizeof(CHARBUNDLE));
  115.  
  116.     //
  117.     // Use default font if no font set
  118.     //
  119.     if (m_font.Ok())
  120.     {
  121.         m_font.RealizeResource();
  122.     }
  123.     else
  124.     {
  125.         ::GpiSetCharSet(hPS, LCID_DEFAULT);
  126.     }
  127.  
  128.     //
  129.     // Base on the status of the menu item pick the right colors
  130.     //
  131.     if (eStatus & wxODSelected)
  132.     {
  133.         wxColour                        vCol2("WHITE");
  134.         vColBack.Set( (unsigned char)0
  135.                      ,(unsigned char)0
  136.                      ,(unsigned char)160
  137.                     ); // no dark blue in color table
  138.         vColText = vCol2;
  139.     }
  140.     else if (eStatus & wxODDisabled)
  141.     {
  142.         vRef = (ULONG)::WinQuerySysColor( HWND_DESKTOP
  143.                                          ,SYSCLR_MENU // Light gray
  144.                                          ,0L
  145.                                         );
  146.         vColBack.Set( GetRValue(vRef)
  147.                      ,GetGValue(vRef)
  148.                      ,GetBValue(vRef)
  149.                     );
  150.         vRef = (ULONG)::WinQuerySysColor( HWND_DESKTOP
  151.                                          ,SYSCLR_MENUDISABLEDTEXT // dark gray
  152.                                          ,0L
  153.                                         );
  154.         vColText.Set( GetRValue(vRef)
  155.                      ,GetGValue(vRef)
  156.                      ,GetBValue(vRef)
  157.                     );
  158.     }
  159.     else
  160.     {
  161.         //
  162.         // Fall back to default colors if none explicitly specified
  163.         //
  164.         vRef = ::WinQuerySysColor( HWND_DESKTOP
  165.                                   ,SYSCLR_MENU  // we are using gray for all our window backgrounds in wxWindows
  166.                                   ,0L
  167.                                  );
  168.         vColBack.Set( GetRValue(vRef)
  169.                      ,GetGValue(vRef)
  170.                      ,GetBValue(vRef)
  171.                     );
  172.         vRef = ::WinQuerySysColor( HWND_DESKTOP
  173.                                   ,SYSCLR_WINDOWTEXT // Black
  174.                                   ,0L
  175.                                  );
  176.         vColText.Set( GetRValue(vRef)
  177.                      ,GetGValue(vRef)
  178.                      ,GetBValue(vRef)
  179.                     );
  180.     }
  181.  
  182.     rDC.SetTextBackground(vColBack);
  183.     rDC.SetTextForeground(vColText);
  184.     rDC.SetBackgroundMode(wxTRANSPARENT);
  185.     vCbnd.lColor     = vColText.GetPixel();
  186.     vCbnd.lBackColor = vColBack.GetPixel();
  187.     ::GpiSetAttrs( hPS
  188.                   ,PRIM_CHAR
  189.                   ,CBB_BACK_COLOR | CBB_COLOR
  190.                   ,0
  191.                   ,&vCbnd
  192.                  );
  193.     ::GpiSetBackMix( hPS
  194.                     ,BM_LEAVEALONE
  195.                    );
  196.  
  197.     //
  198.     // Paint the background
  199.     //
  200.     ::WinFillRect(hPS, &vRect, vColBack.GetPixel());
  201.  
  202.     //
  203.     // Determine where to draw and leave space for a check-mark.
  204.     //
  205.     int                             nX = rRect.x + GetMarginWidth();
  206.  
  207.     //
  208.     // Unfortunately, unlike Win32, PM has no owner drawn specific text
  209.     // drawing methods like ::DrawState that can cleanly handle accel
  210.     // pneumonics and deal, automatically, with various states, so we have
  211.     // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn
  212.     // strings either.  We cannot handle mneumonics either.  We display
  213.     // it, though, in hopes we can figure it out some day.
  214.     //
  215.  
  216.     //
  217.     // Display main text and accel text separately to allign better
  218.     //
  219.     wxString                        sTgt = "\t";
  220.     wxString                        sFullString = m_strName; // need to save the original text
  221.     wxString                        sAccel;
  222.     size_t                          nIndex;
  223.     size_t                          nWidth;
  224.     size_t                          nCharWidth;
  225.     size_t                          nHeight;
  226.     bool                            bFoundMneumonic = FALSE;
  227.     bool                            bFoundAccel = FALSE;
  228.  
  229.     //
  230.     // Deal with the tab, extracting the Accel text
  231.     //
  232.     nIndex = sFullString.Find(sTgt.c_str());
  233.     if (nIndex != -1)
  234.     {
  235.         bFoundAccel = TRUE;
  236.         sAccel = sFullString.Mid(nIndex + 1);
  237.         sFullString.Remove(nIndex);
  238.     }
  239.  
  240.     //
  241.     // Deal with the mneumonic character
  242.     //
  243.     sTgt = "~";
  244.     nIndex = sFullString.Find(sTgt.c_str());
  245.     if (nIndex != -1)
  246.     {
  247.         wxString                    sTmp = sFullString;
  248.  
  249.         bFoundMneumonic = TRUE;
  250.         sTmp.Remove(nIndex);
  251.         rDC.GetTextExtent( sTmp
  252.                           ,(long *)&nWidth
  253.                           ,(long *)&nHeight
  254.                          );
  255.         sTmp = sFullString[nIndex + 1];
  256.         rDC.GetTextExtent( sTmp
  257.                           ,(long *)&nCharWidth
  258.                           ,(long *)&nHeight
  259.                          );
  260.         sFullString.Replace(sTgt.c_str(), "", TRUE);
  261.     }
  262.  
  263.     //
  264.     // Draw the main item text sans the accel text
  265.     //
  266.     POINTL                      vPntStart = {nX, rRect.y + 4};
  267.     ::GpiCharStringAt( rDC.GetHPS()
  268.                       ,&vPntStart
  269.                       ,sFullString.length()
  270.                       ,(PCH)sFullString.c_str()
  271.                      );
  272.     if (bFoundMneumonic)
  273.     {
  274.         //
  275.         // Underline the mneumonic -- still won't work, but at least it "looks" right
  276.         //
  277.         wxPen                       vPen;
  278.         POINTL                      vPntEnd = {nX + nWidth + nCharWidth - 3, rRect.y + 2}; //CharWidth is bit wide
  279.  
  280.         vPntStart.x = nX + nWidth - 1;
  281.         vPntStart.y = rRect.y + 2; // Make it look pretty!
  282.         vPen = wxPen(vColText, 1, wxSOLID); // Assuming we are always black
  283.         rDC.SetPen(vPen);
  284.         ::GpiMove(hPS, &vPntStart);
  285.         ::GpiLine(hPS, &vPntEnd);
  286.     }
  287.  
  288.     //
  289.     // Now draw the accel text
  290.     //
  291.     if (bFoundAccel)
  292.     {
  293.         size_t                      nWidth;
  294.         size_t                      nHeight;
  295.  
  296.         rDC.GetTextExtent( sAccel
  297.                           ,(long *)&nWidth
  298.                           ,(long *)&nHeight
  299.                          );
  300.         //
  301.         // Back off the starting position from the right edge
  302.         //
  303.         vPntStart.x = rRect.width - (nWidth + 7);
  304.         vPntStart.y = rRect.y + 4;
  305.         ::GpiCharStringAt( rDC.GetHPS()
  306.                           ,&vPntStart
  307.                           ,sAccel.length()
  308.                           ,(PCH)sAccel.c_str()
  309.                          );
  310.     }
  311.  
  312.     //
  313.     // Draw the bitmap
  314.     // ---------------
  315.     //
  316.     if (IsCheckable() && !m_bmpChecked.Ok())
  317.     {
  318.         if (eStatus & wxODChecked)
  319.         {
  320.             RECTL                   vRect;
  321.             HBITMAP                 hBmpCheck = ::WinGetSysBitmap(HWND_DESKTOP, SBMP_MENUCHECK);
  322.  
  323.             vRect.xLeft   = rRect.x;
  324.             vRect.xRight  = rRect.x + GetMarginWidth();
  325.             vRect.yBottom = rRect.y;
  326.             vRect.yTop    = rRect.y + m_nHeight - 3;
  327.  
  328.             ::WinDrawBitmap( hPS             // PS for this menuitem
  329.                             ,hBmpCheck       // system checkmark
  330.                             ,NULL            // draw the whole bitmap
  331.                             ,(PPOINTL)&vRect // destination -- bottom left corner of the menuitem area
  332.                             ,0L              // ignored
  333.                             ,0L              // draw a bitmap
  334.                             ,DBM_NORMAL      // draw normal size
  335.                            );
  336.         }
  337.     }
  338.     else
  339.     {
  340.         //
  341.         // For uncheckable item we use only the 'checked' bitmap
  342.         //
  343.         wxBitmap                    vBmp(GetBitmap(IsCheckable() ? ((eStatus & wxODChecked) != 0) : TRUE));
  344.  
  345.         if (vBmp.Ok())
  346.         {
  347.  
  348.             wxMemoryDC              vDCMem(&rDC);
  349.             wxMemoryDC*             pOldDC = (wxMemoryDC*)vBmp.GetSelectedInto();
  350.  
  351.             if(pOldDC != NULL)
  352.             {
  353.                 vBmp.SetSelectedInto(NULL);
  354.             }
  355.             vDCMem.SelectObject(vBmp);
  356.  
  357.             //
  358.             // Center bitmap
  359.             //
  360.             int                     nBmpWidth = vBmp.GetWidth();
  361.             int                     nBmpHeight = vBmp.GetHeight();
  362.  
  363.             //
  364.             // There should be enough space!
  365.             //
  366.             wxASSERT((nBmpWidth <= rRect.width) && (nBmpHeight <= rRect.height));
  367.  
  368.             int                     nHeightDiff = m_nHeight - nBmpHeight;
  369.  
  370.             rDC.Blit( rRect.x + (GetMarginWidth() - nBmpWidth) / 2
  371.                      ,rRect.y + nHeightDiff / 2
  372.                      ,nBmpWidth
  373.                      ,nBmpHeight
  374.                      ,&vDCMem
  375.                      ,0
  376.                      ,0
  377.                      ,wxCOPY
  378.                      ,TRUE
  379.                     );
  380.  
  381.             if (eStatus & wxODSelected)
  382.             {
  383.                 RECT                vRectBmp = { rRect.x
  384.                                                 ,rRect.y
  385.                                                 ,rRect.x + GetMarginWidth() - 1
  386.                                                 ,rRect.y + m_nHeight - 1
  387.                                                };
  388.                 POINTL              vPnt1 = {rRect.x + 1, rRect.y + 3}; // Leave a little background border
  389.                 POINTL              vPnt2 = {rRect.x + GetMarginWidth(), rRect.y + m_nHeight - 3};
  390.  
  391.                 LINEBUNDLE          vLine;
  392.  
  393.                 vLine.lColor = vColBack.GetPixel();
  394.                 ::GpiSetAttrs( hPS
  395.                               ,PRIM_LINE
  396.                               ,LBB_COLOR
  397.                               ,0
  398.                               ,&vLine
  399.                              );
  400.                 ::GpiMove(hPS, &vPnt1);
  401.                 ::GpiBox( hPS
  402.                          ,DRO_OUTLINE
  403.                          ,&vPnt2
  404.                          ,0L
  405.                          ,0L
  406.                         );
  407.             }
  408.             vBmp.SetSelectedInto(NULL);
  409.         }
  410.     }
  411.     return TRUE;
  412. } // end of wxOwnerDrawn::OnDrawItem
  413.  
  414. #endif //wxUSE_OWNER_DRAWN
  415.