]> git.saurik.com Git - wxWidgets.git/blob - src/msw/tbarmsw.cpp
mention that wxBase builds with BC++ now
[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 and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "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(__WIN32__) && !wxUSE_IMAGE_LOADING_IN_MSW
38 #error wxToolBar needs wxUSE_IMAGE_LOADING_IN_MSW under Win16
39 #endif
40
41 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__)
42 #include "malloc.h"
43 #endif
44
45 #if !defined(__MWERKS__) && !defined(__SALFORDC__)
46 #include <memory.h>
47 #endif
48
49 #include <stdlib.h>
50
51 #include "wx/msw/tbarmsw.h"
52 #include "wx/event.h"
53 #include "wx/app.h"
54 #include "wx/bitmap.h"
55 #include "wx/msw/private.h"
56 #include "wx/msw/dib.h"
57
58 // ----------------------------------------------------------------------------
59 // constants
60 // ----------------------------------------------------------------------------
61
62 #define DEFAULTBITMAPX 16
63 #define DEFAULTBITMAPY 15
64 #define DEFAULTBUTTONX 24
65 #define DEFAULTBUTTONY 22
66 #define DEFAULTBARHEIGHT 27
67
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
76
77 // ----------------------------------------------------------------------------
78 // private classes
79 // ----------------------------------------------------------------------------
80
81 class WXDLLEXPORT wxToolBarTool : public wxToolBarToolBase
82 {
83 public:
84 wxToolBarTool(wxToolBar *tbar,
85 int id,
86 const wxBitmap& bmpNormal,
87 const wxBitmap& bmpDisabled,
88 bool toggle,
89 wxObject *clientData,
90 const wxString& shortHelp,
91 const wxString& longHelp)
92 : wxToolBarToolBase(tbar, id, bmpNormal, bmpDisabled, toggle,
93 clientData, shortHelp, longHelp)
94 {
95 }
96
97 wxToolBarTool(wxToolBar *tbar, wxControl *control)
98 : wxToolBarToolBase(tbar, control)
99 {
100 }
101
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
122 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
123
124 BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
125 EVT_PAINT(wxToolBar::OnPaint)
126 EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent)
127 END_EVENT_TABLE()
128 #endif
129
130 // ============================================================================
131 // implementation
132 // ============================================================================
133
134 // ----------------------------------------------------------------------------
135 // wxToolBarTool
136 // ----------------------------------------------------------------------------
137
138 wxToolBarToolBase *wxToolBar::CreateTool(int id,
139 const wxString& label,
140 const wxBitmap& bmpNormal,
141 const wxBitmap& bmpDisabled,
142 wxItemKind kind,
143 wxObject *clientData,
144 const wxString& shortHelp,
145 const wxString& longHelp)
146 {
147 return new wxToolBarTool(this, id, label, bmpNormal, bmpDisabled, kind,
148 clientData, shortHelp, longHelp);
149 }
150
151 wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
152 {
153 return new wxToolBarTool(this, control);
154 }
155
156 // ----------------------------------------------------------------------------
157 // wxToolBar
158 // ----------------------------------------------------------------------------
159
160 void wxToolBar::Init()
161 {
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;
173
174 m_xPos =
175 m_yPos = -1;
176
177 m_maxWidth = m_maxHeight = 0;
178 m_pressedTool = m_currentTool = -1;
179 m_toolPacking = 1;
180 m_toolSeparation = 5;
181 }
182
183 bool 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;
192
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 }
203
204 // Set it to grey
205 SetBackgroundColour(wxColour(192, 192, 192));
206
207 InitGlobalObjects();
208
209 return TRUE;
210 }
211
212 wxToolBar::~wxToolBar()
213 {
214 FreeGlobalObjects();
215 }
216
217 void wxToolBar::SetToolBitmapSize(const wxSize& size)
218 {
219 m_defaultWidth = size.x;
220 m_defaultHeight = size.y;
221
222 FreeGlobalObjects();
223 InitGlobalObjects();
224 }
225
226 // The button size is bigger than the bitmap size
227 wxSize wxToolBar::GetToolSize() const
228 {
229 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
230 }
231
232 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
233 {
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 }
244
245 node = node->GetNext();
246 }
247
248 return (wxToolBarToolBase *)NULL;
249 }
250
251 wxToolBarToolBase *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);
268 }
269
270 void wxToolBar::OnPaint(wxPaintEvent& event)
271 {
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--;
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).
304 void wxToolBar::OnMouseEvent(wxMouseEvent& event)
305 {
306 static wxToolBarToolBase *eventCurrentTool = NULL;
307 wxClientDC dc(this);
308
309 if (event.Leaving())
310 {
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;
323 }
324
325 wxCoord x, y;
326 event.GetPosition(&x, &y);
327 wxToolBarToolBase *tool = FindToolForPosition(x, y);
328
329 if (!tool)
330 {
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;
347 }
348
349 if (!event.Dragging() && !event.IsButton())
350 {
351 if (tool->GetId() != m_currentTool)
352 {
353 OnMouseEnter(m_currentTool = tool->GetId());
354 return;
355 }
356 }
357 if (event.Dragging() && tool->IsEnabled())
358 {
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 }
384 }
385 if (event.LeftDown() && tool->IsEnabled())
386 {
387 eventCurrentTool = tool;
388 ::SetCapture((HWND) GetHWND());
389 int state = wxTBSTATE_ENABLED|wxTBSTATE_PRESSED;
390 if (tool->IsToggled())
391 state |= wxTBSTATE_CHECKED;
392 DrawTool(dc, tool, state);
393 }
394 else if (event.LeftUp() && tool->IsEnabled())
395 {
396 if (eventCurrentTool)
397 ::ReleaseCapture();
398 if (eventCurrentTool == tool)
399 {
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 }
420 }
421 eventCurrentTool = NULL;
422 }
423 else if (event.RightDown() && tool->IsEnabled())
424 {
425 OnRightClick(tool->GetId(), x, y);
426 }
427 }
428
429 void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool WXUNUSED(enable))
430 {
431 DoRedrawTool(tool);
432 }
433
434 void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
435 {
436 DoRedrawTool(tool);
437 }
438
439 void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
440 bool WXUNUSED(toggle))
441 {
442 // nothing to do
443 }
444
445 void wxToolBar::DoRedrawTool(wxToolBarToolBase *tool)
446 {
447 wxClientDC dc(this);
448
449 DrawTool(dc, tool);
450 }
451
452 void wxToolBar::DrawTool(wxDC& dc, wxToolBarToolBase *toolBase, int state)
453 {
454 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
455
456 DrawButton(dc.GetHDC(),
457 tool->m_x, tool->m_y,
458 tool->GetWidth(), tool->GetHeight(),
459 tool, state);
460 }
461
462 void 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???
470
471 DrawTool(dc, tool, state);
472 }
473
474 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos),
475 wxToolBarToolBase *tool)
476 {
477 // VZ: didn't test whether it works, but why not...
478 tool->Detach();
479
480 Refresh();
481
482 return TRUE;
483 }
484
485 bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
486 {
487 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
488
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__)
494 wxBitmap bmpDisabled;
495 if (tool->CanBeToggled())
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
505
506 tool->m_x = m_xPos;
507 if ( tool->m_x == -1 )
508 tool->m_x = m_xMargin;
509
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() )
517 {
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);
524 }
525
526 return TRUE;
527 }
528
529 bool 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)
542 {
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)
558 {
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 }
573 }
574 else if (tool->GetStyle() == wxTOOL_STYLE_BUTTON)
575 {
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 ++;
603 }
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();
611 }
612
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 }
623
624 m_maxWidth += m_xMargin;
625 m_maxHeight += m_yMargin;
626
627 SetSize(m_maxWidth, m_maxHeight);
628
629 return TRUE;
630 }
631
632 bool wxToolBar::InitGlobalObjects()
633 {
634 GetSysColors();
635 if (!CreateDitherBrush())
636 return FALSE;
637
638 m_hdcMono = (WXHDC) CreateCompatibleDC(NULL);
639 if (!m_hdcMono)
640 return FALSE;
641
642 m_hbmMono = (WXHBITMAP) CreateBitmap((int)GetToolSize().x, (int)GetToolSize().y, 1, 1, NULL);
643 if (!m_hbmMono)
644 return FALSE;
645
646 m_hbmDefault = (WXHBITMAP) SelectObject((HDC) m_hdcMono, (HBITMAP) m_hbmMono);
647 return TRUE;
648 }
649
650 void wxToolBar::FreeGlobalObjects()
651 {
652 FreeDitherBrush();
653
654 if (m_hdcMono) {
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
661 }
662 m_hdcMono = 0;
663
664 if (m_hbmMono)
665 DeleteObject((HBITMAP) m_hbmMono);
666 m_hbmMono = 0;
667 }
668
669 // ----------------------------------------------------------------------------
670 // drawing routines
671 // ----------------------------------------------------------------------------
672
673 void wxToolBar::PatB(WXHDC hdc,int x,int y,int dx,int dy, long rgb)
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
691 void wxToolBar::CreateMask(WXHDC hdc, int xoffset, int yoffset, int dx, int dy)
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);
700 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, hBitmap);
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);
709 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
710 hdcGlyphs, 0, 0, SRCCOPY);
711 // convert this to 1's
712 SetBkColor(hdcGlyphs, m_rgbHilight);
713 // OR in the new 1's
714 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
715 hdcGlyphs, 0, 0, SRCPAINT);
716
717 SelectObject(hdcGlyphs, bitmapOld);
718 DeleteObject(hBitmap);
719 DeleteDC(hdcGlyphs);
720 }
721
722 void wxToolBar::DrawBlankButton(WXHDC hdc, int x, int y, int dx, int dy, int state)
723 {
724 // face color
725 PatB(hdc, x, y, dx, dy, m_rgbFace);
726
727 if (state & wxTBSTATE_PRESSED) {
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);
734 }
735 else {
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);
748 }
749 }
750
751 void wxToolBar::DrawButton(WXHDC hdc, int x, int y, int dx, int dy,
752 wxToolBarToolBase *toolBase, int state)
753 {
754 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
755
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
788 // Using bmpDisabled can cause problems (don't know why!)
789 #if !defined(__WIN32__) && !defined(__WIN386__)
790 HBITMAP bitmapOld;
791 if (tool->GetBitmap2().Ok())
792 bitmapOld = GetHbitmapOf(tool->GetBitmap2());
793 else
794 bitmapOld = GetHbitmapOf(tool->GetBitmap1());
795 #else
796 HBITMAP bitmapOld = GetHbitmapOf(tool->GetBitmap1());
797 #endif
798
799 bitmapOld = (HBITMAP)SelectObject(hdcGlyphs, bitmapOld);
800
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;
804 xCenterOffset = (dxFace - (int)GetToolBitmapSize().x)/2;
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
815 BitBlt((HDC) hdc, x+xCenterOffset, y + yOffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
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) {
830 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
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) {
843 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
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
859 hbrOld = (HBRUSH) SelectObject((HDC) hdc, (HBRUSH) m_hbrDither);
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
879 // ----------------------------------------------------------------------------
880 // drawing helpers
881 // ----------------------------------------------------------------------------
882
883 void wxToolBar::GetSysColors()
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
915 WXHBITMAP wxToolBar::CreateDitherBitmap()
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
968 bool wxToolBar::CreateDitherBrush()
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
998 bool wxToolBar::FreeDitherBrush(void)
999 {
1000 if (m_hbrDither)
1001 DeleteObject((HBRUSH) m_hbrDither);
1002 m_hbrDither = 0;
1003 return TRUE;
1004 }
1005
1006 typedef 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
1020 #define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue
1021 #define BGR_BACKGROUND (RGB(255,000,255)) // magenta
1022 #define FlipColor(rgb) (RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb)))
1023
1024 WXHBITMAP wxToolBar::CreateMappedBitmap(WXHINSTANCE WXUNUSED(hInstance), void *info)
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) {
1087 hbmOld = (HBITMAP) SelectObject(hdcMem, hbm);
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
1104 WXHBITMAP wxToolBar::CreateMappedBitmap(WXHINSTANCE hInstance, WXHBITMAP hBitmap)
1105 {
1106 HANDLE hDIB = wxBitmapToDIB((HBITMAP) hBitmap, 0);
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