removed USE_SHARED_LIBRARY(IES)
[wxWidgets.git] / src / msw / tbar95.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/tbar95.cpp
3 // Purpose: wxToolBar95
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "tbar95.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/log.h"
33 #include "wx/intl.h"
34 #include "wx/dynarray.h"
35 #include "wx/settings.h"
36 #include "wx/bitmap.h"
37 #endif
38
39 #if wxUSE_BUTTONBAR && wxUSE_TOOLBAR && defined(__WIN95__)
40
41 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__)
42 #include "malloc.h"
43 #endif
44
45 #include "wx/msw/private.h"
46
47 #ifndef __TWIN32__
48
49 #ifdef __GNUWIN32_OLD__
50 #include "wx/msw/gnuwin32/extra.h"
51 #else
52 #include <commctrl.h>
53 #endif
54
55 #endif // __TWIN32__
56
57 #include "wx/msw/dib.h"
58 #include "wx/msw/tbar95.h"
59 #include "wx/app.h" // for GetComCtl32Version
60
61 // ----------------------------------------------------------------------------
62 // constants
63 // ----------------------------------------------------------------------------
64
65 // these standard constants are not always defined in compilers headers
66
67 // Styles
68 #ifndef TBSTYLE_FLAT
69 #define TBSTYLE_LIST 0x1000
70 #define TBSTYLE_FLAT 0x0800
71 #define TBSTYLE_TRANSPARENT 0x8000
72 #endif
73 // use TBSTYLE_TRANSPARENT if you use TBSTYLE_FLAT
74
75 // Messages
76 #ifndef TB_GETSTYLE
77 #define TB_GETSTYLE (WM_USER + 57)
78 #define TB_SETSTYLE (WM_USER + 56)
79 #endif
80
81 // these values correspond to those used by comctl32.dll
82 #define DEFAULTBITMAPX 16
83 #define DEFAULTBITMAPY 15
84 #define DEFAULTBUTTONX 24
85 #define DEFAULTBUTTONY 24
86 #define DEFAULTBARHEIGHT 27
87
88 // ----------------------------------------------------------------------------
89 // function prototypes
90 // ----------------------------------------------------------------------------
91
92 static void wxMapBitmap(HBITMAP hBitmap, int width, int height);
93
94 // ----------------------------------------------------------------------------
95 // wxWin macros
96 // ----------------------------------------------------------------------------
97
98 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
99
100 BEGIN_EVENT_TABLE(wxToolBar95, wxToolBarBase)
101 EVT_MOUSE_EVENTS(wxToolBar95::OnMouseEvent)
102 EVT_SYS_COLOUR_CHANGED(wxToolBar95::OnSysColourChanged)
103 END_EVENT_TABLE()
104
105 // ============================================================================
106 // implementation
107 // ============================================================================
108
109 // ----------------------------------------------------------------------------
110 // wxToolBar95 construction
111 // ----------------------------------------------------------------------------
112
113 void wxToolBar95::Init()
114 {
115 m_maxWidth = -1;
116 m_maxHeight = -1;
117 m_hBitmap = 0;
118 m_defaultWidth = DEFAULTBITMAPX;
119 m_defaultHeight = DEFAULTBITMAPY;
120 }
121
122 bool wxToolBar95::Create(wxWindow *parent,
123 wxWindowID id,
124 const wxPoint& pos,
125 const wxSize& size,
126 long style,
127 const wxString& name)
128 {
129 wxASSERT_MSG( (style & wxTB_VERTICAL) == 0,
130 wxT("Sorry, wxToolBar95 under Windows 95 only "
131 "supports horizontal orientation.") );
132
133 // common initialisation
134 if ( !CreateControl(parent, id, pos, size, style, name) )
135 return FALSE;
136
137 // prepare flags
138 DWORD msflags = 0; // WS_VISIBLE | WS_CHILD always included
139 if (style & wxBORDER)
140 msflags |= WS_BORDER;
141 msflags |= TBSTYLE_TOOLTIPS;
142
143 if (style & wxTB_FLAT)
144 {
145 if (wxTheApp->GetComCtl32Version() > 400)
146 msflags |= TBSTYLE_FLAT;
147 }
148
149 // MSW-specific initialisation
150 if ( !wxControl::MSWCreateControl(TOOLBARCLASSNAME, msflags) )
151 return FALSE;
152
153 // toolbar-specific post initialisation
154 ::SendMessage(GetHwnd(), TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
155
156 // set up the colors and fonts
157 wxRGBToColour(m_backgroundColour, GetSysColor(COLOR_BTNFACE));
158 m_foregroundColour = *wxBLACK;
159
160 SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
161
162 // position it
163 int x = pos.x;
164 int y = pos.y;
165 int width = size.x;
166 int height = size.y;
167
168 if (width <= 0)
169 width = 100;
170 if (height <= 0)
171 height = m_defaultHeight;
172 if (x < 0)
173 x = 0;
174 if (y < 0)
175 y = 0;
176
177 SetSize(x, y, width, height);
178
179 return TRUE;
180 }
181
182 wxToolBar95::~wxToolBar95()
183 {
184 UnsubclassWin();
185
186 if (m_hBitmap)
187 {
188 ::DeleteObject((HBITMAP) m_hBitmap);
189 }
190 }
191
192 // ----------------------------------------------------------------------------
193 // adding/removing buttons
194 // ----------------------------------------------------------------------------
195
196 void wxToolBar95::ClearTools()
197 {
198 // TODO: Don't know how to reset the toolbar bitmap, as yet.
199 // But adding tools and calling CreateTools should probably
200 // recreate a buttonbar OK.
201 wxToolBarBase::ClearTools();
202 }
203
204 bool wxToolBar95::DeleteTool(int id)
205 {
206 int index = GetIndexFromId(id);
207 wxASSERT_MSG( index != wxNOT_FOUND, _T("invalid toolbar button id") );
208
209 if ( !SendMessage(GetHwnd(), TB_DELETEBUTTON, index, 0) )
210 {
211 wxLogLastError("TB_DELETEBUTTON");
212
213 return FALSE;
214 }
215
216 wxNode *node = m_tools.Nth(index);
217 delete (wxToolBarTool *)node->Data();
218 m_tools.DeleteNode(node);
219
220 m_ids.RemoveAt(index);
221
222 return TRUE;
223 }
224
225 bool wxToolBar95::AddControl(wxControl *control)
226 {
227 wxCHECK_MSG( control, FALSE, _T("toolbar: can't insert NULL control") );
228
229 wxCHECK_MSG( control->GetParent() == this, FALSE,
230 _T("control must have toolbar as parent") );
231
232 wxToolBarTool *tool = new wxToolBarTool(control);
233
234 m_tools.Append(control->GetId(), tool);
235 m_ids.Add(control->GetId());
236
237 return TRUE;
238 }
239
240 wxToolBarTool *wxToolBar95::AddTool(int index,
241 const wxBitmap& bitmap,
242 const wxBitmap& pushedBitmap,
243 bool toggle,
244 long xPos, long yPos,
245 wxObject *clientData,
246 const wxString& helpString1,
247 const wxString& helpString2)
248 {
249 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, wxNullBitmap,
250 toggle, xPos, yPos,
251 helpString1, helpString2);
252 tool->m_clientData = clientData;
253
254 if (xPos > -1)
255 tool->m_x = xPos;
256 else
257 tool->m_x = m_xMargin;
258
259 if (yPos > -1)
260 tool->m_y = yPos;
261 else
262 tool->m_y = m_yMargin;
263
264 tool->SetSize(GetToolSize().x, GetToolSize().y);
265
266 m_tools.Append((long)index, tool);
267 m_ids.Add(index);
268
269 return tool;
270 }
271
272 bool wxToolBar95::CreateTools()
273 {
274 size_t nTools = m_tools.GetCount();
275 if ( nTools == 0 )
276 return FALSE;
277
278 HBITMAP oldToolBarBitmap = (HBITMAP) m_hBitmap;
279
280 int totalBitmapWidth = (int)(m_defaultWidth * nTools);
281 int totalBitmapHeight = (int)m_defaultHeight;
282
283 // Create a bitmap for all the tool bitmaps
284 HDC dc = ::GetDC(NULL);
285 m_hBitmap = (WXHBITMAP) ::CreateCompatibleBitmap(dc,
286 totalBitmapWidth,
287 totalBitmapHeight);
288 ::ReleaseDC(NULL, dc);
289
290 // Now blit all the tools onto this bitmap
291 HDC memoryDC = ::CreateCompatibleDC(NULL);
292 HBITMAP oldBitmap = (HBITMAP) ::SelectObject(memoryDC, (HBITMAP)m_hBitmap);
293
294 HDC memoryDC2 = ::CreateCompatibleDC(NULL);
295
296 // the button position
297 wxCoord x = 0;
298
299 // the number of buttons (not separators)
300 int noButtons = 0;
301
302 wxNode *node = m_tools.First();
303 while (node)
304 {
305 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
306 if ( tool->m_toolStyle == wxTOOL_STYLE_BUTTON && tool->m_bitmap1.Ok() )
307 {
308 HBITMAP hbmp = GetHbitmapOf(tool->m_bitmap1);
309 if ( hbmp )
310 {
311 HBITMAP oldBitmap2 = (HBITMAP)::SelectObject(memoryDC2, hbmp);
312 if ( !BitBlt(memoryDC, x, 0, m_defaultWidth, m_defaultHeight,
313 memoryDC2, 0, 0, SRCCOPY) )
314 {
315 wxLogLastError("BitBlt");
316 }
317
318 ::SelectObject(memoryDC2, oldBitmap2);
319
320 x += m_defaultWidth;
321 noButtons++;
322 }
323 }
324 node = node->Next();
325 }
326
327 ::SelectObject(memoryDC, oldBitmap);
328 ::DeleteDC(memoryDC);
329 ::DeleteDC(memoryDC2);
330
331 // Map to system colours
332 wxMapBitmap((HBITMAP) m_hBitmap, totalBitmapWidth, totalBitmapHeight);
333
334 if ( oldToolBarBitmap )
335 {
336 TBREPLACEBITMAP replaceBitmap;
337 replaceBitmap.hInstOld = NULL;
338 replaceBitmap.hInstNew = NULL;
339 replaceBitmap.nIDOld = (UINT) oldToolBarBitmap;
340 replaceBitmap.nIDNew = (UINT) (HBITMAP) m_hBitmap;
341 replaceBitmap.nButtons = noButtons;
342 if ( ::SendMessage(GetHwnd(), TB_REPLACEBITMAP,
343 0, (LPARAM) &replaceBitmap) == -1 )
344 {
345 wxFAIL_MSG(wxT("Could not add bitmap to toolbar"));
346 }
347
348 ::DeleteObject((HBITMAP) oldToolBarBitmap);
349
350 // Now delete all the buttons
351 int i = 0;
352 while ( TRUE )
353 {
354 // TODO: What about separators???? They don't have an id!
355 if ( ! ::SendMessage( GetHwnd(), TB_DELETEBUTTON, i, 0 ) )
356 break;
357 }
358 }
359 else
360 {
361 TBADDBITMAP addBitmap;
362 addBitmap.hInst = 0;
363 addBitmap.nID = (UINT)m_hBitmap;
364 if ( ::SendMessage(GetHwnd(), TB_ADDBITMAP,
365 (WPARAM) noButtons, (LPARAM)&addBitmap) == -1 )
366 {
367 wxFAIL_MSG(wxT("Could not add bitmap to toolbar"));
368 }
369 }
370
371 // Now add the buttons.
372 TBBUTTON *buttons = new TBBUTTON[nTools];
373
374 // this array will holds the indices of all controls in the toolbar
375 wxArrayInt controlIds;
376
377 int i = 0;
378 int bitmapId = 0;
379
380 node = m_tools.First();
381 while (node)
382 {
383 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
384 TBBUTTON& button = buttons[i];
385
386 wxZeroMemory(button);
387
388 switch ( tool->m_toolStyle )
389 {
390 case wxTOOL_STYLE_CONTROL:
391 controlIds.Add(i);
392 button.idCommand = tool->m_index;
393 // fall through: create just a separator too
394
395 case wxTOOL_STYLE_SEPARATOR:
396 button.fsState = TBSTATE_ENABLED;
397 button.fsStyle = TBSTYLE_SEP;
398 break;
399
400 case wxTOOL_STYLE_BUTTON:
401 button.iBitmap = bitmapId;
402 button.idCommand = tool->m_index;
403
404 if (tool->m_enabled)
405 button.fsState |= TBSTATE_ENABLED;
406 if (tool->m_toggleState)
407 button.fsState |= TBSTATE_CHECKED;
408 button.fsStyle = tool->m_isToggle ? TBSTYLE_CHECK
409 : TBSTYLE_BUTTON;
410
411 bitmapId++;
412 break;
413 }
414
415 i++;
416 node = node->Next();
417 }
418
419 if ( !::SendMessage(GetHwnd(), TB_ADDBUTTONS,
420 (WPARAM)i, (LPARAM)buttons) )
421 {
422 wxLogLastError("TB_ADDBUTTONS");
423 }
424
425 delete [] buttons;
426
427 // adjust the controls size to fit nicely in the toolbar
428 size_t nControls = controlIds.GetCount();
429 for ( size_t nCtrl = 0; nCtrl < nControls; nCtrl++ )
430 {
431 wxToolBarTool *tool = (wxToolBarTool *)
432 m_tools.Nth(controlIds[nCtrl])->Data();
433 wxControl *control = tool->GetControl();
434
435 wxSize size = control->GetSize();
436
437 // the position of the leftmost controls corner
438 int left = -1;
439
440 // TB_SETBUTTONINFO message is only supported by comctl32.dll 4.71+
441 #if defined(_WIN32_IE) && (_WIN32_IE >= 0x400 )
442 // available in headers, now check whether it is available now
443 // (during run-time)
444 if ( wxTheApp->GetComCtl32Version() >= 471 )
445 {
446 // set the (underlying) separators width to be that of the
447 // control
448 TBBUTTONINFO tbbi;
449 tbbi.cbSize = sizeof(tbbi);
450 tbbi.dwMask = TBIF_SIZE;
451 tbbi.cx = size.x;
452 if ( !SendMessage(GetHwnd(), TB_SETBUTTONINFO,
453 tool->m_index, (LPARAM)&tbbi) )
454 {
455 // the index is probably invalid
456 wxLogLastError("TB_SETBUTTONINFO");
457 }
458
459 }
460 else
461 #endif // comctl32.dll 4.71
462 // TB_SETBUTTONINFO unavailable
463 {
464 int index = GetIndexFromId(tool->m_index);
465 wxASSERT_MSG( index != wxNOT_FOUND,
466 _T("control wasn't added to the tbar?") );
467
468 // try adding several separators to fit the controls width
469 RECT r;
470 if ( !SendMessage(GetHwnd(), TB_GETRECT,
471 tool->m_index, (LPARAM)(LPRECT)&r) )
472 {
473 wxLogLastError("TB_GETITEMRECT");
474 }
475
476 int widthSep = r.right - r.left;
477 left = r.left;
478
479 TBBUTTON tbb;
480 wxZeroMemory(tbb);
481 tbb.idCommand = 0;
482 tbb.fsState = TBSTATE_ENABLED;
483 tbb.fsStyle = TBSTYLE_SEP;
484
485 size_t nSeparators = size.x / widthSep;
486 for ( size_t nSep = 0; nSep < nSeparators; nSep++ )
487 {
488 m_ids.Insert(0, (size_t)index);
489
490 if ( !SendMessage(GetHwnd(), TB_INSERTBUTTON,
491 index, (LPARAM)&tbb) )
492 {
493 wxLogLastError("TB_INSERTBUTTON");
494 }
495 }
496
497 // adjust the controls width to exactly cover the separators
498 control->SetSize((nSeparators + 1)*widthSep, -1);
499 }
500
501 // and position the control itself correctly vertically
502 RECT r;
503 if ( !SendMessage(GetHwnd(), TB_GETRECT,
504 tool->m_index, (LPARAM)(LPRECT)&r) )
505 {
506 wxLogLastError("TB_GETRECT");
507 }
508
509 int height = r.bottom - r.top;
510 int diff = height - size.y;
511 if ( diff < 0 )
512 {
513 // the control is too high, resize to fit
514 control->SetSize(-1, height - 2);
515
516 diff = 2;
517 }
518
519 control->Move(left == -1 ? r.left : left, r.top + diff / 2);
520 }
521
522 (void)::SendMessage(GetHwnd(), TB_AUTOSIZE, (WPARAM)0, (LPARAM) 0);
523
524 SetRows(m_maxRows);
525
526 return TRUE;
527 }
528
529 // ----------------------------------------------------------------------------
530 // message handlers
531 // ----------------------------------------------------------------------------
532
533 bool wxToolBar95::MSWCommand(WXUINT cmd, WXWORD id)
534 {
535 wxNode *node = m_tools.Find((long)id);
536 if (!node)
537 return FALSE;
538
539 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
540 if (tool->m_isToggle)
541 {
542 LRESULT state = ::SendMessage(GetHwnd(), TB_GETSTATE, id, 0);
543 tool->m_toggleState = state & TBSTATE_CHECKED;
544 }
545
546 BOOL ret = OnLeftClick((int)id, tool->m_toggleState);
547 if ( ret == FALSE && tool->m_isToggle )
548 {
549 tool->m_toggleState = !tool->m_toggleState;
550 ::SendMessage(GetHwnd(), TB_CHECKBUTTON,
551 (WPARAM)id, (LPARAM)MAKELONG(tool->m_toggleState, 0));
552 }
553
554 return TRUE;
555 }
556
557 bool wxToolBar95::MSWOnNotify(int WXUNUSED(idCtrl),
558 WXLPARAM lParam,
559 WXLPARAM *result)
560 {
561 // First check if this applies to us
562 NMHDR *hdr = (NMHDR *)lParam;
563
564 // the tooltips control created by the toolbar is sometimes Unicode, even
565 // in an ANSI application - this seems to be a bug in comctl32.dll v5
566 int code = (int)hdr->code;
567 if ( (code != TTN_NEEDTEXTA) && (code != TTN_NEEDTEXTW) )
568 return FALSE;
569
570 HWND toolTipWnd = (HWND)::SendMessage((HWND)GetHWND(), TB_GETTOOLTIPS, 0, 0);
571 if ( toolTipWnd != hdr->hwndFrom )
572 return FALSE;
573
574 LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam;
575 int id = (int)ttText->hdr.idFrom;
576 wxNode *node = m_tools.Find((long)id);
577 if (!node)
578 return FALSE;
579
580 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
581
582 const wxString& help = tool->m_shortHelpString;
583
584 if ( !help.IsEmpty() )
585 {
586 if ( code == TTN_NEEDTEXTA )
587 {
588 ttText->lpszText = (wxChar *)help.c_str();
589 }
590 #if (_WIN32_IE >= 0x0300)
591 else
592 {
593 // FIXME this is a temp hack only until I understand better what
594 // must be done in both ANSI and Unicode builds
595
596 size_t lenAnsi = help.Len();
597 #ifdef __MWERKS__
598 // MetroWerks doesn't like calling mbstowcs with NULL argument
599 size_t lenUnicode = 2*lenAnsi;
600 #else
601 size_t lenUnicode = mbstowcs(NULL, help, lenAnsi);
602 #endif
603
604 // using the pointer of right type avoids us doing all sorts of
605 // pointer arithmetics ourselves
606 wchar_t *dst = (wchar_t *)ttText->szText,
607 *pwz = new wchar_t[lenUnicode + 1];
608 mbstowcs(pwz, help, lenAnsi + 1);
609 memcpy(dst, pwz, lenUnicode*sizeof(wchar_t));
610
611 // put the terminating _wide_ NUL
612 dst[lenUnicode] = 0;
613
614 delete [] pwz;
615 }
616 #endif // _WIN32_IE >= 0x0300
617 }
618
619 // For backward compatibility...
620 OnMouseEnter(tool->m_index);
621
622 return TRUE;
623 }
624
625 // ----------------------------------------------------------------------------
626 // sizing stuff
627 // ----------------------------------------------------------------------------
628
629 void wxToolBar95::SetToolBitmapSize(const wxSize& size)
630 {
631 wxToolBarBase::SetToolBitmapSize(size);
632
633 ::SendMessage(GetHwnd(), TB_SETBITMAPSIZE, 0, MAKELONG(size.x, size.y));
634 }
635
636 void wxToolBar95::SetRows(int nRows)
637 {
638 // TRUE in wParam means to create at least as many rows
639 RECT rect;
640 ::SendMessage(GetHwnd(), TB_SETROWS,
641 MAKEWPARAM(nRows, TRUE), (LPARAM) &rect);
642
643 m_maxWidth = (rect.right - rect.left + 2);
644 m_maxHeight = (rect.bottom - rect.top + 2);
645
646 m_maxRows = nRows;
647 }
648
649 wxSize wxToolBar95::GetMaxSize() const
650 {
651 if ( (m_maxWidth == -1) || (m_maxHeight == -1) )
652 {
653 // it has a side effect of filling m_maxWidth/Height variables
654 ((wxToolBar95 *)this)->SetRows(m_maxRows); // const_cast
655 }
656
657 return wxSize(m_maxWidth, m_maxHeight);
658 }
659
660 // The button size is bigger than the bitmap size
661 wxSize wxToolBar95::GetToolSize() const
662 {
663 // FIXME: this is completely bogus (VZ)
664 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
665 }
666
667 // ----------------------------------------------------------------------------
668 // tool state
669 // ----------------------------------------------------------------------------
670
671 void wxToolBar95::EnableTool(int toolIndex, bool enable)
672 {
673 wxNode *node = m_tools.Find((long)toolIndex);
674 if (node)
675 {
676 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
677 tool->m_enabled = enable;
678 ::SendMessage(GetHwnd(), TB_ENABLEBUTTON,
679 (WPARAM)toolIndex, (LPARAM)MAKELONG(enable, 0));
680 }
681 }
682
683 void wxToolBar95::ToggleTool(int toolIndex, bool toggle)
684 {
685 wxNode *node = m_tools.Find((long)toolIndex);
686 if (node)
687 {
688 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
689 if (tool->m_isToggle)
690 {
691 tool->m_toggleState = toggle;
692 ::SendMessage(GetHwnd(), TB_CHECKBUTTON,
693 (WPARAM)toolIndex, (LPARAM)MAKELONG(toggle, 0));
694 }
695 }
696 }
697
698 bool wxToolBar95::GetToolState(int toolIndex) const
699 {
700 wxASSERT_MSG( GetIndexFromId(toolIndex) != wxNOT_FOUND,
701 _T("invalid toolbar button id") );
702
703 return ::SendMessage(GetHwnd(), TB_ISBUTTONCHECKED,
704 (WPARAM)toolIndex, (LPARAM)0) != 0;
705 }
706
707 // ----------------------------------------------------------------------------
708 // event handlers
709 // ----------------------------------------------------------------------------
710
711 // Responds to colour changes, and passes event on to children.
712 void wxToolBar95::OnSysColourChanged(wxSysColourChangedEvent& event)
713 {
714 m_backgroundColour = wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)),
715 GetGValue(GetSysColor(COLOR_BTNFACE)), GetBValue(GetSysColor(COLOR_BTNFACE)));
716
717 // Remap the buttons
718 CreateTools();
719
720 Refresh();
721
722 // Propagate the event to the non-top-level children
723 wxWindow::OnSysColourChanged(event);
724 }
725
726 void wxToolBar95::OnMouseEvent(wxMouseEvent& event)
727 {
728 if (event.RightDown())
729 {
730 // For now, we don't have an id. Later we could
731 // try finding the tool.
732 OnRightClick((int)-1, event.GetX(), event.GetY());
733 }
734 else
735 {
736 event.Skip();
737 }
738 }
739
740
741 // ----------------------------------------------------------------------------
742 // helpers
743 // ----------------------------------------------------------------------------
744
745 int wxToolBar95::GetIndexFromId(int id) const
746 {
747 size_t count = m_ids.GetCount();
748 for ( size_t n = 0; n < count; n++ )
749 {
750 if ( m_ids[n] == id )
751 return n;
752 }
753
754 return wxNOT_FOUND;
755 }
756
757 // ----------------------------------------------------------------------------
758 // private functions
759 // ----------------------------------------------------------------------------
760
761 // These are the default colors used to map the bitmap colors to the current
762 // system colors. Note that they are in BGR format because this is what Windows
763 // wants (and not RGB)
764
765 #define BGR_BUTTONTEXT (RGB(000,000,000)) // black
766 #define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey
767 #define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey
768 #define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white
769 #define BGR_BACKGROUNDSEL (RGB(000,000,255)) // blue
770 #define BGR_BACKGROUND (RGB(255,000,255)) // magenta
771
772 void wxMapBitmap(HBITMAP hBitmap, int width, int height)
773 {
774 COLORMAP ColorMap[] =
775 {
776 {BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black
777 {BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey
778 {BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey
779 {BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white
780 {BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue
781 {BGR_BACKGROUND, COLOR_WINDOW} // magenta
782 };
783
784 int NUM_MAPS = (sizeof(ColorMap)/sizeof(COLORMAP));
785 int n;
786 for ( n = 0; n < NUM_MAPS; n++)
787 {
788 ColorMap[n].to = ::GetSysColor(ColorMap[n].to);
789 }
790
791 HBITMAP hbmOld;
792 HDC hdcMem = CreateCompatibleDC(NULL);
793
794 if (hdcMem)
795 {
796 hbmOld = (HBITMAP) SelectObject(hdcMem, hBitmap);
797
798 int i, j, k;
799 for ( i = 0; i < width; i++)
800 {
801 for ( j = 0; j < height; j++)
802 {
803 COLORREF pixel = ::GetPixel(hdcMem, i, j);
804 /*
805 BYTE red = GetRValue(pixel);
806 BYTE green = GetGValue(pixel);
807 BYTE blue = GetBValue(pixel);
808 */
809
810 for ( k = 0; k < NUM_MAPS; k ++)
811 {
812 if ( ColorMap[k].from == pixel )
813 {
814 /* COLORREF actualPixel = */ ::SetPixel(hdcMem, i, j, ColorMap[k].to);
815 break;
816 }
817 }
818 }
819 }
820
821
822 SelectObject(hdcMem, hbmOld);
823 DeleteObject(hdcMem);
824 }
825
826 }
827
828 // Some experiments...
829 #if 0
830 // What we want to do is create another bitmap which has a depth of 4,
831 // and set the bits. So probably we want to convert this HBITMAP into a
832 // DIB, then call SetDIBits.
833 // AAAGH. The stupid thing is that if newBitmap has a depth of 4 (less than that of
834 // the screen), then SetDIBits fails.
835 HBITMAP newBitmap = ::CreateBitmap(totalBitmapWidth, totalBitmapHeight, 1, 4, NULL);
836 HANDLE newDIB = ::BitmapToDIB((HBITMAP) m_hBitmap, NULL);
837 LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) GlobalLock(newDIB);
838
839 dc = ::GetDC(NULL);
840 // LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) newDIB;
841
842 int result = ::SetDIBits(dc, newBitmap, 0, lpbmi->biHeight, FindDIBBits((LPSTR)lpbmi), (LPBITMAPINFO)lpbmi,
843 DIB_PAL_COLORS);
844 DWORD err = GetLastError();
845
846 ::ReleaseDC(NULL, dc);
847
848 // Delete the DIB
849 GlobalUnlock (newDIB);
850 GlobalFree (newDIB);
851
852 // WXHBITMAP hBitmap2 = wxCreateMappedBitmap((WXHINSTANCE) wxGetInstance(), (WXHBITMAP) m_hBitmap);
853 // Substitute our new bitmap for the old one
854 ::DeleteObject((HBITMAP) m_hBitmap);
855 m_hBitmap = (WXHBITMAP) newBitmap;
856 #endif
857
858
859 #endif // !(wxUSE_TOOLBAR && Win95)