]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/tbarmsw.cpp
a better fix for notebook page not being refreshed after Delete()
[wxWidgets.git] / src / msw / tbarmsw.cpp
... / ...
CommitLineData
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
81class WXDLLEXPORT wxToolBarTool : public wxToolBarToolBase
82{
83public:
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
122IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
123
124BEGIN_EVENT_TABLE(wxToolBar, wxToolBarBase)
125 EVT_PAINT(wxToolBar::OnPaint)
126 EVT_MOUSE_EVENTS(wxToolBar::OnMouseEvent)
127END_EVENT_TABLE()
128#endif
129
130// ============================================================================
131// implementation
132// ============================================================================
133
134// ----------------------------------------------------------------------------
135// wxToolBarTool
136// ----------------------------------------------------------------------------
137
138wxToolBarToolBase *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
151wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
152{
153 return new wxToolBarTool(this, control);
154}
155
156// ----------------------------------------------------------------------------
157// wxToolBar
158// ----------------------------------------------------------------------------
159
160void 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
183bool wxToolBar::Create(wxWindow *parent,
184 wxWindowID id,
185 const wxPoint& pos,
186 const wxSize& size,
187 long style,
188 const wxString& name)
189{
190 if ( !wxWindow::Create(parent, id, pos, size, style, name) )
191 return FALSE;
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
212wxToolBar::~wxToolBar()
213{
214 FreeGlobalObjects();
215}
216
217void 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
227wxSize wxToolBar::GetToolSize() const
228{
229 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
230}
231
232wxToolBarToolBase *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
251wxToolBarToolBase *wxToolBar::AddTool(int id,
252 const wxBitmap& bitmap,
253 const wxBitmap& pushedBitmap,
254 bool toggle,
255 wxCoord xPos,
256 wxCoord yPos,
257 wxObject *clientData,
258 const wxString& helpString1,
259 const wxString& helpString2)
260{
261 // rememeber the position for DoInsertTool()
262 m_xPos = xPos;
263 m_yPos = yPos;
264
265 return wxToolBarBase::AddTool(id, bitmap, pushedBitmap, toggle,
266 xPos, yPos, clientData,
267 helpString1, helpString2);
268}
269
270void 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).
304void 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
429void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool WXUNUSED(enable))
430{
431 DoRedrawTool(tool);
432}
433
434void wxToolBar::DoToggleTool(wxToolBarToolBase *tool, bool WXUNUSED(toggle))
435{
436 DoRedrawTool(tool);
437}
438
439void wxToolBar::DoSetToggle(wxToolBarToolBase * WXUNUSED(tool),
440 bool WXUNUSED(toggle))
441{
442 // nothing to do
443}
444
445void wxToolBar::DoRedrawTool(wxToolBarToolBase *tool)
446{
447 wxClientDC dc(this);
448
449 DrawTool(dc, tool);
450}
451
452void 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
462void wxToolBar::DrawTool(wxDC& dc, wxToolBarToolBase *tool)
463{
464 int state = 0;
465 if (tool->IsEnabled())
466 state |= wxTBSTATE_ENABLED;
467 if (tool->IsToggled())
468 state |= wxTBSTATE_CHECKED;
469 // how can i access the PRESSED state???
470
471 DrawTool(dc, tool, state);
472}
473
474bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos),
475 wxToolBarToolBase *tool)
476{
477 // VZ: didn't test whether it works, but why not...
478 tool->Detach();
479
480 Refresh();
481
482 return TRUE;
483}
484
485bool 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
529bool wxToolBar::Realize()
530{
531 m_currentRowsOrColumns = 0;
532 m_lastX = m_xMargin;
533 m_lastY = m_yMargin;
534 int maxToolWidth = 0;
535 int maxToolHeight = 0;
536 m_maxWidth = 0;
537 m_maxHeight = 0;
538
539 // Find the maximum tool width and height
540 wxToolBarToolsList::Node *node = m_tools.GetFirst();
541 while (node)
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
632bool 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
650void 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
673void 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
691void 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
722void 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
751void 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
883void 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
915WXHBITMAP 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
968bool 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
998bool wxToolBar::FreeDitherBrush(void)
999{
1000 if (m_hbrDither)
1001 DeleteObject((HBRUSH) m_hbrDither);
1002 m_hbrDither = 0;
1003 return TRUE;
1004}
1005
1006typedef struct tagCOLORMAP2
1007{
1008 COLORREF bgrfrom;
1009 COLORREF bgrto;
1010 COLORREF sysColor;
1011} COLORMAP2;
1012
1013// these are the default colors used to map the dib colors
1014// to the current system colors
1015
1016#define BGR_BUTTONTEXT (RGB(000,000,000)) // black
1017#define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey
1018#define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey
1019#define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white
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
1024WXHBITMAP 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
1104WXHBITMAP 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