]> git.saurik.com Git - wxWidgets.git/blame - src/msw/tbar95.cpp
fix for mingw which has TBSTYLE_FLAT but not TBSTYLE_TRANSPARENT (yet).
[wxWidgets.git] / src / msw / tbar95.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
1c383dba 2// Name: msw/tbar95.cpp
8a0681f9 3// Purpose: wxToolBar
2bda0e17
KB
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
89b892a2 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
1c383dba
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
1c383dba 21 #pragma implementation "tbar95.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
1c383dba 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
8a0681f9 32 #include "wx/frame.h"
1c383dba
VZ
33 #include "wx/log.h"
34 #include "wx/intl.h"
35 #include "wx/dynarray.h"
4e15f6c5 36 #include "wx/settings.h"
381dd4bf 37 #include "wx/bitmap.h"
f6bcfd97 38 #include "wx/dcmemory.h"
2bda0e17
KB
39#endif
40
8a0681f9
VZ
41#if wxUSE_TOOLBAR && defined(__WIN95__) && wxUSE_TOOLBAR_NATIVE
42
43#include "wx/toolbar.h"
2bda0e17 44
ce3ed50d 45#if !defined(__GNUWIN32__) && !defined(__SALFORDC__)
1c383dba 46 #include "malloc.h"
2bda0e17
KB
47#endif
48
1c383dba 49#include "wx/msw/private.h"
2bda0e17 50
57c208c5 51#ifndef __TWIN32__
1c383dba 52
ae090fdb 53#if defined(__WIN95__) && !((defined(__GNUWIN32_OLD__) || defined(__TWIN32__)) && !defined(__CYGWIN10__))
1c383dba 54 #include <commctrl.h>
ae090fdb
JS
55#else
56 #include "wx/msw/gnuwin32/extra.h"
65fd5cb0 57#endif
2bda0e17 58
1c383dba
VZ
59#endif // __TWIN32__
60
2bda0e17 61#include "wx/msw/dib.h"
1c383dba
VZ
62#include "wx/app.h" // for GetComCtl32Version
63
de85a884
VZ
64#if defined(__MWERKS__) && defined(__WXMSW__)
65// including <windef.h> for max definition doesn't seem
66// to work using CodeWarrior 6 Windows. So we define it
67// here. (Otherwise we get a undefined identifier 'max'
68// later on in this file.) (Added by dimitri@shortcut.nl)
69# ifndef max
70# define max(a,b) (((a) > (b)) ? (a) : (b))
71# endif
72
73#endif
74
f6bcfd97
BP
75// ----------------------------------------------------------------------------
76// conditional compilation
77// ----------------------------------------------------------------------------
78
79// wxWindows previously always considered that toolbar buttons have light grey
80// (0xc0c0c0) background and so ignored any bitmap masks - however, this
81// doesn't work with XPMs which then appear to have black background. To make
82// this work, we must respect the bitmap masks - which we do now. This should
83// be ok in any case, but to restore 100% compatible with the old version
84// behaviour, you can set this to 0.
85#define USE_BITMAP_MASKS 1
86
1c383dba
VZ
87// ----------------------------------------------------------------------------
88// constants
89// ----------------------------------------------------------------------------
90
91// these standard constants are not always defined in compilers headers
2bda0e17 92
6a23cbce 93// Styles
bb6290e3 94#ifndef TBSTYLE_FLAT
1c383dba
VZ
95 #define TBSTYLE_LIST 0x1000
96 #define TBSTYLE_FLAT 0x0800
dd177170
RL
97#endif
98
99#ifndef TBSTYLE_TRANSPARENT
1c383dba 100 #define TBSTYLE_TRANSPARENT 0x8000
bb6290e3 101#endif
bb6290e3 102
6a23cbce
JS
103// Messages
104#ifndef TB_GETSTYLE
1c383dba 105 #define TB_SETSTYLE (WM_USER + 56)
8a0681f9
VZ
106 #define TB_GETSTYLE (WM_USER + 57)
107#endif
108
109#ifndef TB_HITTEST
110 #define TB_HITTEST (WM_USER + 69)
6a23cbce
JS
111#endif
112
1c383dba 113// these values correspond to those used by comctl32.dll
81d66cf3
JS
114#define DEFAULTBITMAPX 16
115#define DEFAULTBITMAPY 15
116#define DEFAULTBUTTONX 24
117#define DEFAULTBUTTONY 24
118#define DEFAULTBARHEIGHT 27
119
1c383dba
VZ
120// ----------------------------------------------------------------------------
121// wxWin macros
122// ----------------------------------------------------------------------------
123
12ed316d 124IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
2bda0e17 125
8a0681f9
VZ
126BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
127 EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent)
128 EVT_SYS_COLOUR_CHANGED(wxToolBar::OnSysColourChanged)
2bda0e17 129END_EVENT_TABLE()
2bda0e17 130
8a0681f9
VZ
131// ----------------------------------------------------------------------------
132// private classes
133// ----------------------------------------------------------------------------
134
135class wxToolBarTool : public wxToolBarToolBase
136{
137public:
138 wxToolBarTool(wxToolBar *tbar,
139 int id,
140 const wxBitmap& bitmap1,
141 const wxBitmap& bitmap2,
142 bool toggle,
143 wxObject *clientData,
144 const wxString& shortHelpString,
145 const wxString& longHelpString)
146 : wxToolBarToolBase(tbar, id, bitmap1, bitmap2, toggle,
147 clientData, shortHelpString, longHelpString)
148 {
149 m_nSepCount = 0;
150 }
151
152 wxToolBarTool(wxToolBar *tbar, wxControl *control)
153 : wxToolBarToolBase(tbar, control)
154 {
155 m_nSepCount = 1;
156 }
157
158 // set/get the number of separators which we use to cover the space used by
159 // a control in the toolbar
160 void SetSeparatorsCount(size_t count) { m_nSepCount = count; }
161 size_t GetSeparatorsCount() const { return m_nSepCount; }
162
163private:
164 size_t m_nSepCount;
165};
166
167
1c383dba
VZ
168// ============================================================================
169// implementation
170// ============================================================================
2bda0e17 171
1c383dba 172// ----------------------------------------------------------------------------
8a0681f9 173// wxToolBarTool
1c383dba
VZ
174// ----------------------------------------------------------------------------
175
8a0681f9
VZ
176wxToolBarToolBase *wxToolBar::CreateTool(int id,
177 const wxBitmap& bitmap1,
178 const wxBitmap& bitmap2,
179 bool toggle,
180 wxObject *clientData,
181 const wxString& shortHelpString,
182 const wxString& longHelpString)
183{
184 return new wxToolBarTool(this, id, bitmap1, bitmap2, toggle,
185 clientData, shortHelpString, longHelpString);
186}
187
188wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
189{
190 return new wxToolBarTool(this, control);
191}
192
193// ----------------------------------------------------------------------------
194// wxToolBar construction
195// ----------------------------------------------------------------------------
196
197void wxToolBar::Init()
2bda0e17 198{
1c383dba 199 m_hBitmap = 0;
8a0681f9
VZ
200
201 m_nButtons = 0;
202
1c383dba
VZ
203 m_defaultWidth = DEFAULTBITMAPX;
204 m_defaultHeight = DEFAULTBITMAPY;
37d0bdff
MB
205
206 m_pInTool = 0;
2bda0e17
KB
207}
208
8a0681f9
VZ
209bool wxToolBar::Create(wxWindow *parent,
210 wxWindowID id,
211 const wxPoint& pos,
212 const wxSize& size,
213 long style,
214 const wxString& name)
2bda0e17 215{
a4aad4de
VZ
216 // toolbars never have border, giving one to them results in broken
217 // appearance
218 style &= ~wxBORDER_MASK;
219 style |= wxBORDER_NONE;
220
1c383dba 221 // common initialisation
11b6a93b 222 if ( !CreateControl(parent, id, pos, size, style, wxDefaultValidator, name) )
1c383dba 223 return FALSE;
89b892a2 224
1c383dba
VZ
225 // prepare flags
226 DWORD msflags = 0; // WS_VISIBLE | WS_CHILD always included
c25a510b 227
b0766406
JS
228 if ( style & wxCLIP_SIBLINGS )
229 msflags |= WS_CLIPSIBLINGS;
230
c25a510b 231#ifdef TBSTYLE_TOOLTIPS
1c383dba 232 msflags |= TBSTYLE_TOOLTIPS;
c25a510b 233#endif
2bda0e17 234
1c383dba
VZ
235 if (style & wxTB_FLAT)
236 {
7d6d3bf3
VZ
237 // static as it doesn't change during the program lifetime
238 static int s_verComCtl = wxTheApp->GetComCtl32Version();
239
240 // comctl32.dll 4.00 doesn't support the flat toolbars and using this
241 // style with 6.00 (part of Windows XP) leads to the toolbar with
242 // incorrect background colour - and not using it still results in the
243 // correct (flat) toolbar, so don't use it there
244 if ( s_verComCtl > 400 && s_verComCtl < 600 )
245 {
246 msflags |= TBSTYLE_FLAT | TBSTYLE_TRANSPARENT;
247 }
1c383dba 248 }
2bda0e17 249
1c383dba
VZ
250 // MSW-specific initialisation
251 if ( !wxControl::MSWCreateControl(TOOLBARCLASSNAME, msflags) )
252 return FALSE;
2bda0e17 253
c8f1f088 254 // toolbar-specific post initialisation
1c383dba 255 ::SendMessage(GetHwnd(), TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
89b892a2 256
c8f1f088 257 // set up the colors and fonts
7d6d3bf3 258 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_MENUBAR));
a756f210 259 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
c8f1f088 260
1c383dba
VZ
261 // position it
262 int x = pos.x;
263 int y = pos.y;
264 int width = size.x;
265 int height = size.y;
2bda0e17 266
1c383dba
VZ
267 if (width <= 0)
268 width = 100;
269 if (height <= 0)
270 height = m_defaultHeight;
271 if (x < 0)
272 x = 0;
273 if (y < 0)
274 y = 0;
bb6290e3 275
1c383dba 276 SetSize(x, y, width, height);
2bda0e17 277
1c383dba 278 return TRUE;
2bda0e17
KB
279}
280
8a0681f9 281wxToolBar::~wxToolBar()
2bda0e17 282{
f6bcfd97
BP
283 // we must refresh the frame size when the toolbar is deleted but the frame
284 // is not - otherwise toolbar leaves a hole in the place it used to occupy
f6bcfd97 285 wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
c2fd78b1 286 if ( frame && !frame->IsBeingDeleted() )
f6bcfd97
BP
287 {
288 frame->SendSizeEvent();
289 }
290
291 if ( m_hBitmap )
1c383dba
VZ
292 {
293 ::DeleteObject((HBITMAP) m_hBitmap);
294 }
295}
296
bdc72a22 297// ----------------------------------------------------------------------------
8a0681f9 298// adding/removing tools
bdc72a22
VZ
299// ----------------------------------------------------------------------------
300
8a0681f9
VZ
301bool wxToolBar::DoInsertTool(size_t WXUNUSED(pos),
302 wxToolBarToolBase *tool)
1c383dba 303{
8a0681f9
VZ
304 // nothing special to do here - we really create the toolbar buttons in
305 // Realize() later
306 tool->Attach(this);
307
308 return TRUE;
1c383dba
VZ
309}
310
8a0681f9 311bool wxToolBar::DoDeleteTool(size_t pos, wxToolBarToolBase *tool)
bdc72a22 312{
f6bcfd97
BP
313 // the main difficulty we have here is with the controls in the toolbars:
314 // as we (sometimes) use several separators to cover up the space used by
315 // them, the indices are not the same for us and the toolbar
316
317 // first determine the position of the first button to delete: it may be
318 // different from pos if we use several separators to cover the space used
319 // by a control
320 wxToolBarToolsList::Node *node;
321 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
322 {
323 wxToolBarToolBase *tool2 = node->GetData();
324 if ( tool2 == tool )
325 {
326 // let node point to the next node in the list
327 node = node->GetNext();
328
329 break;
330 }
331
332 if ( tool2->IsControl() )
333 {
56bd6aac 334 pos += ((wxToolBarTool *)tool2)->GetSeparatorsCount() - 1;
f6bcfd97
BP
335 }
336 }
337
338 // now determine the number of buttons to delete and the area taken by them
8a0681f9 339 size_t nButtonsToDelete = 1;
bdc72a22 340
8a0681f9
VZ
341 // get the size of the button we're going to delete
342 RECT r;
343 if ( !::SendMessage(GetHwnd(), TB_GETITEMRECT, pos, (LPARAM)&r) )
bdc72a22 344 {
8a0681f9 345 wxLogLastError(_T("TB_GETITEMRECT"));
bdc72a22
VZ
346 }
347
8a0681f9 348 int width = r.right - r.left;
bdc72a22 349
8a0681f9
VZ
350 if ( tool->IsControl() )
351 {
352 nButtonsToDelete = ((wxToolBarTool *)tool)->GetSeparatorsCount();
bdc72a22 353
8a0681f9
VZ
354 width *= nButtonsToDelete;
355 }
bdc72a22 356
f6bcfd97
BP
357 // do delete all buttons
358 m_nButtons -= nButtonsToDelete;
8a0681f9
VZ
359 while ( nButtonsToDelete-- > 0 )
360 {
361 if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, pos, 0) )
362 {
f6bcfd97 363 wxLogLastError(wxT("TB_DELETEBUTTON"));
1c383dba 364
8a0681f9
VZ
365 return FALSE;
366 }
367 }
1c383dba 368
8a0681f9 369 tool->Detach();
1c383dba 370
f6bcfd97
BP
371 // and finally reposition all the controls after this button (the toolbar
372 // takes care of all normal items)
373 for ( /* node -> first after deleted */ ; node; node = node->GetNext() )
8a0681f9
VZ
374 {
375 wxToolBarToolBase *tool2 = node->GetData();
376 if ( tool2->IsControl() )
377 {
378 int x;
379 wxControl *control = tool2->GetControl();
380 control->GetPosition(&x, NULL);
381 control->Move(x - width, -1);
382 }
383 }
1c383dba
VZ
384
385 return TRUE;
386}
387
8a0681f9 388bool wxToolBar::Realize()
1c383dba 389{
8a0681f9
VZ
390 size_t nTools = GetToolsCount();
391 if ( nTools == 0 )
392 {
393 // nothing to do
394 return TRUE;
395 }
1c383dba 396
8a0681f9 397 bool isVertical = (GetWindowStyle() & wxTB_VERTICAL) != 0;
2bda0e17 398
8a0681f9
VZ
399 // First, add the bitmap: we use one bitmap for all toolbar buttons
400 // ----------------------------------------------------------------
2bda0e17 401
8a0681f9
VZ
402 // if we already have a bitmap, we'll replace the existing one - otherwise
403 // we'll install a new one
404 HBITMAP oldToolBarBitmap = (HBITMAP)m_hBitmap;
89b892a2 405
1c383dba
VZ
406 int totalBitmapWidth = (int)(m_defaultWidth * nTools);
407 int totalBitmapHeight = (int)m_defaultHeight;
2bda0e17 408
f6bcfd97
BP
409 // Create a bitmap and copy all the tool bitmaps to it
410#if USE_BITMAP_MASKS
411 wxMemoryDC dcAllButtons;
412 wxBitmap bitmap(totalBitmapWidth, totalBitmapHeight);
413 dcAllButtons.SelectObject(bitmap);
414 dcAllButtons.SetBackground(*wxLIGHT_GREY_BRUSH);
415 dcAllButtons.Clear();
416
417 m_hBitmap = bitmap.GetHBITMAP();
418 HBITMAP hBitmap = (HBITMAP)m_hBitmap;
419#else // !USE_BITMAP_MASKS
8a0681f9
VZ
420 HBITMAP hBitmap = ::CreateCompatibleBitmap(ScreenHDC(),
421 totalBitmapWidth,
422 totalBitmapHeight);
423 if ( !hBitmap )
424 {
425 wxLogLastError(_T("CreateCompatibleBitmap"));
426
427 return FALSE;
428 }
429
430 m_hBitmap = (WXHBITMAP)hBitmap;
89b892a2 431
1c383dba 432 HDC memoryDC = ::CreateCompatibleDC(NULL);
8a0681f9 433 HBITMAP oldBitmap = (HBITMAP) ::SelectObject(memoryDC, hBitmap);
2bda0e17 434
1c383dba 435 HDC memoryDC2 = ::CreateCompatibleDC(NULL);
f6bcfd97 436#endif // USE_BITMAP_MASKS/!USE_BITMAP_MASKS
2bda0e17 437
1c383dba
VZ
438 // the button position
439 wxCoord x = 0;
2bda0e17 440
1c383dba 441 // the number of buttons (not separators)
8a0681f9 442 int nButtons = 0;
1c383dba 443
8a0681f9
VZ
444 wxToolBarToolsList::Node *node = m_tools.GetFirst();
445 while ( node )
051205e6 446 {
8a0681f9
VZ
447 wxToolBarToolBase *tool = node->GetData();
448 if ( tool->IsButton() )
1c383dba 449 {
f6bcfd97
BP
450 const wxBitmap& bmp = tool->GetBitmap1();
451 if ( bmp.Ok() )
1c383dba 452 {
f6bcfd97
BP
453#if USE_BITMAP_MASKS
454 // notice the last parameter: do use mask
455 dcAllButtons.DrawBitmap(tool->GetBitmap1(), x, 0, TRUE);
456#else // !USE_BITMAP_MASKS
457 HBITMAP hbmp = GetHbitmapOf(bmp);
1c383dba
VZ
458 HBITMAP oldBitmap2 = (HBITMAP)::SelectObject(memoryDC2, hbmp);
459 if ( !BitBlt(memoryDC, x, 0, m_defaultWidth, m_defaultHeight,
460 memoryDC2, 0, 0, SRCCOPY) )
461 {
f6bcfd97 462 wxLogLastError(wxT("BitBlt"));
1c383dba
VZ
463 }
464
465 ::SelectObject(memoryDC2, oldBitmap2);
f6bcfd97 466#endif // USE_BITMAP_MASKS/!USE_BITMAP_MASKS
1c383dba 467 }
8a0681f9
VZ
468 else
469 {
470 wxFAIL_MSG( _T("invalid tool button bitmap") );
471 }
472
473 // still inc width and number of buttons because otherwise the
474 // subsequent buttons will all be shifted which is rather confusing
475 // (and like this you'd see immediately which bitmap was bad)
476 x += m_defaultWidth;
477 nButtons++;
1c383dba 478 }
8a0681f9
VZ
479
480 node = node->GetNext();
051205e6 481 }
2bda0e17 482
f6bcfd97
BP
483#if USE_BITMAP_MASKS
484 dcAllButtons.SelectObject(wxNullBitmap);
485
486 // don't delete this HBITMAP!
487 bitmap.SetHBITMAP(0);
488#else // !USE_BITMAP_MASKS
1c383dba
VZ
489 ::SelectObject(memoryDC, oldBitmap);
490 ::DeleteDC(memoryDC);
491 ::DeleteDC(memoryDC2);
f6bcfd97 492#endif // USE_BITMAP_MASKS/!USE_BITMAP_MASKS
2bda0e17 493
1c383dba 494 // Map to system colours
566fb299
VZ
495 hBitmap = (HBITMAP)MapBitmap((WXHBITMAP) hBitmap,
496 totalBitmapWidth, totalBitmapHeight);
1c383dba 497
9f83044f
VZ
498 int bitmapId = 0;
499
500 bool addBitmap = TRUE;
501
1c383dba 502 if ( oldToolBarBitmap )
2bda0e17 503 {
9f83044f
VZ
504#ifdef TB_REPLACEBITMAP
505 if ( wxTheApp->GetComCtl32Version() >= 400 )
1c383dba 506 {
9f83044f
VZ
507 TBREPLACEBITMAP replaceBitmap;
508 replaceBitmap.hInstOld = NULL;
509 replaceBitmap.hInstNew = NULL;
510 replaceBitmap.nIDOld = (UINT) oldToolBarBitmap;
511 replaceBitmap.nIDNew = (UINT) hBitmap;
512 replaceBitmap.nButtons = nButtons;
513 if ( !::SendMessage(GetHwnd(), TB_REPLACEBITMAP,
514 0, (LPARAM) &replaceBitmap) )
515 {
516 wxFAIL_MSG(wxT("Could not replace the old bitmap"));
517 }
518
519 ::DeleteObject(oldToolBarBitmap);
520
521 // already done
522 addBitmap = FALSE;
1c383dba 523 }
9f83044f
VZ
524 else
525#endif // TB_REPLACEBITMAP
526 {
527 // we can't replace the old bitmap, so we will add another one
528 // (awfully inefficient, but what else to do?) and shift the bitmap
529 // indices accordingly
530 addBitmap = TRUE;
1c383dba 531
9f83044f
VZ
532 bitmapId = m_nButtons;
533 }
1c383dba
VZ
534
535 // Now delete all the buttons
8a0681f9 536 for ( size_t pos = 0; pos < m_nButtons; pos++ )
1c383dba 537 {
8a0681f9
VZ
538 if ( !::SendMessage(GetHwnd(), TB_DELETEBUTTON, 0, 0) )
539 {
56bd6aac 540 wxLogDebug(wxT("TB_DELETEBUTTON failed"));
8a0681f9 541 }
1c383dba 542 }
9f83044f 543
2bda0e17 544 }
9f83044f
VZ
545
546 if ( addBitmap ) // no old bitmap or we can't replace it
051205e6 547 {
1c383dba
VZ
548 TBADDBITMAP addBitmap;
549 addBitmap.hInst = 0;
8a0681f9 550 addBitmap.nID = (UINT) hBitmap;
1c383dba 551 if ( ::SendMessage(GetHwnd(), TB_ADDBITMAP,
8a0681f9 552 (WPARAM) nButtons, (LPARAM)&addBitmap) == -1 )
1c383dba
VZ
553 {
554 wxFAIL_MSG(wxT("Could not add bitmap to toolbar"));
555 }
051205e6 556 }
2bda0e17 557
8a0681f9
VZ
558 // Next add the buttons and separators
559 // -----------------------------------
560
1c383dba 561 TBBUTTON *buttons = new TBBUTTON[nTools];
2bda0e17 562
8a0681f9 563 // this array will hold the indices of all controls in the toolbar
1c383dba
VZ
564 wxArrayInt controlIds;
565
566 int i = 0;
8a0681f9 567 for ( node = m_tools.GetFirst(); node; node = node->GetNext() )
2bda0e17 568 {
8a0681f9
VZ
569 wxToolBarToolBase *tool = node->GetData();
570
571 // don't add separators to the vertical toolbar - looks ugly
572 if ( isVertical && tool->IsSeparator() )
573 continue;
574
1c383dba
VZ
575 TBBUTTON& button = buttons[i];
576
577 wxZeroMemory(button);
578
8a0681f9 579 switch ( tool->GetStyle() )
1c383dba
VZ
580 {
581 case wxTOOL_STYLE_CONTROL:
8a0681f9 582 button.idCommand = tool->GetId();
1c383dba
VZ
583 // fall through: create just a separator too
584
585 case wxTOOL_STYLE_SEPARATOR:
586 button.fsState = TBSTATE_ENABLED;
587 button.fsStyle = TBSTYLE_SEP;
588 break;
589
590 case wxTOOL_STYLE_BUTTON:
591 button.iBitmap = bitmapId;
8a0681f9 592 button.idCommand = tool->GetId();
1c383dba 593
8a0681f9 594 if ( tool->IsEnabled() )
1c383dba 595 button.fsState |= TBSTATE_ENABLED;
8a0681f9 596 if ( tool->IsToggled() )
1c383dba 597 button.fsState |= TBSTATE_CHECKED;
8a0681f9
VZ
598
599 button.fsStyle = tool->CanBeToggled() ? TBSTYLE_CHECK
600 : TBSTYLE_BUTTON;
1c383dba
VZ
601
602 bitmapId++;
603 break;
604 }
2bda0e17 605
1c383dba 606 i++;
2bda0e17 607 }
1c383dba
VZ
608
609 if ( !::SendMessage(GetHwnd(), TB_ADDBUTTONS,
610 (WPARAM)i, (LPARAM)buttons) )
2bda0e17 611 {
f6bcfd97 612 wxLogLastError(wxT("TB_ADDBUTTONS"));
2bda0e17 613 }
89b892a2 614
1c383dba 615 delete [] buttons;
2bda0e17 616
8a0681f9
VZ
617 // Deal with the controls finally
618 // ------------------------------
619
1c383dba 620 // adjust the controls size to fit nicely in the toolbar
34e5028f 621 int y = 0;
8a0681f9
VZ
622 size_t index = 0;
623 for ( node = m_tools.GetFirst(); node; node = node->GetNext(), index++ )
1c383dba 624 {
8a0681f9 625 wxToolBarToolBase *tool = node->GetData();
1c383dba 626
34e5028f
VZ
627 // we calculate the running y coord for vertical toolbars so we need to
628 // get the items size for all items but for the horizontal ones we
629 // don't need to deal with the non controls
630 bool isControl = tool->IsControl();
631 if ( !isControl && !isVertical )
632 continue;
bdc72a22 633
8a0681f9
VZ
634 // note that we use TB_GETITEMRECT and not TB_GETRECT because the
635 // latter only appeared in v4.70 of comctl32.dll
636 RECT r;
637 if ( !SendMessage(GetHwnd(), TB_GETITEMRECT,
638 index, (LPARAM)(LPRECT)&r) )
639 {
f6bcfd97 640 wxLogLastError(wxT("TB_GETITEMRECT"));
8a0681f9
VZ
641 }
642
34e5028f
VZ
643 if ( !isControl )
644 {
645 // can only be control if isVertical
646 y += r.bottom - r.top;
647
648 continue;
649 }
650
651 wxControl *control = tool->GetControl();
652
653 wxSize size = control->GetSize();
654
655 // the position of the leftmost controls corner
656 int left = -1;
657
bdc72a22 658 // TB_SETBUTTONINFO message is only supported by comctl32.dll 4.71+
34e5028f
VZ
659#if defined(_WIN32_IE) && (_WIN32_IE >= 0x400 )
660 // available in headers, now check whether it is available now
661 // (during run-time)
662 if ( wxTheApp->GetComCtl32Version() >= 471 )
663 {
664 // set the (underlying) separators width to be that of the
665 // control
666 TBBUTTONINFO tbbi;
667 tbbi.cbSize = sizeof(tbbi);
668 tbbi.dwMask = TBIF_SIZE;
669 tbbi.cx = size.x;
670 if ( !SendMessage(GetHwnd(), TB_SETBUTTONINFO,
671 tool->GetId(), (LPARAM)&tbbi) )
bdc72a22 672 {
34e5028f
VZ
673 // the id is probably invalid?
674 wxLogLastError(wxT("TB_SETBUTTONINFO"));
bdc72a22 675 }
34e5028f
VZ
676 }
677 else
678#endif // comctl32.dll 4.71
679 // TB_SETBUTTONINFO unavailable
680 {
681 // try adding several separators to fit the controls width
682 int widthSep = r.right - r.left;
683 left = r.left;
684
685 TBBUTTON tbb;
686 wxZeroMemory(tbb);
687 tbb.idCommand = 0;
688 tbb.fsState = TBSTATE_ENABLED;
689 tbb.fsStyle = TBSTYLE_SEP;
690
691 size_t nSeparators = size.x / widthSep;
692 for ( size_t nSep = 0; nSep < nSeparators; nSep++ )
bdc72a22 693 {
34e5028f
VZ
694 if ( !SendMessage(GetHwnd(), TB_INSERTBUTTON,
695 index, (LPARAM)&tbb) )
bdc72a22 696 {
34e5028f 697 wxLogLastError(wxT("TB_INSERTBUTTON"));
bdc72a22
VZ
698 }
699
34e5028f 700 index++;
bdc72a22 701 }
1c383dba 702
34e5028f
VZ
703 // remember the number of separators we used - we'd have to
704 // delete all of them later
705 ((wxToolBarTool *)tool)->SetSeparatorsCount(nSeparators);
706
707 // adjust the controls width to exactly cover the separators
708 control->SetSize((nSeparators + 1)*widthSep, -1);
709 }
710
711 // position the control itself correctly vertically
1c383dba
VZ
712 int height = r.bottom - r.top;
713 int diff = height - size.y;
714 if ( diff < 0 )
715 {
716 // the control is too high, resize to fit
717 control->SetSize(-1, height - 2);
718
719 diff = 2;
720 }
2bda0e17 721
34e5028f
VZ
722 int top;
723 if ( isVertical )
724 {
725 left = 0;
726 top = y;
727
728 y += height + 2*GetMargins().y;
729 }
730 else // horizontal toolbar
731 {
732 if ( left == -1 )
733 left = r.left;
734
735 top = r.top;
736 }
737
738 control->Move(left, top + (diff + 1) / 2);
1c383dba 739 }
89b892a2 740
8a0681f9
VZ
741 // the max index is the "real" number of buttons - i.e. counting even the
742 // separators which we added just for aligning the controls
743 m_nButtons = index;
89b892a2 744
8a0681f9
VZ
745 if ( !isVertical )
746 {
747 if ( m_maxRows == 0 )
748 {
749 // if not set yet, only one row
750 SetRows(1);
751 }
752 }
753 else if ( m_nButtons > 0 ) // vertical non empty toolbar
754 {
755 if ( m_maxRows == 0 )
756 {
757 // if not set yet, have one column
758 SetRows(m_nButtons);
759 }
760 }
2bda0e17 761
1c383dba 762 return TRUE;
2bda0e17
KB
763}
764
1c383dba
VZ
765// ----------------------------------------------------------------------------
766// message handlers
767// ----------------------------------------------------------------------------
768
33ac7e6f 769bool wxToolBar::MSWCommand(WXUINT WXUNUSED(cmd), WXWORD id)
2bda0e17 770{
8a0681f9
VZ
771 wxToolBarToolBase *tool = FindById((int)id);
772 if ( !tool )
1c383dba
VZ
773 return FALSE;
774
8a0681f9 775 if ( tool->CanBeToggled() )
1c383dba
VZ
776 {
777 LRESULT state = ::SendMessage(GetHwnd(), TB_GETSTATE, id, 0);
82dd98a7 778 tool->Toggle((state & TBSTATE_CHECKED) != 0);
1c383dba
VZ
779 }
780
8a0681f9
VZ
781 bool toggled = tool->IsToggled();
782
783 // OnLeftClick() can veto the button state change - for buttons which may
784 // be toggled only, of couse
785 if ( !OnLeftClick((int)id, toggled) && tool->CanBeToggled() )
1c383dba 786 {
8a0681f9
VZ
787 // revert back
788 toggled = !toggled;
789 tool->SetToggle(toggled);
790
791 ::SendMessage(GetHwnd(), TB_CHECKBUTTON, id, MAKELONG(toggled, 0));
1c383dba
VZ
792 }
793
794 return TRUE;
2bda0e17
KB
795}
796
8a0681f9 797bool wxToolBar::MSWOnNotify(int WXUNUSED(idCtrl),
fd3f686c 798 WXLPARAM lParam,
33ac7e6f 799 WXLPARAM *WXUNUSED(result))
2bda0e17 800{
89b892a2 801 // First check if this applies to us
2bda0e17 802 NMHDR *hdr = (NMHDR *)lParam;
2bda0e17 803
1c383dba
VZ
804 // the tooltips control created by the toolbar is sometimes Unicode, even
805 // in an ANSI application - this seems to be a bug in comctl32.dll v5
a17e237f
VZ
806 int code = (int)hdr->code;
807 if ( (code != TTN_NEEDTEXTA) && (code != TTN_NEEDTEXTW) )
89b892a2 808 return FALSE;
2bda0e17 809
89b892a2
VZ
810 HWND toolTipWnd = (HWND)::SendMessage((HWND)GetHWND(), TB_GETTOOLTIPS, 0, 0);
811 if ( toolTipWnd != hdr->hwndFrom )
812 return FALSE;
2bda0e17 813
89b892a2
VZ
814 LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam;
815 int id = (int)ttText->hdr.idFrom;
89b892a2 816
8a0681f9
VZ
817 wxToolBarToolBase *tool = FindById(id);
818 if ( !tool )
819 return FALSE;
2bda0e17 820
8a0681f9 821 const wxString& help = tool->GetShortHelp();
8df13671
VZ
822
823 if ( !help.IsEmpty() )
89b892a2 824 {
a17e237f 825 if ( code == TTN_NEEDTEXTA )
89b892a2 826 {
837e5743 827 ttText->lpszText = (wxChar *)help.c_str();
89b892a2 828 }
89b892a2
VZ
829 else
830 {
f6bcfd97
BP
831#if wxUSE_UNICODE
832 ttText->lpszText = (wxChar *)help.c_str();
833#else
0d910be7 834 // VZ: I don't know why it happens, but the versions of
56bd6aac 835 // comctl32.dll starting from 4.70 sometimes send TTN_NEEDTEXTW
0d910be7
VZ
836 // even to ANSI programs (normally, this message is supposed
837 // to be sent to Unicode programs only) - hence we need to
838 // handle it as well, otherwise no tooltips will be shown in
839 // this case
8df13671
VZ
840
841 size_t lenAnsi = help.Len();
a9582178 842 #if defined( __MWERKS__ ) || defined( __CYGWIN__ )
8df13671 843 // MetroWerks doesn't like calling mbstowcs with NULL argument
a9582178 844 // neither Cygwin does
8df13671 845 size_t lenUnicode = 2*lenAnsi;
b2cce0c4 846 #else
8df13671 847 size_t lenUnicode = mbstowcs(NULL, help, lenAnsi);
b2cce0c4 848 #endif
8df13671
VZ
849
850 // using the pointer of right type avoids us doing all sorts of
851 // pointer arithmetics ourselves
852 wchar_t *dst = (wchar_t *)ttText->szText,
853 *pwz = new wchar_t[lenUnicode + 1];
854 mbstowcs(pwz, help, lenAnsi + 1);
855 memcpy(dst, pwz, lenUnicode*sizeof(wchar_t));
856
857 // put the terminating _wide_ NUL
858 dst[lenUnicode] = 0;
89b892a2
VZ
859
860 delete [] pwz;
f6bcfd97 861#endif
89b892a2 862 }
2bda0e17 863 }
89b892a2 864
89b892a2 865 return TRUE;
2bda0e17
KB
866}
867
1c383dba 868// ----------------------------------------------------------------------------
8a0681f9 869// toolbar geometry
1c383dba
VZ
870// ----------------------------------------------------------------------------
871
8a0681f9 872void wxToolBar::SetToolBitmapSize(const wxSize& size)
2bda0e17 873{
1c383dba
VZ
874 wxToolBarBase::SetToolBitmapSize(size);
875
876 ::SendMessage(GetHwnd(), TB_SETBITMAPSIZE, 0, MAKELONG(size.x, size.y));
2bda0e17
KB
877}
878
8a0681f9 879void wxToolBar::SetRows(int nRows)
2bda0e17 880{
8a0681f9
VZ
881 if ( nRows == m_maxRows )
882 {
883 // avoid resizing the frame uselessly
884 return;
885 }
886
887 // TRUE in wParam means to create at least as many rows, FALSE -
888 // at most as many
1c383dba
VZ
889 RECT rect;
890 ::SendMessage(GetHwnd(), TB_SETROWS,
8a0681f9
VZ
891 MAKEWPARAM(nRows, !(GetWindowStyle() & wxTB_VERTICAL)),
892 (LPARAM) &rect);
1c383dba
VZ
893
894 m_maxRows = nRows;
8a0681f9
VZ
895
896 UpdateSize();
897}
898
899// The button size is bigger than the bitmap size
900wxSize wxToolBar::GetToolSize() const
901{
902 // TB_GETBUTTONSIZE is supported from version 4.70
5438a566
VZ
903#if defined(_WIN32_IE) && (_WIN32_IE >= 0x300 ) \
904 && !( defined(__GNUWIN32__) && !wxCHECK_W32API_VERSION( 1, 0 ) )
8a0681f9
VZ
905 if ( wxTheApp->GetComCtl32Version() >= 470 )
906 {
907 DWORD dw = ::SendMessage(GetHwnd(), TB_GETBUTTONSIZE, 0, 0);
908
909 return wxSize(LOWORD(dw), HIWORD(dw));
910 }
911 else
912#endif // comctl32.dll 4.70+
913 {
914 // defaults
915 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
916 }
2bda0e17
KB
917}
918
82c9f85c
VZ
919static
920wxToolBarToolBase *GetItemSkippingDummySpacers(const wxToolBarToolsList& tools,
921 size_t index )
a8945eef
MB
922{
923 wxToolBarToolsList::Node* current = tools.GetFirst();
924
82c9f85c 925 for ( ; current != 0; current = current->GetNext() )
a8945eef 926 {
82c9f85c 927 if ( index == 0 )
a8945eef 928 return current->GetData();
82c9f85c
VZ
929
930 wxToolBarTool *tool = (wxToolBarTool *)current->GetData();
931 size_t separators = tool->GetSeparatorsCount();
932
933 // if it is a normal button, sepcount == 0, so skip 1 item (the button)
934 // otherwise, skip as many items as the separator count, plus the
935 // control itself
936 index -= separators ? separators + 1 : 1;
a8945eef
MB
937 }
938
939 return 0;
940}
941
8a0681f9 942wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
2bda0e17 943{
8a0681f9
VZ
944 POINT pt;
945 pt.x = x;
946 pt.y = y;
947 int index = (int)::SendMessage(GetHwnd(), TB_HITTEST, 0, (LPARAM)&pt);
37d0bdff
MB
948 // MBN: when the point ( x, y ) is close to the toolbar border
949 // TB_HITTEST returns m_nButtons ( not -1 )
950 if ( index < 0 || (size_t)index >= m_nButtons )
1c383dba 951 {
8a0681f9
VZ
952 // it's a separator or there is no tool at all there
953 return (wxToolBarToolBase *)NULL;
1c383dba
VZ
954 }
955
82c9f85c 956 // if comctl32 version < 4.71 wxToolBar95 adds dummy spacers
a8945eef
MB
957#if defined(_WIN32_IE) && (_WIN32_IE >= 0x400 )
958 if ( wxTheApp->GetComCtl32Version() >= 471 )
959 {
960 return m_tools.Item((size_t)index)->GetData();
961 }
962 else
82c9f85c 963#endif
a8945eef
MB
964 {
965 return GetItemSkippingDummySpacers( m_tools, (size_t) index );
966 }
2bda0e17
KB
967}
968
8a0681f9 969void wxToolBar::UpdateSize()
2bda0e17 970{
0d7ea902
VZ
971 // the toolbar size changed
972 SendMessage(GetHwnd(), TB_AUTOSIZE, 0, 0);
973
974 // we must also refresh the frame after the toolbar size (possibly) changed
8a0681f9
VZ
975 wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
976 if ( frame )
977 {
f6bcfd97 978 frame->SendSizeEvent();
8a0681f9 979 }
2bda0e17
KB
980}
981
1c383dba
VZ
982// ----------------------------------------------------------------------------
983// tool state
984// ----------------------------------------------------------------------------
985
8a0681f9 986void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
2bda0e17 987{
8a0681f9
VZ
988 ::SendMessage(GetHwnd(), TB_ENABLEBUTTON,
989 (WPARAM)tool->GetId(), (LPARAM)MAKELONG(enable, 0));
2bda0e17
KB
990}
991
8a0681f9 992void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool toggle)
2bda0e17 993{
8a0681f9
VZ
994 ::SendMessage(GetHwnd(), TB_CHECKBUTTON,
995 (WPARAM)tool->GetId(), (LPARAM)MAKELONG(toggle, 0));
2bda0e17
KB
996}
997
33ac7e6f 998void wxToolBar::DoSetToggle(wxToolBarToolBase *WXUNUSED(tool), bool WXUNUSED(toggle))
088a95f5 999{
8a0681f9
VZ
1000 // VZ: AFAIK, the button has to be created either with TBSTYLE_CHECK or
1001 // without, so we really need to delete the button and recreate it here
1002 wxFAIL_MSG( _T("not implemented") );
2bda0e17
KB
1003}
1004
1c383dba
VZ
1005// ----------------------------------------------------------------------------
1006// event handlers
1007// ----------------------------------------------------------------------------
2bda0e17
KB
1008
1009// Responds to colour changes, and passes event on to children.
8a0681f9 1010void wxToolBar::OnSysColourChanged(wxSysColourChangedEvent& event)
2bda0e17 1011{
84c5b38d 1012 wxRGBToColour(m_backgroundColour, ::GetSysColor(COLOR_BTNFACE));
2bda0e17
KB
1013
1014 // Remap the buttons
8a0681f9 1015 Realize();
2bda0e17 1016
56bd6aac
VZ
1017 // Relayout the toolbar
1018 int nrows = m_maxRows;
1019 m_maxRows = 0; // otherwise SetRows() wouldn't do anything
1020 SetRows(nrows);
1021
2bda0e17
KB
1022 Refresh();
1023
56bd6aac
VZ
1024 // let the event propagate further
1025 event.Skip();
2bda0e17
KB
1026}
1027
8a0681f9 1028void wxToolBar::OnMouseEvent(wxMouseEvent& event)
e6460682
JS
1029{
1030 if (event.RightDown())
1031 {
1032 // For now, we don't have an id. Later we could
1033 // try finding the tool.
1034 OnRightClick((int)-1, event.GetX(), event.GetY());
1035 }
1036 else
1037 {
42e69d6b 1038 event.Skip();
e6460682
JS
1039 }
1040}
1041
8a0681f9 1042long wxToolBar::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
bdc72a22 1043{
8a0681f9 1044 if ( nMsg == WM_SIZE )
bdc72a22 1045 {
8a0681f9
VZ
1046 // calculate our minor dimenstion ourselves - we're confusing the
1047 // standard logic (TB_AUTOSIZE) with our horizontal toolbars and other
1048 // hacks
1049 RECT r;
1050 if ( ::SendMessage(GetHwnd(), TB_GETITEMRECT, 0, (LPARAM)&r) )
1051 {
1052 int w, h;
1053
1054 if ( GetWindowStyle() & wxTB_VERTICAL )
1055 {
1056 w = r.right - r.left;
1057 if ( m_maxRows )
1058 {
1059 w *= (m_nButtons + m_maxRows - 1)/m_maxRows;
1060 }
1061 h = HIWORD(lParam);
1062 }
1063 else
1064 {
1065 w = LOWORD(lParam);
1066 h = r.bottom - r.top;
1067 if ( m_maxRows )
1068 {
1069 h += 6; // FIXME: this is the separator line height...
1070 h *= m_maxRows;
1071 }
1072 }
1073
1074 if ( MAKELPARAM(w, h) != lParam )
1075 {
1076 // size really changed
1077 SetSize(w, h);
1078 }
1079
1080 // message processed
1081 return 0;
1082 }
bdc72a22 1083 }
a8945eef
MB
1084 else if ( nMsg == WM_MOUSEMOVE )
1085 {
1086 wxCoord x = GET_X_LPARAM(lParam), y = GET_Y_LPARAM(lParam);
1087 wxToolBarToolBase* tool = FindToolForPosition( x, y );
1088
1089 // cursor left current tool
1090 if( tool != m_pInTool && !tool )
1091 {
1092 m_pInTool = 0;
1093 OnMouseEnter( -1 );
1094 }
1095
1096 // cursor entered a tool
1097 if( tool != m_pInTool && tool )
1098 {
1099 m_pInTool = tool;
1100 OnMouseEnter( tool->GetId() );
1101 }
1102
1103 // we don't handle mouse moves, so fall through
1104 // to wxControl::MSWWindowProc
1105 }
bdc72a22 1106
8a0681f9 1107 return wxControl::MSWWindowProc(nMsg, wParam, lParam);
bdc72a22
VZ
1108}
1109
1c383dba
VZ
1110// ----------------------------------------------------------------------------
1111// private functions
1112// ----------------------------------------------------------------------------
1113
566fb299 1114WXHBITMAP wxToolBar::MapBitmap(WXHBITMAP bitmap, int width, int height)
2bda0e17 1115{
566fb299 1116 MemoryHDC hdcMem;
56bd6aac 1117
566fb299 1118 if ( !hdcMem )
5e68f8f3 1119 {
566fb299
VZ
1120 wxLogLastError(_T("CreateCompatibleDC"));
1121
1122 return bitmap;
5e68f8f3 1123 }
56bd6aac 1124
566fb299 1125 SelectInHDC bmpInHDC(hdcMem, (HBITMAP)bitmap);
56bd6aac 1126
566fb299 1127 if ( !bmpInHDC )
5e68f8f3 1128 {
566fb299
VZ
1129 wxLogLastError(_T("SelectObject"));
1130
1131 return bitmap;
1132 }
56bd6aac 1133
90c1530a
VZ
1134 wxCOLORMAP *cmap = wxGetStdColourMap();
1135
684c68fd
VZ
1136 for ( int i = 0; i < width; i++ )
1137 {
1138 for ( int j = 0; j < height; j++ )
1139 {
1140 COLORREF pixel = ::GetPixel(hdcMem, i, j);
1141
90c1530a 1142 for ( size_t k = 0; k < wxSTD_COL_MAX; k++ )
684c68fd 1143 {
90c1530a 1144 COLORREF col = cmap[k].from;
684c68fd
VZ
1145 if ( abs(GetRValue(pixel) - GetRValue(col)) < 10 &&
1146 abs(GetGValue(pixel) - GetGValue(col)) < 10 &&
1147 abs(GetBValue(pixel) - GetBValue(col)) < 10 )
1148 {
90c1530a 1149 ::SetPixel(hdcMem, i, j, cmap[k].to);
684c68fd
VZ
1150 break;
1151 }
1152 }
1153 }
1154 }
3a3898f8
VZ
1155
1156 return bitmap;
1157
566fb299
VZ
1158 // VZ: I leave here my attempts to map the bitmap to the system colours
1159 // faster by using BitBlt() even though it's broken currently - but
1160 // maybe someone else can finish it? It should be faster than iterating
1161 // over all pixels...
3a3898f8 1162#if 0
566fb299
VZ
1163 MemoryHDC hdcMask, hdcDst;
1164 if ( !hdcMask || !hdcDst )
1165 {
1166 wxLogLastError(_T("CreateCompatibleDC"));
56bd6aac 1167
566fb299 1168 return bitmap;
2bda0e17 1169 }
2bda0e17 1170
566fb299
VZ
1171 // create the target bitmap
1172 HBITMAP hbmpDst = ::CreateCompatibleBitmap(hdcDst, width, height);
1173 if ( !hbmpDst )
1174 {
1175 wxLogLastError(_T("CreateCompatibleBitmap"));
1176
1177 return bitmap;
1178 }
1179
1180 // create the monochrome mask bitmap
1181 HBITMAP hbmpMask = ::CreateBitmap(width, height, 1, 1, 0);
1182 if ( !hbmpMask )
1183 {
1184 wxLogLastError(_T("CreateBitmap(mono)"));
1185
1186 ::DeleteObject(hbmpDst);
1187
1188 return bitmap;
1189 }
1190
1191 SelectInHDC bmpInDst(hdcDst, hbmpDst),
1192 bmpInMask(hdcMask, hbmpMask);
1193
1194 // for each colour:
1195 for ( n = 0; n < NUM_OF_MAPPED_COLOURS; n++ )
1196 {
1197 // create the mask for this colour
1198 ::SetBkColor(hdcMem, ColorMap[n].from);
1199 ::BitBlt(hdcMask, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY);
1200
1201 // replace this colour with the target one in the dst bitmap
1202 HBRUSH hbr = ::CreateSolidBrush(ColorMap[n].to);
1203 HGDIOBJ hbrOld = ::SelectObject(hdcDst, hbr);
2bda0e17 1204
566fb299
VZ
1205 ::MaskBlt(hdcDst, 0, 0, width, height,
1206 hdcMem, 0, 0,
1207 hbmpMask, 0, 0,
1208 MAKEROP4(PATCOPY, SRCCOPY));
1209
1210 (void)::SelectObject(hdcDst, hbrOld);
1211 ::DeleteObject(hbr);
1212 }
1213
1214 ::DeleteObject((HBITMAP)bitmap);
1215
1216 return (WXHBITMAP)hbmpDst;
3a3898f8 1217#endif // 0
566fb299 1218}
2bda0e17 1219
8a0681f9 1220#endif // wxUSE_TOOLBAR && Win95
33ac7e6f 1221