]>
git.saurik.com Git - wxWidgets.git/blob - src/os2/toolbar.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  19 #if wxUSE_TOOLBAR && wxUSE_TOOLBAR_NATIVE 
  20 #include "wx/toolbar.h" 
  23 #include "wx/os2/private.h" 
  25 #include "wx/app.h"         // for GetComCtl32Version 
  27 // ---------------------------------------------------------------------------- 
  29 // ---------------------------------------------------------------------------- 
  31 // these standard constants are not always defined in compilers headers 
  35     #define TBSTYLE_LIST            0x1000 
  36     #define TBSTYLE_FLAT            0x0800 
  37     #define TBSTYLE_TRANSPARENT     0x8000 
  39  // use TBSTYLE_TRANSPARENT if you use TBSTYLE_FLAT 
  43     #define TB_SETSTYLE             (WM_USER + 56) 
  44     #define TB_GETSTYLE             (WM_USER + 57) 
  48     #define TB_HITTEST              (WM_USER + 69) 
  51 // these values correspond to those used by comctl32.dll 
  52 #define DEFAULTBITMAPX   16 
  53 #define DEFAULTBITMAPY   15 
  54 #define DEFAULTBUTTONX   24 
  55 #define DEFAULTBUTTONY   24 
  56 #define DEFAULTBARHEIGHT 27 
  58 // ---------------------------------------------------------------------------- 
  59 // private function prototypes 
  60 // ---------------------------------------------------------------------------- 
  62 static void wxMapBitmap( HBITMAP hBitmap
 
  67 // ---------------------------------------------------------------------------- 
  69 // ---------------------------------------------------------------------------- 
  71 IMPLEMENT_DYNAMIC_CLASS(wxToolBar
, wxControl
) 
  73 BEGIN_EVENT_TABLE(wxToolBar
, wxToolBarBase
) 
  74     EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent
) 
  75     EVT_SYS_COLOUR_CHANGED(wxToolBar::OnSysColourChanged
) 
  78 // ---------------------------------------------------------------------------- 
  80 // ---------------------------------------------------------------------------- 
  82 class wxToolBarTool 
