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