home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / os2 / button.cpp < prev    next >
C/C++ Source or Header  |  2002-12-27  |  14KB  |  451 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        button.cpp
  3. // Purpose:     wxButton
  4. // Author:      David Webster
  5. // Modified by:
  6. // Created:     10/13/99
  7. // RCS-ID:      $Id: BUTTON.CPP,v 1.21.2.1 2002/12/27 14:49:33 JS Exp $
  8. // Copyright:   (c) David Webster
  9. // Licence:     wxWindows licence
  10. /////////////////////////////////////////////////////////////////////////////
  11.  
  12. // For compilers that support precompilation, includes "wx.h".
  13. #include "wx/wxprec.h"
  14.  
  15. #ifndef WX_PRECOMP
  16.     #include "wx/app.h"
  17.     #include "wx/button.h"
  18.     #include "wx/brush.h"
  19.     #include "wx/panel.h"
  20.     #include "wx/bmpbuttn.h"
  21.     #include "wx/settings.h"
  22.     #include "wx/dcscreen.h"
  23.     #include "wx/scrolwin.h"
  24. #endif
  25.  
  26. #include "wx/os2/private.h"
  27.  
  28. #define BUTTON_HEIGHT_FROM_CHAR_HEIGHT(cy) (11*EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy)/10)
  29.  
  30. //
  31. // Should be at the very least less than winDEFAULT_BUTTON_MARGIN
  32. //
  33. #define FOCUS_MARGIN 3
  34.  
  35. #ifndef BST_CHECKED
  36. #define BST_CHECKED 0x0001
  37. #endif
  38.  
  39. IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl)
  40.  
  41. // Button
  42.  
  43. bool wxButton::Create(
  44.   wxWindow*                         pParent
  45. , wxWindowID                        vId
  46. , const wxString&                   rsLabel
  47. , const wxPoint&                    rPos
  48. , const wxSize&                     rSize
  49. , long                              lStyle
  50. , const wxValidator&                rValidator
  51. , const wxString&                   rsName
  52. )
  53. {
  54.     SetName(rsName);
  55. #if wxUSE_VALIDATORS
  56.     SetValidator(rValidator);
  57. #endif
  58.     m_windowStyle = lStyle;
  59.     pParent->AddChild((wxButton *)this);
  60.     if (vId == -1)
  61.         m_windowId = NewControlId();
  62.     else
  63.         m_windowId = vId;
  64.     lStyle = WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON;
  65.  
  66.     //
  67.     // OS/2 PM does not have Right/Left/Top/Bottom styles.
  68.     // We will have to define an additional style when we implement notebooks
  69.     // for a notebook page button
  70.     //
  71.     if (m_windowStyle & wxCLIP_SIBLINGS )
  72.         lStyle |= WS_CLIPSIBLINGS;
  73.  
  74.     m_hWnd = (WXHWND)::WinCreateWindow( GetHwndOf(pParent)   // Parent handle
  75.                                        ,WC_BUTTON            // A Button class window
  76.                                        ,(PSZ)rsLabel.c_str() // Button text
  77.                                        ,lStyle               // Button style
  78.                                        ,0, 0, 0, 0           // Location and size
  79.                                        ,GetHwndOf(pParent)   // Owner handle
  80.                                        ,HWND_TOP             // Top of Z-Order
  81.                                        ,vId                  // Identifier
  82.                                        ,NULL                 // No control data
  83.                                        ,NULL                 // No Presentation parameters
  84.                                       );
  85.     if (m_hWnd == 0)
  86.     {
  87.         return FALSE;
  88.     }
  89.  
  90.     //
  91.     // Subclass again for purposes of dialog editing mode
  92.     //
  93.     SubclassWin(m_hWnd);
  94.     wxFont*                          pButtonFont = new wxFont( 8
  95.                                                               ,wxSWISS
  96.                                                               ,wxNORMAL
  97.                                                               ,wxNORMAL
  98.                                                              );
  99.     SetFont(*pButtonFont);
  100.     SetXComp(0);
  101.     SetYComp(0);
  102.     SetSize( rPos.x
  103.             ,rPos.y
  104.             ,rSize.x
  105.             ,rSize.y
  106.            );
  107.     delete pButtonFont;
  108.     return TRUE;
  109. } // end of wxButton::Create
  110.  
  111. wxButton::~wxButton()
  112. {
  113.     wxPanel*                        pPanel = wxDynamicCast(GetParent(), wxPanel);
  114.  
  115.     if (pPanel)
  116.     {
  117.         if (pPanel->GetDefaultItem() == this)
  118.         {
  119.             //
  120.             // Don't leave the panel with invalid default item
  121.             //
  122.             pPanel->SetDefaultItem(NULL);
  123.         }
  124.     }
  125. } // end of wxButton::~wxButton
  126.  
  127. // ----------------------------------------------------------------------------
  128. // size management including autosizing
  129. // ----------------------------------------------------------------------------
  130.  
  131. wxSize wxButton::DoGetBestSize() const
  132. {
  133.     wxString                        rsLabel = wxGetWindowText(GetHWND());
  134.     int                             nWidthButton;
  135.     int                             nWidthChar;
  136.     int                             nHeightChar;
  137.  
  138.     GetTextExtent( rsLabel
  139.                   ,&nWidthButton
  140.                   ,NULL
  141.                  );
  142.  
  143.     wxGetCharSize( GetHWND()
  144.                   ,&nWidthChar
  145.                   ,&nHeightChar
  146.                   ,(wxFont*)&GetFont()
  147.                  );
  148.  
  149.     //
  150.     // Add a margin - the button is wider than just its label
  151.     //
  152.     nWidthButton += 3 * nWidthChar;
  153.  
  154.     //
  155.     // The button height is proportional to the height of the font used
  156.     //
  157.     int                             nHeightButton = BUTTON_HEIGHT_FROM_CHAR_HEIGHT(nHeightChar);
  158.  
  159.     //
  160.     // Need a little extra to make it look right
  161.     //
  162.     nHeightButton += nHeightChar/1.5;
  163.  
  164.     if (!HasFlag(wxBU_EXACTFIT))
  165.     {
  166.         wxSize                      vSize = GetDefaultSize();
  167.  
  168.         if (nWidthButton > vSize.x)
  169.             vSize.x = nWidthButton;
  170.         if (nHeightButton > vSize.y)
  171.             vSize.y = nHeightButton;
  172.         return vSize;
  173.     }
  174.     return wxSize( nWidthButton
  175.                   ,nHeightButton
  176.                  );
  177. } // end of wxButton::DoGetBestSize
  178.  
  179. /* static */
  180. wxSize wxButton::GetDefaultSize()
  181. {
  182.     static wxSize                   vSizeBtn;
  183.  
  184.     if (vSizeBtn.x == 0)
  185.     {
  186.         wxScreenDC                  vDc;
  187.  
  188.         vDc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
  189.  
  190.         //
  191.         // The size of a standard button in the dialog units is 50x14,
  192.         // translate this to pixels
  193.         // NB1: the multipliers come from the Windows convention
  194.         // NB2: the extra +1/+2 were needed to get the size be the same as the
  195.         //      size of the buttons in the standard dialog - I don't know how
  196.         //      this happens, but on my system this size is 75x23 in pixels and
  197.         //      23*8 isn't even divisible by 14... Would be nice to understand
  198.         //      why these constants are needed though!
  199.         vSizeBtn.x = (50 * (vDc.GetCharWidth() + 1))/4;
  200.         vSizeBtn.y = ((14 * vDc.GetCharHeight()) + 2)/8;
  201.     }
  202.     return vSizeBtn;
  203. } // end of wxButton::GetDefaultSize
  204.  
  205. void wxButton::Command (
  206.   wxCommandEvent&                   rEvent
  207. )
  208. {
  209.     ProcessCommand (rEvent);
  210. } // end of wxButton::Command
  211.  
  212. // ----------------------------------------------------------------------------
  213. // helpers
  214. // ----------------------------------------------------------------------------
  215.  
  216. bool wxButton::SendClickEvent()
  217. {
  218.     wxCommandEvent                  vEvent( wxEVT_COMMAND_BUTTON_CLICKED
  219.                                            ,GetId()
  220.                                           );
  221.  
  222.     vEvent.SetEventObject(this);
  223.     return ProcessCommand(vEvent);
  224. } // end of wxButton::SendClickEvent
  225.  
  226. void wxButton::SetDefault()
  227. {
  228.     wxWindow*                       pParent = GetParent();
  229.  
  230.     wxCHECK_RET( pParent, _T("button without parent?") );
  231.  
  232.     //
  233.     // Set this one as the default button both for wxWindows and Windows
  234.     //
  235.     wxWindow*                       pWinOldDefault = pParent->SetDefaultItem(this);
  236.  
  237.     SetDefaultStyle( wxDynamicCast(pWinOldDefault, wxButton)
  238.                     ,FALSE
  239.                    );
  240.     SetDefaultStyle( this
  241.                     ,TRUE
  242.                    );
  243. } // end of wxButton::SetDefault
  244.  
  245. void wxButton::SetTmpDefault()
  246. {
  247.     wxWindow*                       pParent = GetParent();
  248.  
  249.     wxCHECK_RET( pParent, _T("button without parent?") );
  250.  
  251.     wxWindow*                       pWinOldDefault = pParent->GetDefaultItem();
  252.  
  253.     pParent->SetTmpDefaultItem(this);
  254.     SetDefaultStyle( wxDynamicCast(pWinOldDefault, wxButton)
  255.                     ,FALSE
  256.                    );
  257.     SetDefaultStyle( this
  258.                     ,TRUE
  259.                    );
  260. } // end of wxButton::SetTmpDefault
  261.  
  262. void wxButton::UnsetTmpDefault()
  263. {
  264.     wxWindow*                       pParent = GetParent();
  265.  
  266.     wxCHECK_RET( pParent, _T("button without parent?") );
  267.  
  268.     pParent->SetTmpDefaultItem(NULL);
  269.  
  270.     wxWindow*                       pWinOldDefault = pParent->GetDefaultItem();
  271.  
  272.     SetDefaultStyle( this
  273.                     ,FALSE
  274.                    );
  275.     SetDefaultStyle( wxDynamicCast(pWinOldDefault, wxButton)
  276.                     ,TRUE
  277.                    );
  278. } // end of wxButton::UnsetTmpDefault
  279.  
  280. void wxButton::SetDefaultStyle(
  281.   wxButton*                         pBtn
  282. , bool                              bOn
  283. )
  284. {
  285.     long                            lStyle;
  286.     //
  287.     // We may be called with NULL pointer -- simpler to do the check here than
  288.     // in the caller which does wxDynamicCast()
  289.     //
  290.     if (!pBtn)
  291.         return;
  292.  
  293.     //
  294.     // First, let DefDlgProc() know about the new default button
  295.     //
  296.     if (bOn)
  297.     {
  298.         if (!wxTheApp->IsActive())
  299.             return;
  300.  
  301.         //
  302.         // In OS/2 the dialog/panel doesn't really know it has a default
  303.         // button, the default button simply has that style.  We'll just
  304.         // simulate by setting focus to it
  305.         //
  306.         pBtn->SetFocus();
  307.     }
  308.     lStyle = ::WinQueryWindowULong(GetHwndOf(pBtn), QWL_STYLE);
  309.     if (!(lStyle & BS_DEFAULT) == bOn)
  310.     {
  311.         if ((lStyle & BS_USERBUTTON) != BS_USERBUTTON)
  312.         {
  313.             if (bOn)
  314.                 lStyle | BS_DEFAULT;
  315.             else
  316.                 lStyle &= ~BS_DEFAULT;
  317.             ::WinSetWindowULong(GetHwndOf(pBtn), QWL_STYLE, lStyle);
  318.         }
  319.         else
  320.         {
  321.             //
  322.             // Redraw the button - it will notice itself that it's not the
  323.             // default one any longer
  324.             //
  325.             pBtn->Refresh();
  326.         }
  327.     }
  328. } // end of wxButton::UpdateDefaultStyle
  329.  
  330. // ----------------------------------------------------------------------------
  331. // event/message handlers
  332. // ----------------------------------------------------------------------------
  333.  
  334. bool wxButton::OS2Command(
  335.   WXUINT                            uParam
  336. , WXWORD                            wId
  337. )
  338. {
  339.     bool                            bProcessed = FALSE;
  340.  
  341.     switch (uParam)
  342.     {
  343.         case BN_CLICKED:            // normal buttons send this
  344.         case BN_DBLCLICKED:         // owner-drawn ones also send this
  345.             bProcessed = SendClickEvent();
  346.             break;
  347.     }
  348.     return bProcessed;
  349. } // end of wxButton::OS2Command
  350.  
  351. WXHBRUSH wxButton::OnCtlColor(
  352.   WXHDC                             pDC
  353. , WXHWND                            pWnd
  354. , WXUINT                            nCtlColor
  355. , WXUINT                            uMessage
  356. , WXWPARAM                          wParam
  357. , WXLPARAM                          lParam
  358. )
  359. {
  360.     wxBrush*                        pBackgroundBrush = wxTheBrushList->FindOrCreateBrush( GetBackgroundColour()
  361.                                                                                          ,wxSOLID
  362.                                                                                         );
  363.  
  364.     return (WXHBRUSH)pBackgroundBrush->GetResourceHandle();
  365. } // end of wxButton::OnCtlColor
  366.  
  367. void wxButton::MakeOwnerDrawn()
  368. {
  369.     long                            lStyle = 0L;
  370.  
  371.     lStyle = ::WinQueryWindowULong(GetHwnd(), QWL_STYLE);
  372.     if ((lStyle & BS_USERBUTTON) != BS_USERBUTTON)
  373.     {
  374.         //
  375.         // Make it so
  376.         //
  377.         lStyle |= BS_USERBUTTON;
  378.         ::WinSetWindowULong(GetHwnd(), QWL_STYLE, lStyle);
  379.     }
  380. } // end of wxButton::MakeOwnerDrawn
  381.  
  382. WXDWORD wxButton::OS2GetStyle(
  383.   long                              lStyle
  384. , WXDWORD*                          pdwExstyle
  385. ) const
  386. {
  387.     //
  388.     // Buttons never have an external border, they draw their own one
  389.     //
  390.     WXDWORD                         dwStyle = wxControl::OS2GetStyle( (lStyle & ~wxBORDER_MASK) | wxBORDER_NONE
  391.                                                                      ,pdwExstyle
  392.                                                                     );
  393.  
  394.     //
  395.     // We must use WS_CLIPSIBLINGS with the buttons or they would draw over
  396.     // each other in any resizeable dialog which has more than one button in
  397.     // the bottom
  398.     //
  399.     dwStyle |= WS_CLIPSIBLINGS;
  400.     return dwStyle;
  401. } // end of wxButton::OS2GetStyle
  402.  
  403. MRESULT wxButton::WindowProc(
  404.   WXUINT                            uMsg
  405. , WXWPARAM                          wParam
  406. , WXLPARAM                          lParam
  407. )
  408. {
  409.     //
  410.     // When we receive focus, we want to temporary become the default button in
  411.     // our parent panel so that pressing "Enter" would activate us -- and when
  412.     // losing it we should restore the previous default button as well
  413.     //
  414.     if (uMsg == WM_SETFOCUS)
  415.     {
  416.         if (SHORT1FROMMP(lParam) == TRUE)
  417.             SetTmpDefault();
  418.         else
  419.             UnsetTmpDefault();
  420.  
  421.         //
  422.         // Let the default processign take place too
  423.         //
  424.     }
  425.  
  426.     else if (uMsg == WM_BUTTON1DBLCLK)
  427.     {
  428.         //
  429.         // Emulate a click event to force an owner-drawn button to change its
  430.         // appearance - without this, it won't do it
  431.         //
  432.         (void)wxControl::OS2WindowProc( WM_BUTTON1DOWN
  433.                                        ,wParam
  434.                                        ,lParam
  435.                                       );
  436.  
  437.         //
  438.         // And conitnue with processing the message normally as well
  439.         //
  440.     }
  441.  
  442.     //
  443.     // Let the base class do all real processing
  444.     //
  445.     return (wxControl::OS2WindowProc( uMsg
  446.                                      ,wParam
  447.                                      ,lParam
  448.                                     ));
  449. } // end of wxWindowProc
  450.  
  451.