]> git.saurik.com Git - wxWidgets.git/blame - src/msw/tbarmsw.cpp
Fixed bug [ 754596 ] wxUSE_CONSTRAINTS 0 breaks AutoLayout() with sizers
[wxWidgets.git] / src / msw / tbarmsw.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: tbarmsw.cpp
8a0681f9 3// Purpose: wxToolBar
2bda0e17 4// Author: Julian Smart
8a0681f9 5// Modified by: 13.12.99 by VZ during toolbar classes reorganization
2bda0e17
KB
6// Created: 04/01/98
7// RCS-ID: $Id$
6c9a19aa
JS
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
8a0681f9
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
14f355c2 20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
8a0681f9 21 #pragma implementation "tbarmsw.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
8a0681f9 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
8a0681f9 32 #include "wx/wx.h"
2bda0e17
KB
33#endif
34
c25a510b 35#if wxUSE_TOOLBAR && defined(__WIN16__)
8a0681f9 36
ce3ed50d 37#if !defined(__GNUWIN32__) && !defined(__SALFORDC__)
8a0681f9 38 #include "malloc.h"
2bda0e17
KB
39#endif
40
ce3ed50d 41#if !defined(__MWERKS__) && !defined(__SALFORDC__)
8a0681f9 42 #include <memory.h>
17dff81c 43#endif
ce3ed50d 44
2bda0e17
KB
45#include <stdlib.h>
46
c25a510b 47#include "wx/msw/tbarmsw.h"
2432b92d 48#include "wx/event.h"
2bda0e17 49#include "wx/app.h"
2432b92d 50#include "wx/bitmap.h"
2bda0e17
KB
51#include "wx/msw/private.h"
52#include "wx/msw/dib.h"
53
8a0681f9
VZ
54// ----------------------------------------------------------------------------
55// constants
56// ----------------------------------------------------------------------------
57
81d66cf3
JS
58#define DEFAULTBITMAPX 16
59#define DEFAULTBITMAPY 15
60#define DEFAULTBUTTONX 24
61#define DEFAULTBUTTONY 22
62#define DEFAULTBARHEIGHT 27
63
8a0681f9
VZ
64//
65// States (not all of them currently used)
66//
67#define wxTBSTATE_CHECKED 0x01 // radio button is checked
68#define wxTBSTATE_PRESSED 0x02 // button is being depressed (any style)
69#define wxTBSTATE_ENABLED 0x04 // button is enabled
70#define wxTBSTATE_HIDDEN 0x08 // button is hidden
71#define wxTBSTATE_INDETERMINATE 0x10 // button is indeterminate
2bda0e17 72
8a0681f9
VZ
73// ----------------------------------------------------------------------------
74// private classes
75// ----------------------------------------------------------------------------
2bda0e17 76
8a0681f9
VZ
77class WXDLLEXPORT wxToolBarTool : public wxToolBarToolBase
78{
79public:
80 wxToolBarTool(wxToolBar *tbar,
81 int id,
a3399e6c
VZ
82 const wxBitmap& bmpNormal,
83 const wxBitmap& bmpDisabled,
8a0681f9
VZ
84 bool toggle,
85 wxObject *clientData,
a3399e6c
VZ
86 const wxString& shortHelp,
87 const wxString& longHelp)
88 : wxToolBarToolBase(tbar, id, bmpNormal, bmpDisabled, toggle,
89 clientData, shortHelp, longHelp)
8a0681f9
VZ
90 {
91 }
92
93 wxToolBarTool(wxToolBar *tbar, wxControl *control)
94 : wxToolBarToolBase(tbar, control)
95 {
96 }
2bda0e17 97
8a0681f9
VZ
98 void SetSize(const wxSize& size)
99 {
100 m_width = size.x;
101 m_height = size.y;
102 }
103
104 long GetWidth() const { return m_width; }
105 long GetHeight() const { return m_height; }
106
107 wxCoord m_x;
108 wxCoord m_y;
109 wxCoord m_width;
110 wxCoord m_height;
111};
112
113// ----------------------------------------------------------------------------
114// wxWin macros
115// ----------------------------------------------------------------------------
116
117#if !USE_SHARED_LIBRARY
12ed316d 118IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
8a0681f9
VZ
119
120BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
121 EVT_PAINT(wxToolBar::OnPaint)
122 EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent)
2bda0e17 123END_EVENT_TABLE()
8a0681f9
VZ
124#endif
125
126// ============================================================================
127// implementation
128// ============================================================================
129
130// ----------------------------------------------------------------------------
131// wxToolBarTool
132// ----------------------------------------------------------------------------
133
134wxToolBarToolBase *wxToolBar::CreateTool(int id,
a3399e6c
VZ
135 const wxString& label,
136 const wxBitmap& bmpNormal,
137 const wxBitmap& bmpDisabled,
138 wxItemKind kind,
8a0681f9 139 wxObject *clientData,
a3399e6c
VZ
140 const wxString& shortHelp,
141 const wxString& longHelp)
8a0681f9 142{
a3399e6c
VZ
143 return new wxToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
144 clientData, shortHelp, longHelp);
8a0681f9 145}
2bda0e17 146
8a0681f9 147wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
2bda0e17 148{
8a0681f9 149 return new wxToolBarTool(this, control);
2bda0e17
KB
150}
151
8a0681f9
VZ
152// ----------------------------------------------------------------------------
153// wxToolBar
154// ----------------------------------------------------------------------------
155
156void wxToolBar::Init()
2bda0e17 157{
8a0681f9
VZ
158 m_hbrDither = 0;
159 m_rgbFace = 0;
160 m_rgbShadow = 0;
161 m_rgbHilight = 0;
162 m_rgbFrame = 0;
163 m_hdcMono = 0;
164 m_hbmMono = 0;
165 m_hbmDefault = 0;
166
167 m_defaultWidth = DEFAULTBITMAPX;
168 m_defaultHeight = DEFAULTBITMAPY;
2bda0e17 169
8a0681f9
VZ
170 m_xPos =
171 m_yPos = -1;
2bda0e17 172
8a0681f9
VZ
173 m_maxWidth = m_maxHeight = 0;
174 m_pressedTool = m_currentTool = -1;
175 m_toolPacking = 1;
176 m_toolSeparation = 5;
177}
2bda0e17 178
8a0681f9
VZ
179bool wxToolBar::Create(wxWindow *parent,
180 wxWindowID id,
181 const wxPoint& pos,
182 const wxSize& size,
183 long style,
184 const wxString& name)
185{
186 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
187 return FALSE;
2bda0e17 188
8a0681f9
VZ
189 if ( style & wxTB_HORIZONTAL )
190 {
191 m_lastX = 3;
192 m_lastY = 7;
193 }
194 else
195 {
196 m_lastX = 7;
197 m_lastY = 3;
198 }
2bda0e17 199
8a0681f9
VZ
200 // Set it to grey
201 SetBackgroundColour(wxColour(192, 192, 192));
202
203 InitGlobalObjects();
204
205 return TRUE;
2bda0e17
KB
206}
207
8a0681f9 208wxToolBar::~wxToolBar()
2bda0e17 209{
8a0681f9 210 FreeGlobalObjects();
2bda0e17
KB
211}
212
8a0681f9 213void wxToolBar::SetToolBitmapSize(const wxSize& size)
2bda0e17 214{
8a0681f9
VZ
215 m_defaultWidth = size.x;
216 m_defaultHeight = size.y;
217
218 FreeGlobalObjects();
219 InitGlobalObjects();
2bda0e17
KB
220}
221
222// The button size is bigger than the bitmap size
8a0681f9 223wxSize wxToolBar::GetToolSize() const
2bda0e17 224{
8a0681f9 225 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
2bda0e17
KB
226}
227
8a0681f9 228wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
2bda0e17 229{
8a0681f9
VZ
230 wxToolBarToolsList::Node *node = m_tools.GetFirst();
231 while (node)
232 {
233 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
234 if ((x >= tool->m_x) && (y >= tool->m_y) &&
235 (x <= (tool->m_x + tool->GetWidth())) &&
236 (y <= (tool->m_y + tool->GetHeight())))
237 {
238 return tool;
239 }
2bda0e17 240
8a0681f9
VZ
241 node = node->GetNext();
242 }
2bda0e17 243
8a0681f9
VZ
244 return (wxToolBarToolBase *)NULL;
245}
2bda0e17 246
8a0681f9
VZ
247wxToolBarToolBase *wxToolBar::AddTool(int id,
248 const wxBitmap& bitmap,
249 const wxBitmap& pushedBitmap,
250 bool toggle,
251 wxCoord xPos,
252 wxCoord yPos,
253 wxObject *clientData,
254 const wxString& helpString1,
255 const wxString& helpString2)
256{
257 // rememeber the position for DoInsertTool()
258 m_xPos = xPos;
259 m_yPos = yPos;
260
261 return wxToolBarBase::AddTool(id, bitmap, pushedBitmap, toggle,
262 xPos, yPos, clientData,
263 helpString1, helpString2);
2bda0e17
KB
264}
265
8a0681f9 266void wxToolBar::OnPaint(wxPaintEvent& event)
2bda0e17 267{
8a0681f9
VZ
268 wxPaintDC dc(this);
269
270 static int wxOnPaintCount = 0;
271
272 // Prevent reentry of OnPaint which would cause
273 // wxMemoryDC errors.
274 if (wxOnPaintCount > 0)
275 return;
276 wxOnPaintCount++;
277
278 wxToolBarToolsList::Node *node = m_tools.GetFirst();
279 while (node)
280 {
281 wxToolBarToolBase *tool = node->GetData();
282 if ( tool->GetStyle()!= wxTOOL_STYLE_BUTTON )
283 {
284 int state = tool->IsEnabled() ? wxTBSTATE_ENABLED : 0;
285 if ( tool->IsToggled() )
286 state |= wxTBSTATE_CHECKED;
287
288 DrawTool(dc, tool, state);
289 }
290
291 node = node->GetNext();
292 }
293
294 wxOnPaintCount--;
2bda0e17
KB
295}
296
297// If a Button is disabled, then NO function (besides leaving
298// or entering) should be carried out. Therefore the additions
299// of 'enabled' testing (Stefan Hammes).
8a0681f9 300void wxToolBar::OnMouseEvent(wxMouseEvent& event)
2bda0e17 301{
8a0681f9
VZ
302 static wxToolBarToolBase *eventCurrentTool = NULL;
303 wxClientDC dc(this);
2bda0e17 304
8a0681f9 305 if (event.Leaving())
2bda0e17 306 {
8a0681f9
VZ
307 m_currentTool = -1;
308 if (eventCurrentTool && eventCurrentTool->IsEnabled())
309 {
310 ::ReleaseCapture();
311 int state = wxTBSTATE_ENABLED;
312 if (eventCurrentTool->IsToggled())
313 state |= wxTBSTATE_CHECKED;
314 DrawTool(dc, eventCurrentTool, state);
315 eventCurrentTool = NULL;
316 }
317 OnMouseEnter(-1);
318 return;
2bda0e17 319 }
2bda0e17 320
8a0681f9
VZ
321 wxCoord x, y;
322 event.GetPosition(&x, &y);
323 wxToolBarToolBase *tool = FindToolForPosition(x, y);
2bda0e17 324
8a0681f9 325 if (!tool)
2bda0e17 326 {
8a0681f9
VZ
327 if (eventCurrentTool && eventCurrentTool->IsEnabled())
328 {
329 ::ReleaseCapture();
330
331 int state = wxTBSTATE_ENABLED;
332 if (eventCurrentTool->IsToggled())
333 state |= wxTBSTATE_CHECKED;
334 DrawTool(dc, eventCurrentTool, state);
335 eventCurrentTool = NULL;
336 }
337 if (m_currentTool > -1)
338 {
339 m_currentTool = -1;
340 OnMouseEnter(-1);
341 }
342 return;
2bda0e17 343 }
8a0681f9
VZ
344
345 if (!event.Dragging() && !event.IsButton())
2bda0e17 346 {
8a0681f9
VZ
347 if (tool->GetId() != m_currentTool)
348 {
349 OnMouseEnter(m_currentTool = tool->GetId());
350 return;
351 }
2bda0e17 352 }
8a0681f9 353 if (event.Dragging() && tool->IsEnabled())
2bda0e17 354 {
8a0681f9
VZ
355 if (eventCurrentTool)
356 {
357 // Might have dragged outside tool
358 if (eventCurrentTool != tool)
359 {
360 int state = wxTBSTATE_ENABLED;
361 if (tool->IsToggled())
362 state |= wxTBSTATE_CHECKED;
363 DrawTool(dc, tool, state);
364 eventCurrentTool = NULL;
365 return;
366 }
367 }
368 else
369 {
370 if (tool && event.LeftIsDown() && tool->IsEnabled())
371 {
372 eventCurrentTool = tool;
373 ::SetCapture((HWND) GetHWND());
374 int state = wxTBSTATE_ENABLED|wxTBSTATE_PRESSED;
375 if (tool->IsToggled())
376 state |= wxTBSTATE_CHECKED;
377 DrawTool(dc, tool, state);
378 }
379 }
2bda0e17 380 }
8a0681f9 381 if (event.LeftDown() && tool->IsEnabled())
2bda0e17 382 {
2bda0e17
KB
383 eventCurrentTool = tool;
384 ::SetCapture((HWND) GetHWND());
385 int state = wxTBSTATE_ENABLED|wxTBSTATE_PRESSED;
8a0681f9
VZ
386 if (tool->IsToggled())
387 state |= wxTBSTATE_CHECKED;
2bda0e17 388 DrawTool(dc, tool, state);
2bda0e17 389 }
8a0681f9 390 else if (event.LeftUp() && tool->IsEnabled())
2bda0e17 391 {
8a0681f9
VZ
392 if (eventCurrentTool)
393 ::ReleaseCapture();
394 if (eventCurrentTool == tool)
2bda0e17 395 {
8a0681f9
VZ
396 if (tool->CanBeToggled())
397 {
398 tool->Toggle();
399 if (!OnLeftClick(tool->GetId(), tool->IsToggled()))
400 {
401 tool->Toggle();
402 }
403 int state = wxTBSTATE_ENABLED;
404 if (tool->IsToggled())
405 state |= wxTBSTATE_CHECKED;
406 DrawTool(dc, tool, state);
407 }
408 else
409 {
410 int state = wxTBSTATE_ENABLED;
411 if (tool->IsToggled())
412 state |= wxTBSTATE_CHECKED;
413 DrawTool(dc, tool, state);
414 OnLeftClick(tool->GetId(), tool->IsToggled());
415 }
2bda0e17 416 }
8a0681f9
VZ
417 eventCurrentTool = NULL;
418 }
419 else if (event.RightDown() && tool->IsEnabled())
420 {
421 OnRightClick(tool->GetId(), x, y);
2bda0e17 422 }
2bda0e17
KB
423}
424
8a0681f9 425void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool WXUNUSED(enable))
2bda0e17 426{
8a0681f9 427 DoRedrawTool(tool);
2bda0e17
KB
428}
429
8a0681f9 430void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
2bda0e17 431{
8a0681f9 432 DoRedrawTool(tool);
2bda0e17
KB
433}
434
8a0681f9
VZ
435void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
436 bool WXUNUSED(toggle))
2bda0e17 437{
8a0681f9 438 // nothing to do
2bda0e17
KB
439}
440
8a0681f9 441void wxToolBar::DoRedrawTool(wxToolBarToolBase *tool)
2bda0e17 442{
8a0681f9 443 wxClientDC dc(this);
2bda0e17 444
8a0681f9
VZ
445 DrawTool(dc, tool);
446}
2bda0e17 447
8a0681f9
VZ
448void wxToolBar::DrawTool(wxDC& dc, wxToolBarToolBase *toolBase, int state)
449{
450 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
2bda0e17 451
8a0681f9
VZ
452 DrawButton(dc.GetHDC(),
453 tool->m_x, tool->m_y,
454 tool->GetWidth(), tool->GetHeight(),
455 tool, state);
456}
2bda0e17 457
8a0681f9
VZ
458void wxToolBar::DrawTool(wxDC& dc, wxToolBarToolBase *tool)
459{
460 int state = 0;
461 if (tool->IsEnabled())
462 state |= wxTBSTATE_ENABLED;
463 if (tool->IsToggled())
464 state |= wxTBSTATE_CHECKED;
465 // how can i access the PRESSED state???
2bda0e17 466
8a0681f9
VZ
467 DrawTool(dc, tool, state);
468}
2bda0e17 469
8a0681f9
VZ
470bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos),
471 wxToolBarToolBase *tool)
472{
473 // VZ: didn't test whether it works, but why not...
474 tool->Detach();
2bda0e17 475
8a0681f9 476 Refresh();
2bda0e17 477
8a0681f9 478 return TRUE;
2bda0e17
KB
479}
480
8a0681f9 481bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
81d66cf3 482{
8a0681f9 483 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
81d66cf3 484
8a0681f9
VZ
485 wxCHECK_MSG( !tool->IsControl(), FALSE,
486 _T("generic wxToolBar doesn't support controls") );
487
488 // TODO: use the mapping code from wxToolBar95 to get it right in this class
489#if !defined(__WIN32__) && !defined(__WIN386__)
a3399e6c 490 wxBitmap bmpDisabled;
c25a510b 491 if (tool->CanBeToggled())
8a0681f9
VZ
492 {
493 HBITMAP hbmp = CreateMappedBitmap((WXHINSTANCE)wxGetInstance(),
494 GetHbitmapOf(tool->GetBitmap1()));
495
496 wxBitmap bmp;
497 bmp.SetHBITMAP((WXHBITMAP)hbmp);
498 tool->SetBitmap2(bmp);
499 }
500#endif
81d66cf3 501
8a0681f9
VZ
502 tool->m_x = m_xPos;
503 if ( tool->m_x == -1 )
504 tool->m_x = m_xMargin;
81d66cf3 505
8a0681f9
VZ
506 tool->m_y = m_yPos;
507 if ( tool->m_y == -1 )
508 tool->m_y = m_yMargin;
509
510 tool->SetSize(GetToolSize());
511
512 if ( tool->IsButton() )
81d66cf3 513 {
8a0681f9
VZ
514 // Calculate reasonable max size in case Layout() not called
515 if ((tool->m_x + tool->GetBitmap1().GetWidth() + m_xMargin) > m_maxWidth)
516 m_maxWidth = (tool->m_x + tool->GetWidth() + m_xMargin);
517
518 if ((tool->m_y + tool->GetBitmap1().GetHeight() + m_yMargin) > m_maxHeight)
519 m_maxHeight = (tool->m_y + tool->GetHeight() + m_yMargin);
81d66cf3 520 }
8a0681f9
VZ
521
522 return TRUE;
523}
524
525bool wxToolBar::Realize()
526{
527 m_currentRowsOrColumns = 0;
528 m_lastX = m_xMargin;
529 m_lastY = m_yMargin;
530 int maxToolWidth = 0;
531 int maxToolHeight = 0;
532 m_maxWidth = 0;
533 m_maxHeight = 0;
534
535 // Find the maximum tool width and height
536 wxToolBarToolsList::Node *node = m_tools.GetFirst();
537 while (node)
81d66cf3 538 {
8a0681f9
VZ
539 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
540 if (tool->GetWidth() > maxToolWidth)
541 maxToolWidth = tool->GetWidth();
542 if (tool->GetHeight() > maxToolHeight)
543 maxToolHeight = tool->GetHeight();
544 node = node->GetNext();
545 }
546
547 int separatorSize = m_toolSeparation;
548
549 node = m_tools.GetFirst();
550 while (node)
551 {
552 wxToolBarTool *tool = (wxToolBarTool *)node->GetData();
553 if (tool->GetStyle() == wxTOOL_STYLE_SEPARATOR)
81d66cf3 554 {
8a0681f9
VZ
555 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
556 {
557 if (m_currentRowsOrColumns >= m_maxCols)
558 m_lastY += separatorSize;
559 else
560 m_lastX += separatorSize;
561 }
562 else
563 {
564 if (m_currentRowsOrColumns >= m_maxRows)
565 m_lastX += separatorSize;
566 else
567 m_lastY += separatorSize;
568 }
81d66cf3 569 }
8a0681f9 570 else if (tool->GetStyle() == wxTOOL_STYLE_BUTTON)
81d66cf3 571 {
8a0681f9
VZ
572 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
573 {
574 if (m_currentRowsOrColumns >= m_maxCols)
575 {
576 m_currentRowsOrColumns = 0;
577 m_lastX = m_xMargin;
578 m_lastY += maxToolHeight + m_toolPacking;
579 }
580 tool->m_x = (long) (m_lastX + (maxToolWidth - tool->GetWidth())/2.0);
581 tool->m_y = (long) (m_lastY + (maxToolHeight - tool->GetHeight())/2.0);
582
583 m_lastX += maxToolWidth + m_toolPacking;
584 }
585 else
586 {
587 if (m_currentRowsOrColumns >= m_maxRows)
588 {
589 m_currentRowsOrColumns = 0;
590 m_lastX += (maxToolWidth + m_toolPacking);
591 m_lastY = m_yMargin;
592 }
593 tool->m_x = (long) (m_lastX + (maxToolWidth - tool->GetWidth())/2.0);
594 tool->m_y = (long) (m_lastY + (maxToolHeight - tool->GetHeight())/2.0);
595
596 m_lastY += maxToolHeight + m_toolPacking;
597 }
598 m_currentRowsOrColumns ++;
81d66cf3 599 }
8a0681f9
VZ
600
601 if (m_lastX > m_maxWidth)
602 m_maxWidth = m_lastX;
603 if (m_lastY > m_maxHeight)
604 m_maxHeight = m_lastY;
605
606 node = node->GetNext();
81d66cf3 607 }
81d66cf3 608
8a0681f9
VZ
609 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
610 {
611 m_maxWidth += maxToolWidth;
612 m_maxHeight += maxToolHeight;
613 }
614 else
615 {
616 m_maxWidth += maxToolWidth;
617 m_maxHeight += maxToolHeight;
618 }
81d66cf3 619
8a0681f9
VZ
620 m_maxWidth += m_xMargin;
621 m_maxHeight += m_yMargin;
2a47d3c1 622
8a0681f9 623 SetSize(m_maxWidth, m_maxHeight);
81d66cf3 624
8a0681f9
VZ
625 return TRUE;
626}
81d66cf3 627
8a0681f9 628bool wxToolBar::InitGlobalObjects()
2bda0e17 629{
8a0681f9
VZ
630 GetSysColors();
631 if (!CreateDitherBrush())
632 return FALSE;
2bda0e17 633
8a0681f9
VZ
634 m_hdcMono = (WXHDC) CreateCompatibleDC(NULL);
635 if (!m_hdcMono)
636 return FALSE;
2bda0e17 637
8a0681f9
VZ
638 m_hbmMono = (WXHBITMAP) CreateBitmap((int)GetToolSize().x, (int)GetToolSize().y, 1, 1, NULL);
639 if (!m_hbmMono)
640 return FALSE;
2bda0e17 641
8a0681f9
VZ
642 m_hbmDefault = (WXHBITMAP) SelectObject((HDC) m_hdcMono, (HBITMAP) m_hbmMono);
643 return TRUE;
2bda0e17
KB
644}
645
8a0681f9 646void wxToolBar::FreeGlobalObjects()
2bda0e17
KB
647{
648 FreeDitherBrush();
649
650 if (m_hdcMono) {
8a0681f9
VZ
651 if (m_hbmDefault)
652 {
653 SelectObject((HDC) m_hdcMono, (HBITMAP) m_hbmDefault);
654 m_hbmDefault = 0;
655 }
656 DeleteDC((HDC) m_hdcMono); // toast the DCs
2bda0e17
KB
657 }
658 m_hdcMono = 0;
659
660 if (m_hbmMono)
8a0681f9 661 DeleteObject((HBITMAP) m_hbmMono);
2bda0e17
KB
662 m_hbmMono = 0;
663}
664
8a0681f9
VZ
665// ----------------------------------------------------------------------------
666// drawing routines
667// ----------------------------------------------------------------------------
2bda0e17 668
8a0681f9 669void wxToolBar::PatB(WXHDC hdc,int x,int y,int dx,int dy, long rgb)
2bda0e17
KB
670{
671 RECT rc;
672
673 rc.left = x;
674 rc.top = y;
675 rc.right = x + dx;
676 rc.bottom = y + dy;
677
678 SetBkColor((HDC) hdc,rgb);
679 ExtTextOut((HDC) hdc,0,0,ETO_OPAQUE,&rc,NULL,0,NULL);
680}
681
682
683// create a mono bitmap mask:
684// 1's where color == COLOR_BTNFACE || COLOR_HILIGHT
685// 0's everywhere else
686
8a0681f9 687void wxToolBar::CreateMask(WXHDC hdc, int xoffset, int yoffset, int dx, int dy)
2bda0e17
KB
688{
689 HDC globalDC = ::GetDC(NULL);
690 HDC hdcGlyphs = CreateCompatibleDC((HDC) globalDC);
691 ReleaseDC(NULL, (HDC) globalDC);
692
693 // krj - create a new bitmap and copy the image from hdc.
694 //HBITMAP bitmapOld = SelectObject(hdcGlyphs, hBitmap);
695 HBITMAP hBitmap = CreateCompatibleBitmap((HDC) hdc, dx, dy);
c4e7c2aa 696 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, hBitmap);
2bda0e17
KB
697 BitBlt(hdcGlyphs, 0,0, dx, dy, (HDC) hdc, 0, 0, SRCCOPY);
698
699 // initalize whole area with 1's
700 PatBlt((HDC) m_hdcMono, 0, 0, dx, dy, WHITENESS);
701
702 // create mask based on color bitmap
703 // convert this to 1's
704 SetBkColor(hdcGlyphs, m_rgbFace);
81d66cf3 705 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
2bda0e17
KB
706 hdcGlyphs, 0, 0, SRCCOPY);
707 // convert this to 1's
708 SetBkColor(hdcGlyphs, m_rgbHilight);
709 // OR in the new 1's
81d66cf3 710 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
2bda0e17
KB
711 hdcGlyphs, 0, 0, SRCPAINT);
712
713 SelectObject(hdcGlyphs, bitmapOld);
714 DeleteObject(hBitmap);
715 DeleteDC(hdcGlyphs);
716}
717
8a0681f9 718void wxToolBar::DrawBlankButton(WXHDC hdc, int x, int y, int dx, int dy, int state)
2bda0e17
KB
719{
720 // face color
721 PatB(hdc, x, y, dx, dy, m_rgbFace);
722
723 if (state & wxTBSTATE_PRESSED) {
8a0681f9
VZ
724 PatB(hdc, x + 1, y, dx - 2, 1, m_rgbFrame);
725 PatB(hdc, x + 1, y + dy - 1, dx - 2, 1, m_rgbFrame);
726 PatB(hdc, x, y + 1, 1, dy - 2, m_rgbFrame);
727 PatB(hdc, x + dx - 1, y +1, 1, dy - 2, m_rgbFrame);
728 PatB(hdc, x + 1, y + 1, 1, dy-2, m_rgbShadow);
729 PatB(hdc, x + 1, y + 1, dx-2, 1, m_rgbShadow);
2bda0e17
KB
730 }
731 else {
8a0681f9
VZ
732 PatB(hdc, x + 1, y, dx - 2, 1, m_rgbFrame);
733 PatB(hdc, x + 1, y + dy - 1, dx - 2, 1, m_rgbFrame);
734 PatB(hdc, x, y + 1, 1, dy - 2, m_rgbFrame);
735 PatB(hdc, x + dx - 1, y + 1, 1, dy - 2, m_rgbFrame);
736 dx -= 2;
737 dy -= 2;
738 PatB(hdc, x + 1, y + 1, 1, dy - 1, m_rgbHilight);
739 PatB(hdc, x + 1, y + 1, dx - 1, 1, m_rgbHilight);
740 PatB(hdc, x + dx, y + 1, 1, dy, m_rgbShadow);
741 PatB(hdc, x + 1, y + dy, dx, 1, m_rgbShadow);
742 PatB(hdc, x + dx - 1, y + 2, 1, dy - 2, m_rgbShadow);
743 PatB(hdc, x + 2, y + dy - 1, dx - 2, 1, m_rgbShadow);
2bda0e17
KB
744 }
745}
746
1dbe8708
VZ
747void wxToolBar::DrawButton(WXHDC hdc, int x, int y, int dx, int dy,
748 wxToolBarToolBase *toolBase, int state)
2bda0e17 749{
1dbe8708
VZ
750 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
751
2bda0e17
KB
752 int yOffset;
753 HBRUSH hbrOld, hbr;
754 BOOL bMaskCreated = FALSE;
755 int xButton = 0; // assume button is down
756 int dxFace, dyFace;
757 int xCenterOffset;
758
759 dxFace = dx;
760 dyFace = dy;
761
762// HBITMAP hBitmap = (HBITMAP) tool->m_bitmap1.GetHBITMAP();
763 HDC globalDC = ::GetDC(NULL);
764 HDC hdcGlyphs = CreateCompatibleDC(globalDC);
765 ReleaseDC(NULL, globalDC);
766
767 // get the proper button look - up or down.
768 if (!(state & (wxTBSTATE_PRESSED | wxTBSTATE_CHECKED))) {
769 xButton = dx; // use 'up' version of button
770 dxFace -= 2;
771 dyFace -= 2; // extents to ignore button highlight
772 }
773
774 DrawBlankButton(hdc, x, y, dx, dy, state);
775
776
777 // move coordinates inside border and away from upper left highlight.
778 // the extents change accordingly.
779 x += 2;
780 y += 2;
781 dxFace -= 3;
782 dyFace -= 3;
783
a3399e6c 784 // Using bmpDisabled can cause problems (don't know why!)
2bda0e17
KB
785#if !defined(__WIN32__) && !defined(__WIN386__)
786 HBITMAP bitmapOld;
8a0681f9
VZ
787 if (tool->GetBitmap2().Ok())
788 bitmapOld = GetHbitmapOf(tool->GetBitmap2());
2bda0e17 789 else
8a0681f9 790 bitmapOld = GetHbitmapOf(tool->GetBitmap1());
2bda0e17 791#else
8a0681f9 792 HBITMAP bitmapOld = GetHbitmapOf(tool->GetBitmap1());
2bda0e17
KB
793#endif
794
8a0681f9
VZ
795 bitmapOld = (HBITMAP)SelectObject(hdcGlyphs, bitmapOld);
796
2bda0e17
KB
797 // calculate offset of face from (x,y). y is always from the top,
798 // so the offset is easy. x needs to be centered in face.
799 yOffset = 1;
81d66cf3 800 xCenterOffset = (dxFace - (int)GetToolBitmapSize().x)/2;
2bda0e17
KB
801 if (state & (wxTBSTATE_PRESSED | wxTBSTATE_CHECKED))
802 {
803 // pressed state moves down and to the right
804 // (x moves automatically as face size grows)
805 yOffset++;
806 }
807
808 // now put on the face
809 if (state & wxTBSTATE_ENABLED) {
810 // regular version
81d66cf3 811 BitBlt((HDC) hdc, x+xCenterOffset, y + yOffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
2bda0e17
KB
812 hdcGlyphs, 0, 0, SRCCOPY);
813 } else {
814 // disabled version (or indeterminate)
815 bMaskCreated = TRUE;
816 CreateMask((WXHDC) hdcGlyphs, xCenterOffset, yOffset, dxFace, dyFace);
817// CreateMask(hBitmap, xCenterOffset, yOffset, dxFace, dyFace);
818
819 SetTextColor((HDC) hdc, 0L); // 0's in mono -> 0 (for ROP)
820 SetBkColor((HDC) hdc, 0x00FFFFFF); // 1's in mono -> 1
821
822 // draw glyph's white understrike
823 if (!(state & wxTBSTATE_INDETERMINATE)) {
824 hbr = CreateSolidBrush(m_rgbHilight);
825 if (hbr) {
c4e7c2aa 826 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
2bda0e17
KB
827 if (hbrOld) {
828 // draw hilight color where we have 0's in the mask
829 BitBlt((HDC) hdc, x + 1, y + 1, dxFace, dyFace, (HDC) m_hdcMono, 0, 0, 0x00B8074A);
830 SelectObject((HDC) hdc, hbrOld);
831 }
832 DeleteObject(hbr);
833 }
834 }
835
836 // gray out glyph
837 hbr = CreateSolidBrush(m_rgbShadow);
838 if (hbr) {
c4e7c2aa 839 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
2bda0e17
KB
840 if (hbrOld) {
841 // draw the shadow color where we have 0's in the mask
842 BitBlt((HDC) hdc, x, y, dxFace, dyFace, (HDC) m_hdcMono, 0, 0, 0x00B8074A);
843 SelectObject((HDC) hdc, hbrOld);
844 }
845 DeleteObject(hbr);
846 }
847
848 if (state & wxTBSTATE_CHECKED) {
849 BitBlt((HDC) m_hdcMono, 1, 1, dxFace - 1, dyFace - 1, (HDC) m_hdcMono, 0, 0, SRCAND);
850 }
851 }
852
853 if (state & (wxTBSTATE_CHECKED | wxTBSTATE_INDETERMINATE)) {
854
c4e7c2aa 855 hbrOld = (HBRUSH) SelectObject((HDC) hdc, (HBRUSH) m_hbrDither);
2bda0e17
KB
856 if (hbrOld) {
857
858 if (!bMaskCreated)
859 CreateMask((WXHDC) hdcGlyphs, xCenterOffset, yOffset, dxFace, dyFace);
860// CreateMask(hBitmap, xCenterOffset, yOffset, dxFace, dyFace);
861
862 SetTextColor((HDC) hdc, 0L); // 0 -> 0
863 SetBkColor((HDC) hdc, 0x00FFFFFF); // 1 -> 1
864
865 // only draw the dither brush where the mask is 1's
866 BitBlt((HDC) hdc, x, y, dxFace, dyFace, (HDC) m_hdcMono, 0, 0, 0x00E20746);
867
868 SelectObject((HDC) hdc, hbrOld);
869 }
870 }
871 SelectObject(hdcGlyphs, bitmapOld);
872 DeleteDC(hdcGlyphs);
873}
874
8a0681f9
VZ
875// ----------------------------------------------------------------------------
876// drawing helpers
877// ----------------------------------------------------------------------------
878
879void wxToolBar::GetSysColors()
2bda0e17
KB
880{
881 static COLORREF rgbSaveFace = 0xffffffffL,
882 rgbSaveShadow = 0xffffffffL,
883 rgbSaveHilight = 0xffffffffL,
884 rgbSaveFrame = 0xffffffffL;
885
886 // For now, override these because the colour replacement isn't working,
887 // and we get inconsistent colours. Assume all buttons are grey for the moment.
888
889// m_rgbFace = GetSysColor(COLOR_BTNFACE);
890 m_rgbFace = RGB(192,192,192);
891// m_rgbShadow = GetSysColor(COLOR_BTNSHADOW);
892 m_rgbShadow = RGB(128,128,128);
893// m_rgbHilight = GetSysColor(COLOR_BTNHIGHLIGHT);
894 m_rgbHilight = RGB(255, 255, 255);
895
896 m_rgbFrame = GetSysColor(COLOR_WINDOWFRAME);
897
898 if (rgbSaveFace!=m_rgbFace || rgbSaveShadow!=m_rgbShadow
899 || rgbSaveHilight!=m_rgbHilight || rgbSaveFrame!=m_rgbFrame)
900 {
901 rgbSaveFace = m_rgbFace;
902 rgbSaveShadow = m_rgbShadow;
903 rgbSaveHilight = m_rgbHilight;
904 rgbSaveFrame = m_rgbFrame;
905
906 // Update the brush for pushed-in buttons
907 CreateDitherBrush();
908 }
909}
910
8a0681f9 911WXHBITMAP wxToolBar::CreateDitherBitmap()
2bda0e17
KB
912{
913 BITMAPINFO* pbmi;
914 HBITMAP hbm;
915 HDC hdc;
916 int i;
917 long patGray[8];
918 DWORD rgb;
919
920 pbmi = (BITMAPINFO *)malloc(sizeof(BITMAPINFOHEADER) + 16*sizeof(RGBQUAD));
921 memset(pbmi, 0, (sizeof(BITMAPINFOHEADER) + 16*sizeof(RGBQUAD)));
922
923 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
924 pbmi->bmiHeader.biWidth = 8;
925 pbmi->bmiHeader.biHeight = 8;
926 pbmi->bmiHeader.biPlanes = 1;
927 pbmi->bmiHeader.biBitCount = 1;
928 pbmi->bmiHeader.biCompression = BI_RGB;
929
930// rgb = GetSysColor(COLOR_BTNFACE);
931 rgb = RGB(192,192,192);
932
933 pbmi->bmiColors[0].rgbBlue = GetBValue(rgb);
934 pbmi->bmiColors[0].rgbGreen = GetGValue(rgb);
935 pbmi->bmiColors[0].rgbRed = GetRValue(rgb);
936 pbmi->bmiColors[0].rgbReserved = 0;
937
938// rgb = GetSysColor(COLOR_BTNHIGHLIGHT);
939 rgb = RGB(255, 255, 255);
940
941 pbmi->bmiColors[1].rgbBlue = GetBValue(rgb);
942 pbmi->bmiColors[1].rgbGreen = GetGValue(rgb);
943 pbmi->bmiColors[1].rgbRed = GetRValue(rgb);
944 pbmi->bmiColors[1].rgbReserved = 0;
945
946 /* initialize the brushes */
947
948 for (i = 0; i < 8; i++)
949 if (i & 1)
950 patGray[i] = 0xAAAA5555L; // 0x11114444L; // lighter gray
951 else
952 patGray[i] = 0x5555AAAAL; // 0x11114444L; // lighter gray
953
954 hdc = ::GetDC(NULL);
955
956 hbm = CreateDIBitmap(hdc, &pbmi->bmiHeader, CBM_INIT, patGray, pbmi, DIB_RGB_COLORS);
957
958 ReleaseDC(NULL, hdc);
959 free(pbmi);
960
961 return (WXHBITMAP)hbm;
962}
963
8a0681f9 964bool wxToolBar::CreateDitherBrush()
2bda0e17
KB
965{
966 HBITMAP hbmGray;
967 HBRUSH hbrSave;
968 if (m_hbrDither)
969 return TRUE;
970 hbmGray = (HBITMAP) CreateDitherBitmap();
971
972 if (hbmGray)
973 {
974 hbrSave = (HBRUSH) m_hbrDither;
975 m_hbrDither = (WXHBRUSH) CreatePatternBrush(hbmGray);
976 DeleteObject(hbmGray);
977 if (m_hbrDither)
978 {
979 if (hbrSave)
980 {
981 DeleteObject(hbrSave);
982 }
983 return TRUE;
984 }
985 else
986 {
987 m_hbrDither = (WXHBRUSH) hbrSave;
988 }
989 }
990
991 return FALSE;
992}
993
8a0681f9 994bool wxToolBar::FreeDitherBrush(void)
2bda0e17
KB
995{
996 if (m_hbrDither)
997 DeleteObject((HBRUSH) m_hbrDither);
998 m_hbrDither = 0;
999 return TRUE;
1000}
1001
1002typedef struct tagCOLORMAP2
1003{
1004 COLORREF bgrfrom;
1005 COLORREF bgrto;
1006 COLORREF sysColor;
1007} COLORMAP2;
1008
1009// these are the default colors used to map the dib colors
1010// to the current system colors
1011
1012#define BGR_BUTTONTEXT (RGB(000,000,000)) // black
1013#define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey
1014#define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey
1015#define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white
8a0681f9 1016#define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue
2bda0e17
KB
1017#define BGR_BACKGROUND (RGB(255,000,255)) // magenta
1018#define FlipColor(rgb) (RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb)))
1019
8a0681f9 1020WXHBITMAP wxToolBar::CreateMappedBitmap(WXHINSTANCE WXUNUSED(hInstance), void *info)
2bda0e17
KB
1021{
1022 LPBITMAPINFOHEADER lpBitmapInfo = (LPBITMAPINFOHEADER)info;
1023 HDC hdc, hdcMem = NULL;
1024
1025 DWORD FAR *p;
1026 LPSTR lpBits;
1027 HBITMAP hbm = NULL, hbmOld;
1028 int numcolors, i;
1029 int wid, hgt;
1030 static COLORMAP2 ColorMap[] = {
1031 {BGR_BUTTONTEXT, BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black
1032 {BGR_BUTTONSHADOW, BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey
1033 {BGR_BUTTONFACE, BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey
1034 {BGR_BUTTONHILIGHT, BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white
1035 {BGR_BACKGROUNDSEL, BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue
1036 {BGR_BACKGROUND, BGR_BACKGROUND, COLOR_WINDOW} // magenta
1037 };
1038
1039 #define NUM_MAPS (sizeof(ColorMap)/sizeof(COLORMAP2))
1040
1041 if (!lpBitmapInfo)
1042 return 0;
1043
1044 //
1045 // So what are the new colors anyway ?
1046 //
1047 for (i=0; i < (int) NUM_MAPS; i++) {
1048 ColorMap[i].bgrto = (long unsigned int) FlipColor(GetSysColor((int)ColorMap[i].sysColor));
1049 }
1050
1051 p = (DWORD FAR *)(((LPSTR)lpBitmapInfo) + lpBitmapInfo->biSize);
1052
1053 /* Replace button-face and button-shadow colors with the current values
1054 */
1055 numcolors = 16;
1056
1057 while (numcolors-- > 0) {
1058 for (i = 0; i < (int) NUM_MAPS; i++) {
1059 if (*p == ColorMap[i].bgrfrom) {
1060 *p = ColorMap[i].bgrto;
1061 break;
1062 }
1063 }
1064 p++;
1065 }
1066
1067 /* First skip over the header structure */
1068 lpBits = (LPSTR)(lpBitmapInfo + 1);
1069
1070 /* Skip the color table entries, if any */
1071 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
1072
1073 /* Create a color bitmap compatible with the display device */
1074 i = wid = (int)lpBitmapInfo->biWidth;
1075 hgt = (int)lpBitmapInfo->biHeight;
1076 hdc = ::GetDC(NULL);
1077
1078 hdcMem = CreateCompatibleDC(hdc);
1079 if (hdcMem) {
1080// hbm = CreateDiscardableBitmap(hdc, i, hgt);
1081 hbm = CreateCompatibleBitmap(hdc, i, hgt);
1082 if (hbm) {
c4e7c2aa 1083 hbmOld = (HBITMAP) SelectObject(hdcMem, hbm);
2bda0e17
KB
1084
1085 // set the main image
1086 StretchDIBits(hdcMem, 0, 0, wid, hgt, 0, 0, wid, hgt, lpBits,
1087 (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
1088
1089 SelectObject(hdcMem, hbmOld);
1090 }
1091
1092 DeleteObject(hdcMem);
1093 }
1094
1095 ReleaseDC(NULL, hdc);
1096
1097 return (WXHBITMAP) hbm;
1098}
1099
8a0681f9 1100WXHBITMAP wxToolBar::CreateMappedBitmap(WXHINSTANCE hInstance, WXHBITMAP hBitmap)
2bda0e17 1101{
2b254edf
VZ
1102 HANDLE hDIB = wxDIB::ConvertFromBitmap((HBITMAP) hBitmap);
1103 if ( !hDIB )
1104 return 0;
1105
06d09389 1106 WXHBITMAP newBitmap = CreateMappedBitmap(hInstance, GlobalPtr(hDIB));
2b254edf 1107
2bda0e17 1108 GlobalFree(hDIB);
2b254edf
VZ
1109
1110 return newBitmap;
2bda0e17
KB
1111}
1112
2b254edf
VZ
1113#endif // wxUSE_TOOLBAR
1114