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