]>
git.saurik.com Git - wxWidgets.git/blob - src/os2/toolbar.cpp
718318b17c275f2e23079a81cf80246f87241325
   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_BUTTONBAR && wxUSE_TOOLBAR 
  25 #include "wx/toolbar.h" 
  27 #include "wx/os2/private.h" 
  31 #define TBSTYLE_LIST            0x1000 
  32 #define TBSTYLE_FLAT            0x0800 
  33 #define TBSTYLE_TRANSPARENT     0x8000 
  35  // use TBSTYLE_TRANSPARENT if you use TBSTYLE_FLAT 
  39 #define TB_GETSTYLE             (WM_USER + 57) 
  40 #define TB_SETSTYLE             (WM_USER + 56) 
  43 /* Hint from a newsgroup for custom flatbar drawing: 
  44 Set the TBSTYLE_CUSTOMERASE style, then handle the 
  45 NM_CUSTOMDRAW message and do your custom drawing. 
  48 #define DEFAULTBITMAPX   16 
  49 #define DEFAULTBITMAPY   15 
  50 #define DEFAULTBUTTONX   24 
  51 #define DEFAULTBUTTONY   24 
  52 #define DEFAULTBARHEIGHT 27 
  54 IMPLEMENT_DYNAMIC_CLASS(wxToolBar
, wxToolBarBase
) 
  56 BEGIN_EVENT_TABLE(wxToolBar
, wxToolBarBase
) 
  57     EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent
) 
  58     EVT_SYS_COLOUR_CHANGED(wxToolBar::OnSysColourChanged
) 
  61 static void wxMapBitmap(HBITMAP hBitmap
, int width
, int height
); 
  63 wxToolBar::wxToolBar() 
  68   m_defaultWidth 
= DEFAULTBITMAPX
; 
  69   m_defaultHeight 
= DEFAULTBITMAPY
; 
  72 bool wxToolBar::Create(wxWindow 
*parent
, 
  80   m_backgroundColour 
= *wxWHITE
; //TODO: wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)), 
  81 //                                GetGValue(GetSysColor(COLOR_BTNFACE)), 
  82 //                                GetBValue(GetSysColor(COLOR_BTNFACE))); 
  83   m_foregroundColour 
= *wxBLACK 
; 
  85   wxASSERT_MSG( (style 
& wxTB_VERTICAL
) == 0, 
  86                 wxT("Sorry, wxToolBar under Windows 95 only " 
  87                    "supports horizontal orientation.") ); 
  94   m_defaultWidth 
= DEFAULTBITMAPX
; 
  95   m_defaultHeight 
= DEFAULTBITMAPY
; 
  98   m_windowStyle 
= style
; 
 100   SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT
)); 
 117   m_windowId 
= (id 
< 0 ? NewControlId() : id
); 
 121   if (style & wxBORDER) 
 122     msflags |= WS_BORDER; 
 123   msflags |= WS_CHILD | WS_VISIBLE | TBSTYLE_TOOLTIPS; 
 125   if (style & wxTB_FLAT) 
 127     if (wxTheApp->GetComCtl32Version() > 400) 
 128         msflags |= TBSTYLE_FLAT; 
 132   WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ; 
 134   // Even with extended styles, need to combine with WS_BORDER 
 135   // for them to look right. 
 136   if ( want3D || wxStyleHasBorder(m_windowStyle) ) 
 137       msflags |= WS_BORDER; 
 139   // Create the toolbar control. 
 140   HWND hWndToolbar = CreateWindowEx 
 142                       exStyle,                  // Extended styles. 
 143                       TOOLBARCLASSNAME,         // Class name for the toolbar. 
 144                       wxT(""),                   // No default text. 
 146                       x, y, width, height,      // Standard toolbar size and position. 
 147                       (HWND) parent->GetHWND(), // Parent window of the toolbar. 
 148                       (HMENU)m_windowId,        // Toolbar ID. 
 149                       wxGetInstance(),          // Current instance. 
 150                       NULL                      // No class data. 
 153   wxCHECK_MSG( hWndToolbar, FALSE, wxT("Toolbar creation failed") ); 
 155   // Toolbar-specific initialisation 
 156   ::SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, 
 157                 (WPARAM)sizeof(TBBUTTON), (LPARAM)0); 
 158   m_hWnd = (WXHWND) hWndToolbar; 
 161       parent->AddChild(this); 
 163   SubclassWin((WXHWND)hWndToolbar); 
 170 wxToolBar::~wxToolBar() 
 176 //    ::DeleteObject((HBITMAP) m_hBitmap); 
 181 bool wxToolBar::CreateTools() 
 183   if (m_tools
.Number() == 0) 
 186   HBITMAP oldToolBarBitmap 
= (HBITMAP
) m_hBitmap
; 
 188   int totalBitmapWidth 
= (int)(m_defaultWidth 
* m_tools
.Number()); 
 189   int totalBitmapHeight 
= (int)m_defaultHeight
; 
 193   // Create a bitmap for all the tool bitmaps 
 194   HDC dc = ::GetDC(NULL); 
 195   m_hBitmap = (WXHBITMAP) ::CreateCompatibleBitmap(dc, totalBitmapWidth, totalBitmapHeight); 
 196   ::ReleaseDC(NULL, dc); 
 198   // Now blit all the tools onto this bitmap 
 199   HDC memoryDC = ::CreateCompatibleDC(NULL); 
 200   HBITMAP oldBitmap = (HBITMAP) ::SelectObject(memoryDC, (HBITMAP) m_hBitmap); 
 202   HDC memoryDC2 = ::CreateCompatibleDC(NULL); 
 204   wxNode *node = m_tools.First(); 
 208     wxToolBarTool *tool = (wxToolBarTool *)node->Data(); 
 209     if ((tool->m_toolStyle != wxTOOL_STYLE_SEPARATOR) && tool->m_bitmap1.Ok() && tool->m_bitmap1.GetHBITMAP()) 
 211 //      wxPalette *palette = tool->m_bitmap1->GetPalette(); 
 213       HBITMAP oldBitmap2 = (HBITMAP) ::SelectObject(memoryDC2, (HBITMAP) tool->m_bitmap1.GetHBITMAP()); 
 215       BitBlt(memoryDC, x, 0, (int) m_defaultWidth, (int) m_defaultHeight, memoryDC2, 
 217       ::SelectObject(memoryDC2, oldBitmap2); 
 218       x += (int)m_defaultWidth; 
 223   ::SelectObject(memoryDC, oldBitmap); 
 224   ::DeleteDC(memoryDC); 
 225   ::DeleteDC(memoryDC2); 
 227   // Map to system colours 
 228   wxMapBitmap((HBITMAP) m_hBitmap, totalBitmapWidth, totalBitmapHeight); 
 230   if ( oldToolBarBitmap ) 
 232     TBREPLACEBITMAP replaceBitmap; 
 233     replaceBitmap.hInstOld = NULL; 
 234     replaceBitmap.hInstNew = NULL; 
 235     replaceBitmap.nIDOld = (UINT) oldToolBarBitmap; 
 236     replaceBitmap.nIDNew = (UINT) (HBITMAP) m_hBitmap; 
 237     replaceBitmap.nButtons = noButtons; 
 238     if (::SendMessage((HWND) GetHWND(), TB_REPLACEBITMAP, (WPARAM) 0, (LPARAM) &replaceBitmap) == -1) 
 240       wxFAIL_MSG(wxT("Could not add bitmap to toolbar")); 
 243     ::DeleteObject((HBITMAP) oldToolBarBitmap); 
 245     // Now delete all the buttons 
 249         // TODO: What about separators???? They don't have an id! 
 250         if ( ! ::SendMessage( (HWND) GetHWND(), TB_DELETEBUTTON, i, 0 ) ) 
 256     TBADDBITMAP addBitmap; 
 258     addBitmap.nID = (UINT)m_hBitmap; 
 259     if (::SendMessage((HWND) GetHWND(), TB_ADDBITMAP, (WPARAM) noButtons, (LPARAM) &addBitmap) == -1) 
 261       wxFAIL_MSG(wxT("Could not add bitmap to toolbar")); 
 265   // Now add the buttons. 
 266   TBBUTTON buttons[50]; 
 268   node = m_tools.First(); 
 273     wxToolBarTool *tool = (wxToolBarTool *)node->Data(); 
 274     if (tool->m_toolStyle == wxTOOL_STYLE_SEPARATOR) 
 276       buttons[i].iBitmap = 0; 
 277       buttons[i].idCommand = 0; 
 279       buttons[i].fsState = TBSTATE_ENABLED; 
 280       buttons[i].fsStyle = TBSTYLE_SEP; 
 281       buttons[i].dwData = 0L; 
 282       buttons[i].iString = 0; 
 286       buttons[i].iBitmap = bitmapId; 
 287       buttons[i].idCommand = tool->m_index; 
 289       buttons[i].fsState = 0; 
 291         buttons[i].fsState |= TBSTATE_ENABLED; 
 292       if (tool->m_toggleState) 
 293         buttons[i].fsState |= TBSTATE_CHECKED; 
 294       buttons[i].fsStyle = tool->m_isToggle ? TBSTYLE_CHECK : TBSTYLE_BUTTON; 
 295       buttons[i].dwData = 0L; 
 296       buttons[i].iString = 0; 
 305   long rc = ::SendMessage((HWND) GetHWND(), TB_ADDBUTTONS, (WPARAM)i, (LPARAM)& buttons); 
 307   wxCHECK_MSG( rc, FALSE, wxT("failed to add buttons to the toolbar") ); 
 309   (void)::SendMessage((HWND) GetHWND(), TB_AUTOSIZE, (WPARAM)0, (LPARAM) 0); 
 316 bool wxToolBar::OS2Command(WXUINT cmd
, WXWORD id
) 
 318   wxNode 
*node 
= m_tools
.Find((long)id
); 
 321   wxToolBarTool 
*tool 
= (wxToolBarTool 
*)node
->Data(); 
 324  if (tool->m_isToggle) 
 325     tool->m_toggleState = (1 == (1 & (int)::SendMessage((HWND) GetHWND(), TB_GETSTATE, (WPARAM) id, (LPARAM) 0))); 
 327   BOOL ret = OnLeftClick((int)id, tool->m_toggleState); 
 328   if (ret == FALSE && tool->m_isToggle) 
 330     tool->m_toggleState = !tool->m_toggleState; 
 331     ::SendMessage((HWND) GetHWND(), TB_CHECKBUTTON, (WPARAM)id, (LPARAM)MAKELONG(tool->m_toggleState, 0)); 
 338 bool wxToolBar::OS2OnNotify(int WXUNUSED(idCtrl
), 
 344     // First check if this applies to us 
 345     NMHDR *hdr = (NMHDR *)lParam; 
 347     // the tooltips control created by the toolbar is sometimes Unicode, even in 
 348     // an ANSI application 
 349     int code = (int)hdr->code; 
 350     if ( (code != TTN_NEEDTEXTA) && (code != TTN_NEEDTEXTW) ) 
 353     HWND toolTipWnd = (HWND)::SendMessage((HWND)GetHWND(), TB_GETTOOLTIPS, 0, 0); 
 354     if ( toolTipWnd != hdr->hwndFrom ) 
 357     LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam; 
 358     int id = (int)ttText->hdr.idFrom; 
 359     wxNode *node = m_tools.Find((long)id); 
 363     wxToolBarTool *tool = (wxToolBarTool *)node->Data(); 
 365     const wxString& help = tool->m_shortHelpString; 
 367     if ( !help.IsEmpty() ) 
 369         if ( code == TTN_NEEDTEXTA ) 
 371             ttText->lpszText = (wxChar *)help.c_str(); 
 373 #if (_WIN32_IE >= 0x0300) 
 376             // FIXME this is a temp hack only until I understand better what 
 377             //       must be done in both ANSI and Unicode builds 
 379             size_t lenAnsi = help.Len(); 
 381                 // MetroWerks doesn't like calling mbstowcs with NULL argument 
 382                 size_t lenUnicode = 2*lenAnsi; 
 384                 size_t lenUnicode = mbstowcs(NULL, help, lenAnsi); 
 387             // using the pointer of right type avoids us doing all sorts of 
 388             // pointer arithmetics ourselves 
 389             wchar_t *dst = (wchar_t *)ttText->szText, 
 390                     *pwz = new wchar_t[lenUnicode + 1]; 
 391             mbstowcs(pwz, help, lenAnsi + 1); 
 392             memcpy(dst, pwz, lenUnicode*sizeof(wchar_t)); 
 394             // put the terminating _wide_ NUL 
 399 #endif // _WIN32_IE >= 0x0300 
 402     // For backward compatibility... 
 403     OnMouseEnter(tool->m_index); 
 410 void wxToolBar::SetToolBitmapSize(const wxSize
& size
) 
 412   m_defaultWidth 
= size
.x
; 
 413   m_defaultHeight 
= size
.y
; 
 414 //  ::SendMessage((HWND) GetHWND(), TB_SETBITMAPSIZE, 0, (LPARAM) MAKELONG ((int)size.x, (int)size.y)); 
 417 void wxToolBar::SetRows(int nRows
) 
 422   ::SendMessage((HWND) GetHWND(), TB_SETROWS, MAKEWPARAM(nRows, TRUE), (LPARAM) & rect); 
 423   m_maxWidth = (rect.right - rect.left + 2); 
 424   m_maxHeight = (rect.bottom - rect.top + 2); 
 428 wxSize 
wxToolBar::GetMaxSize() const 
 432   if ((m_maxWidth == -1) || (m_maxHeight == -1)) 
 435     ::SendMessage((HWND) GetHWND(), TB_SETROWS, MAKEWPARAM(m_maxRows, TRUE), (LPARAM) & rect); 
 436     ((wxToolBar *)this)->m_maxWidth = (rect.right - rect.left + 2); // ??? 
 437     ((wxToolBar *)this)->m_maxHeight = (rect.bottom - rect.top + 2); // ??? 
 440   return wxSize(m_maxWidth
, m_maxHeight
); 
 443 // The button size is bigger than the bitmap size 
 444 wxSize 
wxToolBar::GetToolSize() const 
 446   return wxSize(m_defaultWidth 
+ 8, m_defaultHeight 
+ 7); 
 449 void wxToolBar::EnableTool(int toolIndex
, bool enable
) 
 451   wxNode 
*node 
= m_tools
.Find((long)toolIndex
); 
 454     wxToolBarTool 
*tool 
= (wxToolBarTool 
*)node
->Data(); 
 455     tool
->m_enabled 
= enable
; 
 456 //    ::SendMessage((HWND) GetHWND(), TB_ENABLEBUTTON, (WPARAM)toolIndex, (LPARAM)MAKELONG(enable, 0)); 
 460 void wxToolBar::ToggleTool(int toolIndex
, bool toggle
) 
 462   wxNode 
*node 
= m_tools
.Find((long)toolIndex
); 
 465     wxToolBarTool 
*tool 
= (wxToolBarTool 
*)node
->Data(); 
 466     if (tool
->m_isToggle
) 
 468       tool
->m_toggleState 
= toggle
; 
 469 //      ::SendMessage((HWND) GetHWND(), TB_CHECKBUTTON, (WPARAM)toolIndex, (LPARAM)MAKELONG(toggle, 0)); 
 474 bool wxToolBar::GetToolState(int toolIndex
) const 
 476 //    return (::SendMessage((HWND) GetHWND(), TB_ISBUTTONCHECKED, (WPARAM)toolIndex, (LPARAM)0) != 0); 
 480 void wxToolBar::ClearTools() 
 482   // TODO: Don't know how to reset the toolbar bitmap, as yet. 
 483   // But adding tools and calling CreateTools should probably 
 484   // recreate a buttonbar OK. 
 485   wxToolBarBase::ClearTools(); 
 488 // If pushedBitmap is NULL, a reversed version of bitmap is 
 489 // created and used as the pushed/toggled image. 
 490 // If toggle is TRUE, the button toggles between the two states. 
 491 wxToolBarTool 
*wxToolBar::AddTool(int index
, const wxBitmap
& bitmap
, const wxBitmap
& pushedBitmap
, 
 492              bool toggle
, long xPos
, long yPos
, wxObject 
*clientData
, const wxString
& helpString1
, const wxString
& helpString2
) 
 494   wxToolBarTool 
*tool 
= new wxToolBarTool(index
, bitmap
, wxNullBitmap
, toggle
, xPos
, yPos
, helpString1
, helpString2
); 
 495   tool
->m_clientData 
= clientData
; 
 500     tool
->m_x 
= m_xMargin
; 
 505     tool
->m_y 
= m_yMargin
; 
 507   tool
->SetSize(GetToolSize().x
, GetToolSize().y
); 
 509   m_tools
.Append((long)index
, tool
); 
 513 // Responds to colour changes, and passes event on to children. 
 514 void wxToolBar::OnSysColourChanged(wxSysColourChangedEvent
& event
) 
 518     m_backgroundColour = wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)), 
 519           GetGValue(GetSysColor(COLOR_BTNFACE)), GetBValue(GetSysColor(COLOR_BTNFACE))); 
 526     // Propagate the event to the non-top-level children 
 527     wxWindow::OnSysColourChanged(event
); 
 530 void wxToolBar::OnMouseEvent(wxMouseEvent
& event
) 
 532     if (event
.RightDown()) 
 534         // For now, we don't have an id. Later we could 
 535         // try finding the tool. 
 536         OnRightClick((int)-1, event
.GetX(), event
.GetY()); 
 544 // These are the default colors used to map the bitmap colors 
 545 // to the current system colors 
 547 #define BGR_BUTTONTEXT      (RGB(000,000,000))  // black 
 548 #define BGR_BUTTONSHADOW    (RGB(128,128,128))  // dark grey 
 549 #define BGR_BUTTONFACE      (RGB(192,192,192))  // bright grey 
 550 #define BGR_BUTTONHILIGHT   (RGB(255,255,255))  // white 
 551 #define BGR_BACKGROUNDSEL   (RGB(255,000,000))  // blue 
 552 #define BGR_BACKGROUND      (RGB(255,000,255))  // magenta 
 554 void wxMapBitmap(HBITMAP hBitmap
, int width
, int height
) 
 558   COLORMAP ColorMap[] = { 
 559     {BGR_BUTTONTEXT,    COLOR_BTNTEXT},     // black 
 560     {BGR_BUTTONSHADOW,  COLOR_BTNSHADOW},   // dark grey 
 561     {BGR_BUTTONFACE,    COLOR_BTNFACE},     // bright grey 
 562     {BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white 
 563     {BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT},   // blue 
 564     {BGR_BACKGROUND,    COLOR_WINDOW}       // magenta 
 567   int NUM_MAPS = (sizeof(ColorMap)/sizeof(COLORMAP)); 
 569   for ( n = 0; n < NUM_MAPS; n++) 
 571     ColorMap[n].to = ::GetSysColor(ColorMap[n].to); 
 575   HDC hdcMem = CreateCompatibleDC(NULL); 
 579     hbmOld = (HBITMAP) SelectObject(hdcMem, hBitmap); 
 582     for ( i = 0; i < width; i++) 
 584         for ( j = 0; j < height; j++) 
 586             COLORREF pixel = ::GetPixel(hdcMem, i, j); 
 587             BYTE red = GetRValue(pixel); 
 588             BYTE green = GetGValue(pixel); 
 589             BYTE blue = GetBValue(pixel); 
 591             for ( k = 0; k < NUM_MAPS; k ++) 
 593                 if ( ColorMap[k].from == pixel ) 
 595                     COLORREF actualPixel = ::SetPixel(hdcMem, i, j, ColorMap[k].to); 
 602     SelectObject(hdcMem, hbmOld); 
 603     DeleteObject(hdcMem); 
 608 // Some experiments... 
 610   // What we want to do is create another bitmap which has a depth of 4, 
 611   // and set the bits. So probably we want to convert this HBITMAP into a 
 612   // DIB, then call SetDIBits. 
 613   // AAAGH. The stupid thing is that if newBitmap has a depth of 4 (less than that of 
 614   // the screen), then SetDIBits fails. 
 615   HBITMAP newBitmap 
= ::CreateBitmap(totalBitmapWidth
, totalBitmapHeight
, 1, 4, NULL
); 
 616   HANDLE newDIB 
= ::BitmapToDIB((HBITMAP
) m_hBitmap
, NULL
); 
 617   LPBITMAPINFOHEADER lpbmi 
= (LPBITMAPINFOHEADER
) GlobalLock(newDIB
); 
 620 //  LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) newDIB; 
 622   int result 
= ::SetDIBits(dc
, newBitmap
, 0, lpbmi
->biHeight
, FindDIBBits((LPSTR
)lpbmi
), (LPBITMAPINFO
)lpbmi
, 
 624   DWORD err 
= GetLastError(); 
 626   ::ReleaseDC(NULL
, dc
); 
 629   GlobalUnlock (newDIB
); 
 632 //  WXHBITMAP hBitmap2 = wxCreateMappedBitmap((WXHINSTANCE) wxGetInstance(), (WXHBITMAP) m_hBitmap); 
 633   // Substitute our new bitmap for the old one 
 634   ::DeleteObject((HBITMAP
) m_hBitmap
); 
 635   m_hBitmap 
= (WXHBITMAP
) newBitmap
;