]> git.saurik.com Git - wxWidgets.git/blob - src/msw/tbarmsw.cpp
fixed crash on startup under GTK
[wxWidgets.git] / src / msw / tbarmsw.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: tbarmsw.cpp
3 // Purpose: wxToolBar
4 // Author: Julian Smart
5 // Modified by: 13.12.99 by VZ during toolbar classes reorganization
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "tbarmsw.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/wx.h"
33 #endif
34
35 #if wxUSE_TOOLBAR && defined(__WIN16__)
36
37 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__)
38 #include "malloc.h"
39 #endif
40
41 #if !defined(__MWERKS__) && !defined(__SALFORDC__)
42 #include <memory.h>
43 #endif
44
45 #include <stdlib.h>
46
47 #include "wx/msw/tbarmsw.h"
48 #include "wx/event.h"
49 #include "wx/app.h"
50 #include "wx/bitmap.h"
51 #include "wx/msw/private.h"
52 #include "wx/msw/dib.h"
53
54 // ----------------------------------------------------------------------------
55 // constants
56 // ----------------------------------------------------------------------------
57
58 #define DEFAULTBITMAPX 16
59 #define DEFAULTBITMAPY 15
60 #define DEFAULTBUTTONX 24
61 #define DEFAULTBUTTONY 22
62 #define DEFAULTBARHEIGHT 27
63
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
72
73 // ----------------------------------------------------------------------------
74 // private classes
75 // ----------------------------------------------------------------------------
76
77 class WXDLLEXPORT wxToolBarTool : public wxToolBarToolBase
78 {
79 public:
80 wxToolBarTool(wxToolBar *tbar,
81 int id,
82 const wxBitmap& bmpNormal,
83 const wxBitmap& bmpDisabled,
84 bool toggle,
85 wxObject *clientData,
86 const wxString& shortHelp,
87 const wxString& longHelp)
88 : wxToolBarToolBase(tbar, id, bmpNormal, bmpDisabled, toggle,
89 clientData, shortHelp, longHelp)
90 {
91 }
92
93 wxToolBarTool(wxToolBar *tbar, wxControl *control)
94 : wxToolBarToolBase(tbar, control)
95 {
96 }
97
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
118 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
119
120 BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
121 EVT_PAINT(wxToolBar::OnPaint)
122 EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent)
123 END_EVENT_TABLE()
124 #endif
125
126 // ============================================================================
127 // implementation
128 // ============================================================================
129
130 // ----------------------------------------------------------------------------
131 // wxToolBarTool
132 // ----------------------------------------------------------------------------
133
134 wxToolBarToolBase *wxToolBar::CreateTool(int id,
135 const wxString& label,
136 const wxBitmap& bmpNormal,
137 const wxBitmap& bmpDisabled,
138 wxItemKind kind,
139 wxObject *clientData,
140 const wxString& shortHelp,
141 const wxString& longHelp)
142 {
143 return new wxToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
144 clientData, shortHelp, longHelp);
145 }
146
147 wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
148 {
149 return new wxToolBarTool(this, control);
150 }
151
152 // ----------------------------------------------------------------------------
153 // wxToolBar
154 // ----------------------------------------------------------------------------
155
156 void wxToolBar::Init()
157 {
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;
169
170 m_xPos =
171 m_yPos = -1;
172
173 m_maxWidth = m_maxHeight = 0;
174 m_pressedTool = m_currentTool = -1;
175 m_toolPacking = 1;
176 m_toolSeparation = 5;
177 }
178
179 bool 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;
188
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 }
199
200 // Set it to grey
201 SetBackgroundColour(wxColour(192, 192, 192));
202
203 InitGlobalObjects();
204
205 return TRUE;
206 }
207
208 wxToolBar::~wxToolBar()
209 {
210 FreeGlobalObjects();
211 }
212
213 void wxToolBar::SetToolBitmapSize(const wxSize& size)
214 {
215 m_defaultWidth = size.x;
216 m_defaultHeight = size.y;
217
218 FreeGlobalObjects();
219 InitGlobalObjects();
220 }
221
222 // The button size is bigger than the bitmap size
223 wxSize wxToolBar::GetToolSize() const
224 {
225 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
226 }
227
228 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
229 {
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 }
240
241 node = node->GetNext();
242 }
243
244 return (wxToolBarToolBase *)NULL;
245 }
246
247 wxToolBarToolBase *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);
264 }
265
266 void wxToolBar::OnPaint(wxPaintEvent& event)
267 {
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--;
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).
300 void wxToolBar::OnMouseEvent(wxMouseEvent& event)
301 {
302 static wxToolBarToolBase *eventCurrentTool = NULL;
303 wxClientDC dc(this);
304
305 if (event.Leaving())
306 {
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;
319 }
320
321 wxCoord x, y;
322 event.GetPosition(&x, &y);
323 wxToolBarToolBase *tool = FindToolForPosition(x, y);
324
325 if (!tool)
326 {
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;
343 }
344
345 if (!event.Dragging() && !event.IsButton())
346 {
347 if (tool->GetId() != m_currentTool)
348 {
349 OnMouseEnter(m_currentTool = tool->GetId());
350 return;
351 }
352 }
353 if (event.Dragging() && tool->IsEnabled())
354 {
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 }
380 }
381 if (event.LeftDown() && tool->IsEnabled())
382 {
383 eventCurrentTool = tool;
384 ::SetCapture((HWND) GetHWND());
385 int state = wxTBSTATE_ENABLED|wxTBSTATE_PRESSED;
386 if (tool->IsToggled())
387 state |= wxTBSTATE_CHECKED;
388 DrawTool(dc, tool, state);
389 }
390 else if (event.LeftUp() && tool->IsEnabled())
391 {
392 if (eventCurrentTool)
393 ::ReleaseCapture();
394 if (eventCurrentTool == tool)
395 {
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 }
416 }
417 eventCurrentTool = NULL;
418 }
419 else if (event.RightDown() && tool->IsEnabled())
420 {
421 OnRightClick(tool->GetId(), x, y);
422 }
423 }
424
425 void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool WXUNUSED(enable))
426 {
427 DoRedrawTool(tool);
428 }
429
430 void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
431 {
432 DoRedrawTool(tool);
433 }
434
435 void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
436 bool WXUNUSED(toggle))
437 {
438 // nothing to do
439 }
440
441 void wxToolBar::DoRedrawTool(wxToolBarToolBase *tool)
442 {
443 wxClientDC dc(this);
444
445 DrawTool(dc, tool);
446 }
447
448 void wxToolBar::DrawTool(wxDC& dc, wxToolBarToolBase *toolBase, int state)
449 {
450 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
451
452 DrawButton(dc.GetHDC(),
453 tool->m_x, tool->m_y,
454 tool->GetWidth(), tool->GetHeight(),
455 tool, state);
456 }
457
458 void 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???
466
467 DrawTool(dc, tool, state);
468 }
469
470 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos),
471 wxToolBarToolBase *tool)
472 {
473 // VZ: didn't test whether it works, but why not...
474 tool->Detach();
475
476 Refresh();
477
478 return TRUE;
479 }
480
481 bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
482 {
483 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
484
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__)
490 wxBitmap bmpDisabled;
491 if (tool->CanBeToggled())
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
501
502 tool->m_x = m_xPos;
503 if ( tool->m_x == -1 )
504 tool->m_x = m_xMargin;
505
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() )
513 {
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);
520 }
521
522 return TRUE;
523 }
524
525 bool 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)
538 {
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)
554 {
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 }
569 }
570 else if (tool->GetStyle() == wxTOOL_STYLE_BUTTON)
571 {
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 ++;
599 }
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();
607 }
608
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 }
619
620 m_maxWidth += m_xMargin;
621 m_maxHeight += m_yMargin;
622
623 SetSize(m_maxWidth, m_maxHeight);
624
625 return TRUE;
626 }
627
628 bool wxToolBar::InitGlobalObjects()
629 {
630 GetSysColors();
631 if (!CreateDitherBrush())
632 return FALSE;
633
634 m_hdcMono = (WXHDC) CreateCompatibleDC(NULL);
635 if (!m_hdcMono)
636 return FALSE;
637
638 m_hbmMono = (WXHBITMAP) CreateBitmap((int)GetToolSize().x, (int)GetToolSize().y, 1, 1, NULL);
639 if (!m_hbmMono)
640 return FALSE;
641
642 m_hbmDefault = (WXHBITMAP) SelectObject((HDC) m_hdcMono, (HBITMAP) m_hbmMono);
643 return TRUE;
644 }
645
646 void wxToolBar::FreeGlobalObjects()
647 {
648 FreeDitherBrush();
649
650 if (m_hdcMono) {
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
657 }
658 m_hdcMono = 0;
659
660 if (m_hbmMono)
661 DeleteObject((HBITMAP) m_hbmMono);
662 m_hbmMono = 0;
663 }
664
665 // ----------------------------------------------------------------------------
666 // drawing routines
667 // ----------------------------------------------------------------------------
668
669 void wxToolBar::PatB(WXHDC hdc,int x,int y,int dx,int dy, long rgb)
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
687 void wxToolBar::CreateMask(WXHDC hdc, int xoffset, int yoffset, int dx, int dy)
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);
696 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, hBitmap);
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);
705 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
706 hdcGlyphs, 0, 0, SRCCOPY);
707 // convert this to 1's
708 SetBkColor(hdcGlyphs, m_rgbHilight);
709 // OR in the new 1's
710 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
711 hdcGlyphs, 0, 0, SRCPAINT);
712
713 SelectObject(hdcGlyphs, bitmapOld);
714 DeleteObject(hBitmap);
715 DeleteDC(hdcGlyphs);
716 }
717
718 void wxToolBar::DrawBlankButton(WXHDC hdc, int x, int y, int dx, int dy, int state)
719 {
720 // face color
721 PatB(hdc, x, y, dx, dy, m_rgbFace);
722
723 if (state & wxTBSTATE_PRESSED) {
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);
730 }
731 else {
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);
744 }
745 }
746
747 void wxToolBar::DrawButton(WXHDC hdc, int x, int y, int dx, int dy,
748 wxToolBarToolBase *toolBase, int state)
749 {
750 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
751
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
784 // Using bmpDisabled can cause problems (don't know why!)
785 #if !defined(__WIN32__) && !defined(__WIN386__)
786 HBITMAP bitmapOld;
787 if (tool->GetBitmap2().Ok())
788 bitmapOld = GetHbitmapOf(tool->GetBitmap2());
789 else
790 bitmapOld = GetHbitmapOf(tool->GetBitmap1());
791 #else
792 HBITMAP bitmapOld = GetHbitmapOf(tool->GetBitmap1());
793 #endif
794
795 bitmapOld = (HBITMAP)SelectObject(hdcGlyphs, bitmapOld);
796
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;
800 xCenterOffset = (dxFace - (int)GetToolBitmapSize().x)/2;
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
811 BitBlt((HDC) hdc, x+xCenterOffset, y + yOffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
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) {
826 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
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) {
839 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
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
855 hbrOld = (HBRUSH) SelectObject((HDC) hdc, (HBRUSH) m_hbrDither);
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
875 // ----------------------------------------------------------------------------
876 // drawing helpers
877 // ----------------------------------------------------------------------------
878
879 void wxToolBar::GetSysColors()
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
911 WXHBITMAP wxToolBar::CreateDitherBitmap()
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
964 bool wxToolBar::CreateDitherBrush()
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
994 bool wxToolBar::FreeDitherBrush(void)
995 {
996 if (m_hbrDither)
997 DeleteObject((HBRUSH) m_hbrDither);
998 m_hbrDither = 0;
999 return TRUE;
1000 }
1001
1002 typedef 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
1016 #define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue
1017 #define BGR_BACKGROUND (RGB(255,000,255)) // magenta
1018 #define FlipColor(rgb) (RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb)))
1019
1020 WXHBITMAP wxToolBar::CreateMappedBitmap(WXHINSTANCE WXUNUSED(hInstance), void *info)
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) {
1083 hbmOld = (HBITMAP) SelectObject(hdcMem, hbm);
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
1100 WXHBITMAP wxToolBar::CreateMappedBitmap(WXHINSTANCE hInstance, WXHBITMAP hBitmap)
1101 {
1102 HANDLE hDIB = wxDIB::ConvertFromBitmap((HBITMAP) hBitmap);
1103 if ( !hDIB )
1104 return 0;
1105
1106 WXHBITMAP newBitmap = CreateMappedBitmap(hInstance, GlobalPtr(hDIB));
1107
1108 GlobalFree(hDIB);
1109
1110 return newBitmap;
1111 }
1112
1113 #endif // wxUSE_TOOLBAR
1114