: public wxToolBarToolBase
 
  85     inline wxToolBarTool( wxToolBar
*      pTbar
 
  87                          ,const wxBitmap
& rBitmap1
 
  88                          ,const wxBitmap
& rBitmap2
 
  90                          ,wxObject
*       pClientData
 
  91                          ,const wxString
& rShortHelpString
 
  92                          ,const wxString
& rLongHelpString
 
  93                         ) : wxToolBarToolBase( pTbar
 
 106     inline wxToolBarTool( wxToolBar
* pTbar
 
 108                         ) : wxToolBarToolBase( pTbar
 
 115     // set/get the number of separators which we use to cover the space used by 
 116     // a control in the toolbar 
 117     inline void SetSeparatorsCount(size_t nCount
) { m_nSepCount 
= nCount
; } 
 118     inline size_t GetSeparatorsCount(void) const { return m_nSepCount
; } 
 125 // ============================================================================ 
 127 // ============================================================================ 
 129 // ---------------------------------------------------------------------------- 
 131 // ---------------------------------------------------------------------------- 
 133 wxToolBarToolBase
* wxToolBar::CreateTool( 
 135 , const wxBitmap
&                   rBitmap1
 
 136 , const wxBitmap
&                   rBitmap2
 
 138 , wxObject
*                         pClientData
 
 139 , const wxString
&                   rShortHelpString
 
 140 , const wxString
&                   rLongHelpString
 
 143     return(new wxToolBarTool( this 
 154 wxToolBarToolBase
* wxToolBar::CreateTool( 
 158     return(new wxToolBarTool( this 
 163 // ---------------------------------------------------------------------------- 
 164 // wxToolBar construction 
 165 // ---------------------------------------------------------------------------- 
 167 void wxToolBar::Init() 
 171     m_defaultWidth 
= DEFAULTBITMAPX
; 
 172     m_defaultHeight 
= DEFAULTBITMAPY
; 
 175 bool wxToolBar::Create( 
 178 , const wxPoint
&                    rPos
 
 179 , const wxSize
&                     rSize
 
 181 , const wxString
&                   rName
 
 184     // common initialisation 
 185     if (!CreateControl( pParent
 
 196     DWORD                           msflags 
= 0;      // WS_VISIBLE | WS_CHILD always included 
 200     if (lStyle & wxBORDER) 
 201         msflags |= WS_BORDER; 
 202     msflags |= TBSTYLE_TOOLTIPS; 
 204     if (style & wxTB_FLAT) 
 206         if (wxTheApp->GetComCtl32Version() > 400) 
 207             msflags |= TBSTYLE_FLAT; 
 210     // MSW-specific initialisation 
 211     if ( !wxControl::MSWCreateControl(TOOLBARCLASSNAME, msflags) ) 
 214     // toolbar-specific post initialisation 
 215     ::SendMessage(GetHwnd(), TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0); 
 217     // set up the colors and fonts 
 218     wxRGBToColour(m_backgroundColour, GetSysColor(COLOR_BTNFACE)); 
 219     m_foregroundColour = *wxBLACK; 
 221     SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT)); 
 232         height = m_defaultHeight; 
 238     SetSize(x, y, width, height); 
 243 wxToolBar::~wxToolBar() 
 247         ::GpiDeleteBitmap((HBITMAP
) m_hBitmap
); 
 251 // ---------------------------------------------------------------------------- 
 252 // adding/removing tools 
 253 // ---------------------------------------------------------------------------- 
 255 bool wxToolBar::DoInsertTool( 
 256   size_t                            WXUNUSED(nPos
) 
 257 , wxToolBarToolBase
*                pTool
 
 260     // nothing special to do here - we really create the toolbar buttons in 
 266 bool wxToolBar::DoDeleteTool( 
 268 , wxToolBarToolBase
*                pTool
 
 271     // normally, we only delete one button, but we use several separators to 
 272     // cover the space used by one control sometimes (with old comctl32.dll) 
 273     size_t                          nButtonsToDelete 
= 1; 
 275     // get the size of the button we're going to delete 
 280     if ( !::SendMessage(GetHwnd(), TB_GETITEMRECT, pos, (LPARAM)&r) ) 
 282         wxLogLastError(_T("TB_GETITEMRECT")); 
 285     int width = r.right - r.left; 
 287     if ( tool->IsControl() ) 
 289         nButtonsToDelete = ((wxToolBarTool *)tool)->GetSeparatorsCount(); 
 291         width *= nButtonsToDelete; 
 294     while ( nButtonsToDelete-- > 0 ) 
 296         if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, pos, 0) ) 
 298             wxLogLastError("TB_DELETEBUTTON"); 
 306     m_nButtons -= nButtonsToDelete; 
 308     // reposition all the controls after this button 
 309     wxToolBarToolsList::Node *node = m_tools.Item(pos); 
 310     for ( node = node->GetNext(); node; node = node->GetNext() ) 
 312         wxToolBarToolBase *tool2 = node->GetData(); 
 313         if ( tool2->IsControl() ) 
 316             wxControl *control = tool2->GetControl(); 
 317             control->GetPosition(&x, NULL); 
 318             control->Move(x - width, -1); 
 325 bool wxToolBar::Realize() 
 327     size_t                          nTools 
= GetToolsCount(); 
 335     bool                            bIsVertical 
= (GetWindowStyle() & wxTB_VERTICAL
) != 0; 
 339     // First, add the bitmap: we use one bitmap for all toolbar buttons 
 340     // ---------------------------------------------------------------- 
 342     // if we already have a bitmap, we'll replace the existing one - otherwise 
 343     // we'll install a new one 
 344     HBITMAP oldToolBarBitmap = (HBITMAP)m_hBitmap; 
 346     int totalBitmapWidth = (int)(m_defaultWidth * nTools); 
 347     int totalBitmapHeight = (int)m_defaultHeight; 
 349     // Create a bitmap for all the tool bitmaps 
 350     HBITMAP hBitmap = ::CreateCompatibleBitmap(ScreenHDC(), 
 355         wxLogLastError(_T("CreateCompatibleBitmap")); 
 360     m_hBitmap = (WXHBITMAP)hBitmap; 
 362     // Now blit all the tools onto this bitmap 
 363     HDC memoryDC = ::CreateCompatibleDC(NULL); 
 364     HBITMAP oldBitmap = (HBITMAP) ::SelectObject(memoryDC, hBitmap); 
 366     HDC memoryDC2 = ::CreateCompatibleDC(NULL); 
 368     // the button position 
 371     // the number of buttons (not separators) 
 374     wxToolBarToolsList::Node *node = m_tools.GetFirst(); 
 377         wxToolBarToolBase *tool = node->GetData(); 
 378         if ( tool->IsButton() ) 
 380             HBITMAP hbmp = GetHbitmapOf(tool->GetBitmap1()); 
 383                 HBITMAP oldBitmap2 = (HBITMAP)::SelectObject(memoryDC2, hbmp); 
 384                 if ( !BitBlt(memoryDC, x, 0,  m_defaultWidth, m_defaultHeight, 
 385                              memoryDC2, 0, 0, SRCCOPY) ) 
 387                     wxLogLastError("BitBlt"); 
 390                 ::SelectObject(memoryDC2, oldBitmap2); 
 394                 wxFAIL_MSG( _T("invalid tool button bitmap") ); 
 397             // still inc width and number of buttons because otherwise the 
 398             // subsequent buttons will all be shifted which is rather confusing 
 399             // (and like this you'd see immediately which bitmap was bad) 
 404         node = node->GetNext(); 
 407     ::SelectObject(memoryDC, oldBitmap); 
 408     ::DeleteDC(memoryDC); 
 409     ::DeleteDC(memoryDC2); 
 411     // Map to system colours 
 412     wxMapBitmap(hBitmap, totalBitmapWidth, totalBitmapHeight); 
 414     if ( oldToolBarBitmap ) 
 416         TBREPLACEBITMAP replaceBitmap; 
 417         replaceBitmap.hInstOld = NULL; 
 418         replaceBitmap.hInstNew = NULL; 
 419         replaceBitmap.nIDOld = (UINT) oldToolBarBitmap; 
 420         replaceBitmap.nIDNew = (UINT) hBitmap; 
 421         replaceBitmap.nButtons = nButtons; 
 422         if ( !::SendMessage(GetHwnd(), TB_REPLACEBITMAP, 
 423                             0, (LPARAM) &replaceBitmap) ) 
 425             wxFAIL_MSG(wxT("Could not add bitmap to toolbar")); 
 428         ::DeleteObject(oldToolBarBitmap); 
 430         // Now delete all the buttons 
 431         for ( size_t pos = 0; pos < m_nButtons; pos++ ) 
 433             if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, 0, 0) ) 
 435                 wxLogLastError("TB_DELETEBUTTON"); 
 439     else // no old bitmap 
 441         TBADDBITMAP addBitmap; 
 443         addBitmap.nID = (UINT) hBitmap; 
 444         if ( ::SendMessage(GetHwnd(), TB_ADDBITMAP, 
 445                            (WPARAM) nButtons, (LPARAM)&addBitmap) == -1 ) 
 447             wxFAIL_MSG(wxT("Could not add bitmap to toolbar")); 
 451     // Next add the buttons and separators 
 452     // ----------------------------------- 
 454     TBBUTTON *buttons = new TBBUTTON[nTools]; 
 456     // this array will hold the indices of all controls in the toolbar 
 457     wxArrayInt controlIds; 
 462     for ( node = m_tools.GetFirst(); node; node = node->GetNext() ) 
 464         wxToolBarToolBase *tool = node->GetData(); 
 466         // don't add separators to the vertical toolbar - looks ugly 
 467         if ( isVertical && tool->IsSeparator() ) 
 470         TBBUTTON& button = buttons[i]; 
 472         wxZeroMemory(button); 
 474         switch ( tool->GetStyle() ) 
 476             case wxTOOL_STYLE_CONTROL: 
 477                 button.idCommand = tool->GetId(); 
 478                 // fall through: create just a separator too 
 480             case wxTOOL_STYLE_SEPARATOR: 
 481                 button.fsState = TBSTATE_ENABLED; 
 482                 button.fsStyle = TBSTYLE_SEP; 
 485             case wxTOOL_STYLE_BUTTON: 
 486                 button.iBitmap = bitmapId; 
 487                 button.idCommand = tool->GetId(); 
 489                 if ( tool->IsEnabled() ) 
 490                     button.fsState |= TBSTATE_ENABLED; 
 491                 if ( tool->IsToggled() ) 
 492                     button.fsState |= TBSTATE_CHECKED; 
 494                 button.fsStyle = tool->CanBeToggled() ? TBSTYLE_CHECK 
 504     if ( !::SendMessage(GetHwnd(), TB_ADDBUTTONS, 
 505                         (WPARAM)i, (LPARAM)buttons) ) 
 507         wxLogLastError("TB_ADDBUTTONS"); 
 512     // Deal with the controls finally 
 513     // ------------------------------ 
 515     // adjust the controls size to fit nicely in the toolbar 
 517     for ( node = m_tools.GetFirst(); node; node = node->GetNext(), index++ ) 
 519         wxToolBarToolBase *tool = node->GetData(); 
 520         if ( !tool->IsControl() ) 
 523         wxControl *control = tool->GetControl(); 
 525         wxSize size = control->GetSize(); 
 527         // the position of the leftmost controls corner 
 530         // note that we use TB_GETITEMRECT and not TB_GETRECT because the 
 531         // latter only appeared in v4.70 of comctl32.dll 
 533         if ( !SendMessage(GetHwnd(), TB_GETITEMRECT, 
 534                           index, (LPARAM)(LPRECT)&r) ) 
 536             wxLogLastError("TB_GETITEMRECT"); 
 539         // TB_SETBUTTONINFO message is only supported by comctl32.dll 4.71+ 
 540         #if defined(_WIN32_IE) && (_WIN32_IE >= 0x400 ) 
 541             // available in headers, now check whether it is available now 
 543             if ( wxTheApp->GetComCtl32Version() >= 471 ) 
 545                 // set the (underlying) separators width to be that of the 
 548                 tbbi.cbSize = sizeof(tbbi); 
 549                 tbbi.dwMask = TBIF_SIZE; 
 551                 if ( !SendMessage(GetHwnd(), TB_SETBUTTONINFO, 
 552                                   tool->GetId(), (LPARAM)&tbbi) ) 
 554                     // the id is probably invalid? 
 555                     wxLogLastError("TB_SETBUTTONINFO"); 
 560         #endif // comctl32.dll 4.71 
 561             // TB_SETBUTTONINFO unavailable 
 563                 // try adding several separators to fit the controls width 
 564                 int widthSep = r.right - r.left; 
 570                 tbb.fsState = TBSTATE_ENABLED; 
 571                 tbb.fsStyle = TBSTYLE_SEP; 
 573                 size_t nSeparators = size.x / widthSep; 
 574                 for ( size_t nSep = 0; nSep < nSeparators; nSep++ ) 
 576                     if ( !SendMessage(GetHwnd(), TB_INSERTBUTTON, 
 577                                       index, (LPARAM)&tbb) ) 
 579                         wxLogLastError("TB_INSERTBUTTON"); 
 585                 // remember the number of separators we used - we'd have to 
 586                 // delete all of them later 
 587                 ((wxToolBarTool *)tool)->SetSeparatorsCount(nSeparators); 
 589                 // adjust the controls width to exactly cover the separators 
 590                 control->SetSize((nSeparators + 1)*widthSep, -1); 
 593         // and position the control itself correctly vertically 
 594         int height = r.bottom - r.top; 
 595         int diff = height - size.y; 
 598             // the control is too high, resize to fit 
 599             control->SetSize(-1, height - 2); 
 604         control->Move(left == -1 ? r.left : left, r.top + (diff + 1) / 2); 
 607     // the max index is the "real" number of buttons - i.e. counting even the 
 608     // separators which we added just for aligning the controls 
 613         if ( m_maxRows == 0 ) 
 615             // if not set yet, only one row 
 619     else if ( m_nButtons > 0 ) // vertical non empty toolbar 
 621         if ( m_maxRows == 0 ) 
 623             // if not set yet, have one column 
 631 // ---------------------------------------------------------------------------- 
 633 // ---------------------------------------------------------------------------- 
 635 bool wxToolBar::OS2Command( 
 640     wxToolBarToolBase
*              pTool 
= FindById((int)nId
); 
 646     if (pTool->CanBeToggled()) 
 648         LRESULT state = ::SendMessage(GetHwnd(), TB_GETSTATE, id, 0); 
 649         tool->SetToggle((state & TBSTATE_CHECKED) != 0); 
 652     bool toggled = tool->IsToggled(); 
 654     // OnLeftClick() can veto the button state change - for buttons which may 
 655     // be toggled only, of couse 
 656     if ( !OnLeftClick((int)id, toggled) && tool->CanBeToggled() ) 
 660         tool->SetToggle(toggled); 
 662         ::SendMessage(GetHwnd(), TB_CHECKBUTTON, id, MAKELONG(toggled, 0)); 
 668 bool wxToolBar::OS2OnNotify( 
 676     // First check if this applies to us 
 677     NMHDR *hdr = (NMHDR *)lParam; 
 679     // the tooltips control created by the toolbar is sometimes Unicode, even 
 680     // in an ANSI application - this seems to be a bug in comctl32.dll v5 
 681     int code = (int)hdr->code; 
 682     if ( (code != TTN_NEEDTEXTA) && (code != TTN_NEEDTEXTW) ) 
 685     HWND toolTipWnd = (HWND)::SendMessage((HWND)GetHWND(), TB_GETTOOLTIPS, 0, 0); 
 686     if ( toolTipWnd != hdr->hwndFrom ) 
 689     LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam; 
 690     int id = (int)ttText->hdr.idFrom; 
 692     wxToolBarToolBase *tool = FindById(id); 
 696     const wxString& help = tool->GetShortHelp(); 
 698     if ( !help.IsEmpty() ) 
 700         if ( code == TTN_NEEDTEXTA ) 
 702             ttText->lpszText = (wxChar *)help.c_str(); 
 704 #if (_WIN32_IE >= 0x0300) 
 707             // FIXME this is a temp hack only until I understand better what 
 708             //       must be done in both ANSI and Unicode builds 
 710             size_t lenAnsi = help.Len(); 
 712                 // MetroWerks doesn't like calling mbstowcs with NULL argument 
 713                 size_t lenUnicode = 2*lenAnsi; 
 715                 size_t lenUnicode = mbstowcs(NULL, help, lenAnsi); 
 718             // using the pointer of right type avoids us doing all sorts of 
 719             // pointer arithmetics ourselves 
 720             wchar_t *dst = (wchar_t *)ttText->szText, 
 721                     *pwz = new wchar_t[lenUnicode + 1]; 
 722             mbstowcs(pwz, help, lenAnsi + 1); 
 723             memcpy(dst, pwz, lenUnicode*sizeof(wchar_t)); 
 725             // put the terminating _wide_ NUL 
 730 #endif // _WIN32_IE >= 0x0300 
 733     // For backward compatibility... 
 734     OnMouseEnter(tool->GetId()); 
 739 // ---------------------------------------------------------------------------- 
 741 // ---------------------------------------------------------------------------- 
 743 void wxToolBar::SetToolBitmapSize( 
 747     wxToolBarBase::SetToolBitmapSize(rSize
); 
 749     // ::SendMessage(GetHwnd(), TB_SETBITMAPSIZE, 0, MAKELONG(size.x, size.y)); 
 752 void wxToolBar::SetRows( 
 756     if (nRows 
== m_maxRows
) 
 758         // avoid resizing the frame uselessly 
 763     // TRUE in wParam means to create at least as many rows, FALSE - 
 766     ::SendMessage(GetHwnd(), TB_SETROWS, 
 767                   MAKEWPARAM(nRows, !(GetWindowStyle() & wxTB_VERTICAL)), 
 776 // The button size is bigger than the bitmap size 
 777 wxSize 
wxToolBar::GetToolSize() const 
 781     // TB_GETBUTTONSIZE is supported from version 4.70 
 782 #if defined(_WIN32_IE) && (_WIN32_IE >= 0x300 ) 
 783     if ( wxTheApp->GetComCtl32Version() >= 470 ) 
 785         DWORD dw = ::SendMessage(GetHwnd(), TB_GETBUTTONSIZE, 0, 0); 
 787         return wxSize(LOWORD(dw), HIWORD(dw)); 
 790 #endif // comctl32.dll 4.70+ 
 793         return wxSize(m_defaultWidth + 8, m_defaultHeight + 7); 
 796     return wxSize(m_defaultWidth 
+ 8, m_defaultHeight 
+ 7); 
 799 wxToolBarToolBase 
*wxToolBar::FindToolForPosition( 
 809     int                             nIndex 
= 0; //(int)::SendMessage(GetHwnd(), TB_HITTEST, 0, (LPARAM)&pt); 
 812         // it's a separator or there is no tool at all there 
 813         return (wxToolBarToolBase 
*)NULL
; 
 815     return(m_tools
.Item((size_t)nIndex
)->GetData()); 
 818 void wxToolBar::UpdateSize() 
 820     // we must refresh the frame after the toolbar size (possibly) changed 
 821     wxFrame
*                        pFrame 
= wxDynamicCast(GetParent(), wxFrame
); 
 825         // don't change the size, we just need to generate a WM_SIZE 
 829         if ( !GetWindowRect(GetHwndOf(frame), &r) ) 
 831             wxLogLastError(_T("GetWindowRect")); 
 834         (void)::SendMessage(GetHwndOf(frame), WM_SIZE, SIZE_RESTORED, 
 835                             MAKELPARAM(r.right - r.left, r.bottom - r.top)); 
 840 // ---------------------------------------------------------------------------- 
 842 // ---------------------------------------------------------------------------- 
 844 void wxToolBar::DoEnableTool( 
 845   wxToolBarToolBase
*                pTool
 
 851     ::SendMessage(GetHwnd(), TB_ENABLEBUTTON, 
 852                   (WPARAM)tool->GetId(), (LPARAM)MAKELONG(enable, 0)); 
 856 void wxToolBar::DoToggleTool( 
 857   wxToolBarToolBase
*                pTool
 
 863     ::SendMessage(GetHwnd(), TB_CHECKBUTTON, 
 864                   (WPARAM)tool->GetId(), (LPARAM)MAKELONG(toggle, 0)); 
 868 void wxToolBar::DoSetToggle( 
 869   wxToolBarToolBase
*                pTool
 
 873     // VZ: AFAIK, the button has to be created either with TBSTYLE_CHECK or 
 874     //     without, so we really need to delete the button and recreate it here 
 875     wxFAIL_MSG( _T("not implemented") ); 
 878 // ---------------------------------------------------------------------------- 
 880 // ---------------------------------------------------------------------------- 
 882 // Responds to colour changes, and passes event on to children. 
 883 void wxToolBar::OnSysColourChanged( 
 884   wxSysColourChangedEvent
&          rEvent
 
 889     m_backgroundColour = wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)), 
 890           GetGValue(GetSysColor(COLOR_BTNFACE)), GetBValue(GetSysColor(COLOR_BTNFACE))); 
 898     // Propagate the event to the non-top-level children 
 899     wxWindow::OnSysColourChanged(rEvent
); 
 902 void wxToolBar::OnMouseEvent( 
 906     if (rEvent
.RightDown()) 
 908         // For now, we don't have an id. Later we could 
 909         // try finding the tool. 
 910         OnRightClick( (int)-1 
 921 MRESULT 
wxToolBar::OS2WindowProc( 
 931         // calculate our minor dimenstion ourselves - we're confusing the 
 932         // standard logic (TB_AUTOSIZE) with our horizontal toolbars and other 
 935         if ( ::SendMessage(GetHwnd(), TB_GETITEMRECT, 0, (LPARAM)&r) ) 
 939             if ( GetWindowStyle() & wxTB_VERTICAL ) 
 941                 w = r.right - r.left; 
 944                     w *= (m_nButtons + m_maxRows - 1)/m_maxRows; 
 951                 h = r.bottom - r.top; 
 954                     h += 6; // FIXME: this is the separator line height... 
 959             if ( MAKELPARAM(w, h) != lParam ) 
 961                 // size really changed 
 970     return wxControl::MSWWindowProc(nMsg, wParam, lParam); 
 975 // ---------------------------------------------------------------------------- 
 977 // ---------------------------------------------------------------------------- 
 979 // These are the default colors used to map the bitmap colors to the current 
 980 // system colors. Note that they are in BGR format because this is what Windows 
 981 // wants (and not RGB) 
 983 #define BGR_BUTTONTEXT      (RGB(000,000,000))  // black 
 984 #define BGR_BUTTONSHADOW    (RGB(128,128,128))  // dark grey 
 985 #define BGR_BUTTONFACE      (RGB(192,192,192))  // bright grey 
 986 #define BGR_BUTTONHILIGHT   (RGB(255,255,255))  // white 
 987 #define BGR_BACKGROUNDSEL   (RGB(255,000,000))  // blue 
 988 #define BGR_BACKGROUND      (RGB(255,000,255))  // magenta 
 998   COLORMAP ColorMap[] = 
1000     {BGR_BUTTONTEXT,    COLOR_BTNTEXT},     // black 
1001     {BGR_BUTTONSHADOW,  COLOR_BTNSHADOW},   // dark grey 
1002     {BGR_BUTTONFACE,    COLOR_BTNFACE},     // bright grey 
1003     {BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white 
1004     {BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT},   // blue 
1005     {BGR_BACKGROUND,    COLOR_WINDOW}       // magenta 
1008   int NUM_MAPS = (sizeof(ColorMap)/sizeof(COLORMAP)); 
1010   for ( n = 0; n < NUM_MAPS; n++) 
1012     ColorMap[n].to = ::GetSysColor(ColorMap[n].to); 
1016   HDC hdcMem = CreateCompatibleDC(NULL); 
1020     hbmOld = (HBITMAP) SelectObject(hdcMem, hBitmap); 
1023     for ( i = 0; i < width; i++) 
1025         for ( j = 0; j < height; j++) 
1027             COLORREF pixel = ::GetPixel(hdcMem, i, j); 
1029 //            BYTE red = GetRValue(pixel); 
1030 //            BYTE green = GetGValue(pixel); 
1031 //            BYTE blue = GetBValue(pixel); 
1034             for ( k = 0; k < NUM_MAPS; k ++) 
1036                 if ( ColorMap[k].from == pixel ) 
1038                     // COLORREF actualPixel =  ::SetPixel(hdcMem, i, j, ColorMap[k].to); 
1046     SelectObject(hdcMem, hbmOld); 
1047     DeleteObject(hdcMem); 
1052 // Some experiments... 
1054   // What we want to do is create another bitmap which has a depth of 4, 
1055   // and set the bits. So probably we want to convert this HBITMAP into a 
1056   // DIB, then call SetDIBits. 
1057   // AAAGH. The stupid thing is that if newBitmap has a depth of 4 (less than that of 
1058   // the screen), then SetDIBits fails. 
1059   HBITMAP newBitmap 
= ::CreateBitmap(totalBitmapWidth
, totalBitmapHeight
, 1, 4, NULL
); 
1060   HANDLE newDIB 
= ::BitmapToDIB((HBITMAP
) m_hBitmap
, NULL
); 
1061   LPBITMAPINFOHEADER lpbmi 
= (LPBITMAPINFOHEADER
) GlobalLock(newDIB
); 
1064 //  LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) newDIB; 
1066   int result 
= ::SetDIBits(dc
, newBitmap
, 0, lpbmi
->biHeight
, FindDIBBits((LPSTR
)lpbmi
), (LPBITMAPINFO
)lpbmi
, 
1068   DWORD err 
= GetLastError(); 
1070   ::ReleaseDC(NULL
, dc
); 
1073   GlobalUnlock (newDIB
); 
1074   GlobalFree (newDIB
); 
1076 //  WXHBITMAP hBitmap2 = wxCreateMappedBitmap((WXHINSTANCE) wxGetInstance(), (WXHBITMAP) m_hBitmap); 
1077   // Substitute our new bitmap for the old one 
1078   ::DeleteObject((HBITMAP
) m_hBitmap
); 
1079   m_hBitmap 
= (WXHBITMAP
) newBitmap
;