]> git.saurik.com Git - wxWidgets.git/blob - src/msw/tbarmsw.cpp
ScrollWindow() should use the rect it scrolls as the clipping rect as well
[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& 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 }
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 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 }
149
150 wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
151 {
152 return new wxToolBarTool(this, control);
153 }
154
155 // ----------------------------------------------------------------------------
156 // wxToolBar
157 // ----------------------------------------------------------------------------
158
159 void wxToolBar::Init()
160 {
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;
172
173 m_xPos =
174 m_yPos = -1;
175
176 m_maxWidth = m_maxHeight = 0;
177 m_pressedTool = m_currentTool = -1;
178 m_toolPacking = 1;
179 m_toolSeparation = 5;
180 }
181
182 bool 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;
191
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 }
202
203 // Set it to grey
204 SetBackgroundColour(wxColour(192, 192, 192));
205
206 InitGlobalObjects();
207
208 return TRUE;
209 }
210
211 wxToolBar::~wxToolBar()
212 {
213 FreeGlobalObjects();
214 }
215
216 void wxToolBar::SetToolBitmapSize(const wxSize& size)
217 {
218 m_defaultWidth = size.x;
219 m_defaultHeight = size.y;
220
221 FreeGlobalObjects();
222 InitGlobalObjects();
223 }
224
225 // The button size is bigger than the bitmap size
226 wxSize wxToolBar::GetToolSize() const
227 {
228 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
229 }
230
231 wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
232 {
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 }
243
244 node = node->GetNext();
245 }
246
247 return (wxToolBarToolBase *)NULL;
248 }
249
250 wxToolBarToolBase *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);
267 }
268
269 void wxToolBar::OnPaint(wxPaintEvent& event)
270 {
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--;
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).
303 void wxToolBar::OnMouseEvent(wxMouseEvent& event)
304 {
305 static wxToolBarToolBase *eventCurrentTool = NULL;
306 wxClientDC dc(this);
307
308 if (event.Leaving())
309 {
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;
322 }
323
324 wxCoord x, y;
325 event.GetPosition(&x, &y);
326 wxToolBarToolBase *tool = FindToolForPosition(x, y);
327
328 if (!tool)
329 {
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;
346 }
347
348 if (!event.Dragging() && !event.IsButton())
349 {
350 if (tool->GetId() != m_currentTool)
351 {
352 OnMouseEnter(m_currentTool = tool->GetId());
353 return;
354 }
355 }
356 if (event.Dragging() && tool->IsEnabled())
357 {
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 }
383 }
384 if (event.LeftDown() && tool->IsEnabled())
385 {
386 eventCurrentTool = tool;
387 ::SetCapture((HWND) GetHWND());
388 int state = wxTBSTATE_ENABLED|wxTBSTATE_PRESSED;
389 if (tool->IsToggled())
390 state |= wxTBSTATE_CHECKED;
391 DrawTool(dc, tool, state);
392 }
393 else if (event.LeftUp() && tool->IsEnabled())
394 {
395 if (eventCurrentTool)
396 ::ReleaseCapture();
397 if (eventCurrentTool == tool)
398 {
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 }
419 }
420 eventCurrentTool = NULL;
421 }
422 else if (event.RightDown() && tool->IsEnabled())
423 {
424 OnRightClick(tool->GetId(), x, y);
425 }
426 }
427
428 void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool WXUNUSED(enable))
429 {
430 DoRedrawTool(tool);
431 }
432
433 void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
434 {
435 DoRedrawTool(tool);
436 }
437
438 void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
439 bool WXUNUSED(toggle))
440 {
441 // nothing to do
442 }
443
444 void wxToolBar::DoRedrawTool(wxToolBarToolBase *tool)
445 {
446 wxClientDC dc(this);
447
448 DrawTool(dc, tool);
449 }
450
451 void wxToolBar::DrawTool(wxDC& dc, wxToolBarToolBase *toolBase, int state)
452 {
453 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
454
455 DrawButton(dc.GetHDC(),
456 tool->m_x, tool->m_y,
457 tool->GetWidth(), tool->GetHeight(),
458 tool, state);
459 }
460
461 void 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???
469
470 DrawTool(dc, tool, state);
471 }
472
473 bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos),
474 wxToolBarToolBase *tool)
475 {
476 // VZ: didn't test whether it works, but why not...
477 tool->Detach();
478
479 Refresh();
480
481 return TRUE;
482 }
483
484 bool wxToolBar::DoInsertTool(size_t pos, wxToolBarToolBase *toolBase)
485 {
486 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
487
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;
494 if (tool->CanBeToggled())
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
504
505 tool->m_x = m_xPos;
506 if ( tool->m_x == -1 )
507 tool->m_x = m_xMargin;
508
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() )
516 {
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);
523 }
524
525 return TRUE;
526 }
527
528 bool 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)
541 {
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)
557 {
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 }
572 }
573 else if (tool->GetStyle() == wxTOOL_STYLE_BUTTON)
574 {
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 ++;
602 }
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();
610 }
611
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 }
622
623 m_maxWidth += m_xMargin;
624 m_maxHeight += m_yMargin;
625
626 SetSize(m_maxWidth, m_maxHeight);
627
628 return TRUE;
629 }
630
631 bool wxToolBar::InitGlobalObjects()
632 {
633 GetSysColors();
634 if (!CreateDitherBrush())
635 return FALSE;
636
637 m_hdcMono = (WXHDC) CreateCompatibleDC(NULL);
638 if (!m_hdcMono)
639 return FALSE;
640
641 m_hbmMono = (WXHBITMAP) CreateBitmap((int)GetToolSize().x, (int)GetToolSize().y, 1, 1, NULL);
642 if (!m_hbmMono)
643 return FALSE;
644
645 m_hbmDefault = (WXHBITMAP) SelectObject((HDC) m_hdcMono, (HBITMAP) m_hbmMono);
646 return TRUE;
647 }
648
649 void wxToolBar::FreeGlobalObjects()
650 {
651 FreeDitherBrush();
652
653 if (m_hdcMono) {
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
660 }
661 m_hdcMono = 0;
662
663 if (m_hbmMono)
664 DeleteObject((HBITMAP) m_hbmMono);
665 m_hbmMono = 0;
666 }
667
668 // ----------------------------------------------------------------------------
669 // drawing routines
670 // ----------------------------------------------------------------------------
671
672 void wxToolBar::PatB(WXHDC hdc,int x,int y,int dx,int dy, long rgb)
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
690 void wxToolBar::CreateMask(WXHDC hdc, int xoffset, int yoffset, int dx, int dy)
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);
699 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, hBitmap);
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);
708 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
709 hdcGlyphs, 0, 0, SRCCOPY);
710 // convert this to 1's
711 SetBkColor(hdcGlyphs, m_rgbHilight);
712 // OR in the new 1's
713 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
714 hdcGlyphs, 0, 0, SRCPAINT);
715
716 SelectObject(hdcGlyphs, bitmapOld);
717 DeleteObject(hBitmap);
718 DeleteDC(hdcGlyphs);
719 }
720
721 void wxToolBar::DrawBlankButton(WXHDC hdc, int x, int y, int dx, int dy, int state)
722 {
723 // face color
724 PatB(hdc, x, y, dx, dy, m_rgbFace);
725
726 if (state & wxTBSTATE_PRESSED) {
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);
733 }
734 else {
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);
747 }
748 }
749
750 void wxToolBar::DrawButton(WXHDC hdc, int x, int y, int dx, int dy,
751 wxToolBarToolBase *toolBase, int state)
752 {
753 wxToolBarTool *tool = (wxToolBarTool *)toolBase;
754
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;
790 if (tool->GetBitmap2().Ok())
791 bitmapOld = GetHbitmapOf(tool->GetBitmap2());
792 else
793 bitmapOld = GetHbitmapOf(tool->GetBitmap1());
794 #else
795 HBITMAP bitmapOld = GetHbitmapOf(tool->GetBitmap1());
796 #endif
797
798 bitmapOld = (HBITMAP)SelectObject(hdcGlyphs, bitmapOld);
799
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;
803 xCenterOffset = (dxFace - (int)GetToolBitmapSize().x)/2;
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
814 BitBlt((HDC) hdc, x+xCenterOffset, y + yOffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
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) {
829 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
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) {
842 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
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
858 hbrOld = (HBRUSH) SelectObject((HDC) hdc, (HBRUSH) m_hbrDither);
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
878 // ----------------------------------------------------------------------------
879 // drawing helpers
880 // ----------------------------------------------------------------------------
881
882 void wxToolBar::GetSysColors()
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
914 WXHBITMAP wxToolBar::CreateDitherBitmap()
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
967 bool wxToolBar::CreateDitherBrush()
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
997 bool wxToolBar::FreeDitherBrush(void)
998 {
999 if (m_hbrDither)
1000 DeleteObject((HBRUSH) m_hbrDither);
1001 m_hbrDither = 0;
1002 return TRUE;
1003 }
1004
1005 typedef 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
1019 #define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue
1020 #define BGR_BACKGROUND (RGB(255,000,255)) // magenta
1021 #define FlipColor(rgb) (RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb)))
1022
1023 WXHBITMAP wxToolBar::CreateMappedBitmap(WXHINSTANCE WXUNUSED(hInstance), void *info)
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) {
1086 hbmOld = (HBITMAP) SelectObject(hdcMem, hbm);
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
1103 WXHBITMAP wxToolBar::CreateMappedBitmap(WXHINSTANCE hInstance, WXHBITMAP hBitmap)
1104 {
1105 HANDLE hDIB = wxBitmapToDIB((HBITMAP) hBitmap, 0);
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