]> git.saurik.com Git - wxWidgets.git/blame - src/msw/tbarmsw.cpp
bug in FindItemForId() fixed (?)
[wxWidgets.git] / src / msw / tbarmsw.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: tbarmsw.cpp
3// Purpose: wxToolBarMSW
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "tbarmsw.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
2432b92d 24#include "wx/wx.h"
2bda0e17
KB
25#endif
26
47d67540 27#if wxUSE_BUTTONBAR && wxUSE_TOOLBAR
2bda0e17 28
ce3ed50d 29#if !defined(__GNUWIN32__) && !defined(__SALFORDC__)
2bda0e17
KB
30#include "malloc.h"
31#endif
32
ce3ed50d 33#if !defined(__MWERKS__) && !defined(__SALFORDC__)
2bda0e17 34#include <memory.h>
17dff81c 35#endif
ce3ed50d 36
2bda0e17
KB
37#include <stdlib.h>
38
39#include "wx/tbarmsw.h"
2432b92d 40#include "wx/event.h"
2bda0e17 41#include "wx/app.h"
2432b92d 42#include "wx/bitmap.h"
2bda0e17
KB
43#include "wx/msw/private.h"
44#include "wx/msw/dib.h"
45
81d66cf3
JS
46#define DEFAULTBITMAPX 16
47#define DEFAULTBITMAPY 15
48#define DEFAULTBUTTONX 24
49#define DEFAULTBUTTONY 22
50#define DEFAULTBARHEIGHT 27
51
2bda0e17
KB
52/////// Non-Windows 95 implementation
53
f97c9854 54#if !wxUSE_IMAGE_LOADING_IN_MSW
47d67540 55#error If wxUSE_IMAGE_LOADING_IN_MSW is set to 0, then wxUSE_BUTTONBAR must be set to 0 too.
2bda0e17
KB
56#endif
57
58#if !USE_SHARED_LIBRARY
59IMPLEMENT_DYNAMIC_CLASS(wxToolBarMSW, wxToolBarBase)
60
61BEGIN_EVENT_TABLE(wxToolBarMSW, wxToolBarBase)
62 EVT_SIZE(wxToolBarMSW::OnSize)
63 EVT_PAINT(wxToolBarMSW::OnPaint)
64 EVT_MOUSE_EVENTS(wxToolBarMSW::OnMouseEvent)
65END_EVENT_TABLE()
66#endif
67
68wxToolBarMSW::wxToolBarMSW(void)
69{
70 m_hbrDither = 0;
71 m_rgbFace = 0;
72 m_rgbShadow = 0;
73 m_rgbHilight = 0;
74 m_rgbFrame = 0;
75 m_hdcMono = 0;
76 m_hbmMono = 0;
77 m_hbmDefault = 0;
78 m_defaultWidth = DEFAULTBITMAPX;
79 m_defaultHeight = DEFAULTBITMAPY;
80}
81
debe6624 82bool wxToolBarMSW::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
81d66cf3 83 long style, const wxString& name)
2bda0e17
KB
84{
85 if ( ! wxWindow::Create(parent, id, pos, size, style, name) )
86 return FALSE;
87
81d66cf3 88 if ( style & wxTB_HORIZONTAL )
2bda0e17
KB
89 { m_lastX = 3; m_lastY = 7; }
90 else
91 { m_lastX = 7; m_lastY = 3; }
92 m_maxWidth = m_maxHeight = 0;
93 m_pressedTool = m_currentTool = -1;
94 m_xMargin = 0;
95 m_yMargin = 0;
96 m_toolPacking = 1;
97 m_toolSeparation = 5;
98
99 // Set it to grey
100 SetBackgroundColour(wxColour(192, 192, 192));
101
102 m_hbrDither = 0;
103 m_rgbFace = 0;
104 m_rgbShadow = 0;
105 m_rgbHilight = 0;
106 m_rgbFrame = 0;
107 m_hdcMono = 0;
108 m_hbmMono = 0;
109 m_hbmDefault = 0;
110 m_defaultWidth = DEFAULTBITMAPX;
111 m_defaultHeight = DEFAULTBITMAPY;
112
113 InitGlobalObjects();
114
115 return TRUE;
116}
117
118wxToolBarMSW::~wxToolBarMSW(void)
119{
120 FreeGlobalObjects();
121}
122
81d66cf3 123void wxToolBarMSW::SetToolBitmapSize(const wxSize& size)
2bda0e17
KB
124{
125 m_defaultWidth = size.x; m_defaultHeight = size.y;
126 FreeGlobalObjects();
127 InitGlobalObjects();
128}
129
130// The button size is bigger than the bitmap size
81d66cf3 131wxSize wxToolBarMSW::GetToolSize(void) const
2bda0e17
KB
132{
133 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
134}
135
136void wxToolBarMSW::OnPaint(wxPaintEvent& event)
137{
138 wxPaintDC dc(this);
139
140 static int wxOnPaintCount = 0;
141
142 // Prevent reentry of OnPaint which would cause
143 // wxMemoryDC errors.
144 if (wxOnPaintCount > 0)
145 return;
146 wxOnPaintCount ++;
147
148 wxNode *node = m_tools.First();
149 while (node)
150 {
151 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
152 if (tool->m_toolStyle != wxTOOL_STYLE_SEPARATOR)
153 {
154 int state = wxTBSTATE_ENABLED;
155 if (!tool->m_enabled)
156 state = 0;
157 if (tool->m_isToggle && tool->m_toggleState)
158 state |= wxTBSTATE_CHECKED;
159 DrawTool(dc, tool, state);
160 }
161 node = node->Next();
162 }
163 wxOnPaintCount --;
164}
165
166void wxToolBarMSW::OnSize(wxSizeEvent& event)
167{
168 wxToolBarBase::OnSize(event);
169}
170
171// If a Button is disabled, then NO function (besides leaving
172// or entering) should be carried out. Therefore the additions
173// of 'enabled' testing (Stefan Hammes).
174void wxToolBarMSW::OnMouseEvent(wxMouseEvent& event)
175{
176 static wxToolBarTool *eventCurrentTool = NULL;
177 wxClientDC dc(this);
178
179 if (event.Leaving())
180 {
181 m_currentTool = -1;
182 if (eventCurrentTool && eventCurrentTool->m_enabled)
183 {
184 ::ReleaseCapture();
185 int state = wxTBSTATE_ENABLED;
186 if (eventCurrentTool->m_toggleState)
187 state |= wxTBSTATE_CHECKED;
188 DrawTool(dc, eventCurrentTool, state);
189 eventCurrentTool = NULL;
190 }
191 OnMouseEnter(-1);
192 return;
193 }
194
195 long x, y;
196 event.Position(&x, &y);
197 wxToolBarTool *tool = FindToolForPosition(x, y);
198
199 if (!tool)
200 {
201 if (eventCurrentTool && eventCurrentTool->m_enabled)
202 {
203 ::ReleaseCapture();
204
205 int state = wxTBSTATE_ENABLED;
206 if (eventCurrentTool->m_toggleState)
207 state |= wxTBSTATE_CHECKED;
208 DrawTool(dc, eventCurrentTool, state);
209 eventCurrentTool = NULL;
210 }
211 if (m_currentTool > -1)
212 {
213 m_currentTool = -1;
214 OnMouseEnter(-1);
215 }
216 return;
217 }
218
219 if (!event.Dragging() && !event.IsButton())
220 {
221 if (tool->m_index != m_currentTool)
222 {
223 OnMouseEnter(tool->m_index);
224 m_currentTool = tool->m_index;
225 return;
226 }
227 }
228 if (event.Dragging() && tool->m_enabled)
229 {
230 if (eventCurrentTool)
231 {
232 // Might have dragged outside tool
233 if (eventCurrentTool != tool)
234 {
235 int state = wxTBSTATE_ENABLED;
236 if (tool->m_toggleState)
237 state |= wxTBSTATE_CHECKED;
238 DrawTool(dc, tool, state);
239 eventCurrentTool = NULL;
240 return;
241 }
242 }
243 else
244 {
245 if (tool && event.LeftIsDown() && tool->m_enabled)
246 {
247 eventCurrentTool = tool;
248 ::SetCapture((HWND) GetHWND());
249 int state = wxTBSTATE_ENABLED|wxTBSTATE_PRESSED;
250 if (tool->m_toggleState)
251 state |= wxTBSTATE_CHECKED;
252 DrawTool(dc, tool, state);
253 }
254 }
255 }
256 if (event.LeftDown() && tool->m_enabled)
257 {
258 eventCurrentTool = tool;
259 ::SetCapture((HWND) GetHWND());
260 int state = wxTBSTATE_ENABLED|wxTBSTATE_PRESSED;
261 if (tool->m_toggleState)
262 state |= wxTBSTATE_CHECKED;
263 DrawTool(dc, tool, state);
264 }
265 else if (event.LeftUp() && tool->m_enabled)
266 {
267 if (eventCurrentTool)
268 ::ReleaseCapture();
269 if (eventCurrentTool == tool)
270 {
271 if (tool->m_isToggle)
272 {
273 tool->m_toggleState = !tool->m_toggleState;
274 if (!OnLeftClick(tool->m_index, tool->m_toggleState))
275 {
276 tool->m_toggleState = !tool->m_toggleState;
277 }
278 int state = wxTBSTATE_ENABLED;
279 if (tool->m_toggleState)
280 state |= wxTBSTATE_CHECKED;
281 DrawTool(dc, tool, state);
282 }
283 else
284 {
285 int state = wxTBSTATE_ENABLED;
286 if (tool->m_toggleState)
287 state |= wxTBSTATE_CHECKED;
288 DrawTool(dc, tool, state);
289 OnLeftClick(tool->m_index, tool->m_toggleState);
290 }
291 }
292 eventCurrentTool = NULL;
293 }
294 else if (event.RightDown() && tool->m_enabled)
295 {
296 OnRightClick(tool->m_index, x, y);
297 }
298}
299
300// This function enables/disables a toolbar tool and redraws it.
301// If that would not be done, the enabling/disabling wouldn't be
302// visible on the screen.
debe6624 303void wxToolBarMSW::EnableTool(int toolIndex, bool enable)
2bda0e17
KB
304{
305 wxNode *node = m_tools.Find((long)toolIndex);
306 if (node)
307 {
308 wxClientDC dc(this);
309
310 // at first do the enabling/disabling in the base class
311 wxToolBarBase::EnableTool(toolIndex,enable);
312 // then calculate the state of the tool and draw it
313 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
314 int state = 0;
315 if(tool->m_toggleState) state |= wxTBSTATE_CHECKED;
316 if(tool->m_enabled) state |= wxTBSTATE_ENABLED;
317 // how can i access the PRESSED state???
318 DrawTool(dc, tool,state);
319 }
320}
321
322void wxToolBarMSW::DrawTool(wxDC& dc, wxToolBarTool *tool, int state)
323{
324 DrawButton(dc.GetHDC(), (int)tool->m_x, (int)tool->m_y, (int)tool->GetWidth(), (int)tool->GetHeight(), tool, state);
325}
326
327void wxToolBarMSW::DrawTool(wxDC& dc, wxMemoryDC& , wxToolBarTool *tool)
328{
329 int state = wxTBSTATE_ENABLED;
330 if (!tool->m_enabled)
331 state = 0;
332 if (tool->m_toggleState)
333 state |= wxTBSTATE_CHECKED;
334 DrawTool(dc, tool, state);
335}
336
337// If pushedBitmap is NULL, a reversed version of bitmap is
338// created and used as the pushed/toggled image.
339// If toggle is TRUE, the button toggles between the two states.
debe6624
JS
340wxToolBarTool *wxToolBarMSW::AddTool(int index, const wxBitmap& bitmap, const wxBitmap& pushedBitmap,
341 bool toggle, long xPos, long yPos, wxObject *clientData, const wxString& helpString1, const wxString& helpString2)
2bda0e17
KB
342{
343 // Using bitmap2 can cause problems (don't know why!)
344
345 // TODO: use the mapping code from wxToolBar95 to get it right in this class
346#if !defined(__WIN32__) && !defined(__WIN386__)
1e6d9499 347 wxBitmap bitmap2;
2bda0e17
KB
348 if (toggle)
349 {
1e6d9499 350 bitmap2.SetHBITMAP( (WXHBITMAP) CreateMappedBitmap(wxGetInstance(), (HBITMAP) ((wxBitmap& )bitmap).GetHBITMAP()));
2bda0e17
KB
351 }
352
1e6d9499 353 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, bitmap2, toggle, xPos, yPos, helpString1, helpString2);
2bda0e17 354#else
c0ed460c 355 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, wxNullBitmap, toggle, xPos, yPos, helpString1, helpString2);
2bda0e17
KB
356#endif
357
358 tool->m_clientData = clientData;
359
360 if (xPos > -1)
361 tool->m_x = xPos;
362 else
363 tool->m_x = m_xMargin;
364
365 if (yPos > -1)
366 tool->m_y = yPos;
367 else
368 tool->m_y = m_yMargin;
369
370 tool->m_deleteSecondBitmap = TRUE;
81d66cf3 371 tool->SetSize(GetToolSize().x, GetToolSize().y);
2bda0e17
KB
372
373 // Calculate reasonable max size in case Layout() not called
374 if ((tool->m_x + bitmap.GetWidth() + m_xMargin) > m_maxWidth)
375 m_maxWidth = (tool->m_x + tool->GetWidth() + m_xMargin);
376
377 if ((tool->m_y + bitmap.GetHeight() + m_yMargin) > m_maxHeight)
378 m_maxHeight = (tool->m_y + tool->GetHeight() + m_yMargin);
379
380 m_tools.Append((long)index, tool);
381 return tool;
382}
383
81d66cf3
JS
384void wxToolBarMSW::Layout(void)
385{
386 m_currentRowsOrColumns = 0;
387 m_lastX = m_xMargin;
388 m_lastY = m_yMargin;
389 int maxToolWidth = 0;
390 int maxToolHeight = 0;
391 m_maxWidth = 0;
392 m_maxHeight = 0;
393
394 // Find the maximum tool width and height
395 wxNode *node = m_tools.First();
396 while (node)
397 {
398 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
399 if (tool->GetWidth() > maxToolWidth)
400 maxToolWidth = (int)tool->GetWidth();
401 if (tool->GetHeight() > maxToolHeight)
402 maxToolHeight = (int)tool->GetHeight();
403 node = node->Next();
404 }
405
406 int separatorSize = m_toolSeparation;
407
408 node = m_tools.First();
409 while (node)
410 {
411 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
412 if (tool->m_toolStyle == wxTOOL_STYLE_SEPARATOR)
413 {
414 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
415 {
416 if (m_currentRowsOrColumns >= m_maxCols)
417 m_lastY += separatorSize;
418 else
419 m_lastX += separatorSize;
420 }
421 else
422 {
423 if (m_currentRowsOrColumns >= m_maxRows)
424 m_lastX += separatorSize;
425 else
426 m_lastY += separatorSize;
427 }
428 }
429 else if (tool->m_toolStyle == wxTOOL_STYLE_BUTTON)
430 {
431 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
432 {
433 if (m_currentRowsOrColumns >= m_maxCols)
434 {
435 m_currentRowsOrColumns = 0;
436 m_lastX = m_xMargin;
437 m_lastY += maxToolHeight + m_toolPacking;
438 }
439 tool->m_x = (long) (m_lastX + (maxToolWidth - tool->GetWidth())/2.0);
440 tool->m_y = (long) (m_lastY + (maxToolHeight - tool->GetHeight())/2.0);
441
442 m_lastX += maxToolWidth + m_toolPacking;
443 }
444 else
445 {
446 if (m_currentRowsOrColumns >= m_maxRows)
447 {
448 m_currentRowsOrColumns = 0;
449 m_lastX += (maxToolWidth + m_toolPacking);
450 m_lastY = m_yMargin;
451 }
452 tool->m_x = (long) (m_lastX + (maxToolWidth - tool->GetWidth())/2.0);
453 tool->m_y = (long) (m_lastY + (maxToolHeight - tool->GetHeight())/2.0);
454
455 m_lastY += maxToolHeight + m_toolPacking;
456 }
457 m_currentRowsOrColumns ++;
458 }
459
460 if (m_lastX > m_maxWidth)
461 m_maxWidth = m_lastX;
462 if (m_lastY > m_maxHeight)
463 m_maxHeight = m_lastY;
464
465 node = node->Next();
466 }
467 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
2a47d3c1 468 {
81d66cf3 469 m_maxWidth += maxToolWidth;
2a47d3c1
JS
470 m_maxHeight += maxToolHeight;
471 }
81d66cf3 472 else
2a47d3c1
JS
473 {
474 m_maxWidth += maxToolWidth;
81d66cf3 475 m_maxHeight += maxToolHeight;
2a47d3c1 476 }
81d66cf3
JS
477
478 m_maxWidth += m_xMargin;
479 m_maxHeight += m_yMargin;
2a47d3c1
JS
480
481 SetSize(m_maxWidth, m_maxHeight);
81d66cf3
JS
482}
483
484
2bda0e17
KB
485bool wxToolBarMSW::InitGlobalObjects(void)
486{
487 GetSysColors();
488 if (!CreateDitherBrush())
489 return FALSE;
490
491 m_hdcMono = (WXHDC) CreateCompatibleDC(NULL);
492 if (!m_hdcMono)
493 return FALSE;
494
81d66cf3 495 m_hbmMono = (WXHBITMAP) CreateBitmap((int)GetToolSize().x, (int)GetToolSize().y, 1, 1, NULL);
2bda0e17
KB
496 if (!m_hbmMono)
497 return FALSE;
498
499 m_hbmDefault = (WXHBITMAP) SelectObject((HDC) m_hdcMono, (HBITMAP) m_hbmMono);
500 return TRUE;
501}
502
503void wxToolBarMSW::FreeGlobalObjects(void)
504{
505 FreeDitherBrush();
506
507 if (m_hdcMono) {
508 if (m_hbmDefault)
509 {
510 SelectObject((HDC) m_hdcMono, (HBITMAP) m_hbmDefault);
511 m_hbmDefault = 0;
512 }
513 DeleteDC((HDC) m_hdcMono); // toast the DCs
514 }
515 m_hdcMono = 0;
516
517 if (m_hbmMono)
518 DeleteObject((HBITMAP) m_hbmMono);
519 m_hbmMono = 0;
520}
521
522
523void wxToolBarMSW::PatB(WXHDC hdc,int x,int y,int dx,int dy, long rgb)
524{
525 RECT rc;
526
527 rc.left = x;
528 rc.top = y;
529 rc.right = x + dx;
530 rc.bottom = y + dy;
531
532 SetBkColor((HDC) hdc,rgb);
533 ExtTextOut((HDC) hdc,0,0,ETO_OPAQUE,&rc,NULL,0,NULL);
534}
535
536
537// create a mono bitmap mask:
538// 1's where color == COLOR_BTNFACE || COLOR_HILIGHT
539// 0's everywhere else
540
541void wxToolBarMSW::CreateMask(WXHDC hdc, int xoffset, int yoffset, int dx, int dy)
542{
543 HDC globalDC = ::GetDC(NULL);
544 HDC hdcGlyphs = CreateCompatibleDC((HDC) globalDC);
545 ReleaseDC(NULL, (HDC) globalDC);
546
547 // krj - create a new bitmap and copy the image from hdc.
548 //HBITMAP bitmapOld = SelectObject(hdcGlyphs, hBitmap);
549 HBITMAP hBitmap = CreateCompatibleBitmap((HDC) hdc, dx, dy);
c4e7c2aa 550 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, hBitmap);
2bda0e17
KB
551 BitBlt(hdcGlyphs, 0,0, dx, dy, (HDC) hdc, 0, 0, SRCCOPY);
552
553 // initalize whole area with 1's
554 PatBlt((HDC) m_hdcMono, 0, 0, dx, dy, WHITENESS);
555
556 // create mask based on color bitmap
557 // convert this to 1's
558 SetBkColor(hdcGlyphs, m_rgbFace);
81d66cf3 559 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
2bda0e17
KB
560 hdcGlyphs, 0, 0, SRCCOPY);
561 // convert this to 1's
562 SetBkColor(hdcGlyphs, m_rgbHilight);
563 // OR in the new 1's
81d66cf3 564 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
2bda0e17
KB
565 hdcGlyphs, 0, 0, SRCPAINT);
566
567 SelectObject(hdcGlyphs, bitmapOld);
568 DeleteObject(hBitmap);
569 DeleteDC(hdcGlyphs);
570}
571
572void wxToolBarMSW::DrawBlankButton(WXHDC hdc, int x, int y, int dx, int dy, int state)
573{
574 // face color
575 PatB(hdc, x, y, dx, dy, m_rgbFace);
576
577 if (state & wxTBSTATE_PRESSED) {
578 PatB(hdc, x + 1, y, dx - 2, 1, m_rgbFrame);
579 PatB(hdc, x + 1, y + dy - 1, dx - 2, 1, m_rgbFrame);
580 PatB(hdc, x, y + 1, 1, dy - 2, m_rgbFrame);
581 PatB(hdc, x + dx - 1, y +1, 1, dy - 2, m_rgbFrame);
582 PatB(hdc, x + 1, y + 1, 1, dy-2, m_rgbShadow);
583 PatB(hdc, x + 1, y + 1, dx-2, 1, m_rgbShadow);
584 }
585 else {
586 PatB(hdc, x + 1, y, dx - 2, 1, m_rgbFrame);
587 PatB(hdc, x + 1, y + dy - 1, dx - 2, 1, m_rgbFrame);
588 PatB(hdc, x, y + 1, 1, dy - 2, m_rgbFrame);
589 PatB(hdc, x + dx - 1, y + 1, 1, dy - 2, m_rgbFrame);
590 dx -= 2;
591 dy -= 2;
592 PatB(hdc, x + 1, y + 1, 1, dy - 1, m_rgbHilight);
593 PatB(hdc, x + 1, y + 1, dx - 1, 1, m_rgbHilight);
594 PatB(hdc, x + dx, y + 1, 1, dy, m_rgbShadow);
595 PatB(hdc, x + 1, y + dy, dx, 1, m_rgbShadow);
596 PatB(hdc, x + dx - 1, y + 2, 1, dy - 2, m_rgbShadow);
597 PatB(hdc, x + 2, y + dy - 1, dx - 2, 1, m_rgbShadow);
598 }
599}
600
601void wxToolBarMSW::DrawButton(WXHDC hdc, int x, int y, int dx, int dy, wxToolBarTool *tool, int state)
602{
603 int yOffset;
604 HBRUSH hbrOld, hbr;
605 BOOL bMaskCreated = FALSE;
606 int xButton = 0; // assume button is down
607 int dxFace, dyFace;
608 int xCenterOffset;
609
610 dxFace = dx;
611 dyFace = dy;
612
613// HBITMAP hBitmap = (HBITMAP) tool->m_bitmap1.GetHBITMAP();
614 HDC globalDC = ::GetDC(NULL);
615 HDC hdcGlyphs = CreateCompatibleDC(globalDC);
616 ReleaseDC(NULL, globalDC);
617
618 // get the proper button look - up or down.
619 if (!(state & (wxTBSTATE_PRESSED | wxTBSTATE_CHECKED))) {
620 xButton = dx; // use 'up' version of button
621 dxFace -= 2;
622 dyFace -= 2; // extents to ignore button highlight
623 }
624
625 DrawBlankButton(hdc, x, y, dx, dy, state);
626
627
628 // move coordinates inside border and away from upper left highlight.
629 // the extents change accordingly.
630 x += 2;
631 y += 2;
632 dxFace -= 3;
633 dyFace -= 3;
634
635 // Using bitmap2 can cause problems (don't know why!)
636#if !defined(__WIN32__) && !defined(__WIN386__)
637 HBITMAP bitmapOld;
638 if (tool->m_bitmap2.Ok())
c4e7c2aa 639 bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap2.GetHBITMAP());
2bda0e17 640 else
c4e7c2aa 641 bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap1.GetHBITMAP());
2bda0e17 642#else
c4e7c2aa 643 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap1.GetHBITMAP());
2bda0e17
KB
644#endif
645
646 // calculate offset of face from (x,y). y is always from the top,
647 // so the offset is easy. x needs to be centered in face.
648 yOffset = 1;
81d66cf3 649 xCenterOffset = (dxFace - (int)GetToolBitmapSize().x)/2;
2bda0e17
KB
650 if (state & (wxTBSTATE_PRESSED | wxTBSTATE_CHECKED))
651 {
652 // pressed state moves down and to the right
653 // (x moves automatically as face size grows)
654 yOffset++;
655 }
656
657 // now put on the face
658 if (state & wxTBSTATE_ENABLED) {
659 // regular version
81d66cf3 660 BitBlt((HDC) hdc, x+xCenterOffset, y + yOffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
2bda0e17
KB
661 hdcGlyphs, 0, 0, SRCCOPY);
662 } else {
663 // disabled version (or indeterminate)
664 bMaskCreated = TRUE;
665 CreateMask((WXHDC) hdcGlyphs, xCenterOffset, yOffset, dxFace, dyFace);
666// CreateMask(hBitmap, xCenterOffset, yOffset, dxFace, dyFace);
667
668 SetTextColor((HDC) hdc, 0L); // 0's in mono -> 0 (for ROP)
669 SetBkColor((HDC) hdc, 0x00FFFFFF); // 1's in mono -> 1
670
671 // draw glyph's white understrike
672 if (!(state & wxTBSTATE_INDETERMINATE)) {
673 hbr = CreateSolidBrush(m_rgbHilight);
674 if (hbr) {
c4e7c2aa 675 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
2bda0e17
KB
676 if (hbrOld) {
677 // draw hilight color where we have 0's in the mask
678 BitBlt((HDC) hdc, x + 1, y + 1, dxFace, dyFace, (HDC) m_hdcMono, 0, 0, 0x00B8074A);
679 SelectObject((HDC) hdc, hbrOld);
680 }
681 DeleteObject(hbr);
682 }
683 }
684
685 // gray out glyph
686 hbr = CreateSolidBrush(m_rgbShadow);
687 if (hbr) {
c4e7c2aa 688 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
2bda0e17
KB
689 if (hbrOld) {
690 // draw the shadow color where we have 0's in the mask
691 BitBlt((HDC) hdc, x, y, dxFace, dyFace, (HDC) m_hdcMono, 0, 0, 0x00B8074A);
692 SelectObject((HDC) hdc, hbrOld);
693 }
694 DeleteObject(hbr);
695 }
696
697 if (state & wxTBSTATE_CHECKED) {
698 BitBlt((HDC) m_hdcMono, 1, 1, dxFace - 1, dyFace - 1, (HDC) m_hdcMono, 0, 0, SRCAND);
699 }
700 }
701
702 if (state & (wxTBSTATE_CHECKED | wxTBSTATE_INDETERMINATE)) {
703
c4e7c2aa 704 hbrOld = (HBRUSH) SelectObject((HDC) hdc, (HBRUSH) m_hbrDither);
2bda0e17
KB
705 if (hbrOld) {
706
707 if (!bMaskCreated)
708 CreateMask((WXHDC) hdcGlyphs, xCenterOffset, yOffset, dxFace, dyFace);
709// CreateMask(hBitmap, xCenterOffset, yOffset, dxFace, dyFace);
710
711 SetTextColor((HDC) hdc, 0L); // 0 -> 0
712 SetBkColor((HDC) hdc, 0x00FFFFFF); // 1 -> 1
713
714 // only draw the dither brush where the mask is 1's
715 BitBlt((HDC) hdc, x, y, dxFace, dyFace, (HDC) m_hdcMono, 0, 0, 0x00E20746);
716
717 SelectObject((HDC) hdc, hbrOld);
718 }
719 }
720 SelectObject(hdcGlyphs, bitmapOld);
721 DeleteDC(hdcGlyphs);
722}
723
724void wxToolBarMSW::GetSysColors(void)
725{
726 static COLORREF rgbSaveFace = 0xffffffffL,
727 rgbSaveShadow = 0xffffffffL,
728 rgbSaveHilight = 0xffffffffL,
729 rgbSaveFrame = 0xffffffffL;
730
731 // For now, override these because the colour replacement isn't working,
732 // and we get inconsistent colours. Assume all buttons are grey for the moment.
733
734// m_rgbFace = GetSysColor(COLOR_BTNFACE);
735 m_rgbFace = RGB(192,192,192);
736// m_rgbShadow = GetSysColor(COLOR_BTNSHADOW);
737 m_rgbShadow = RGB(128,128,128);
738// m_rgbHilight = GetSysColor(COLOR_BTNHIGHLIGHT);
739 m_rgbHilight = RGB(255, 255, 255);
740
741 m_rgbFrame = GetSysColor(COLOR_WINDOWFRAME);
742
743 if (rgbSaveFace!=m_rgbFace || rgbSaveShadow!=m_rgbShadow
744 || rgbSaveHilight!=m_rgbHilight || rgbSaveFrame!=m_rgbFrame)
745 {
746 rgbSaveFace = m_rgbFace;
747 rgbSaveShadow = m_rgbShadow;
748 rgbSaveHilight = m_rgbHilight;
749 rgbSaveFrame = m_rgbFrame;
750
751 // Update the brush for pushed-in buttons
752 CreateDitherBrush();
753 }
754}
755
756WXHBITMAP wxToolBarMSW::CreateDitherBitmap()
757{
758 BITMAPINFO* pbmi;
759 HBITMAP hbm;
760 HDC hdc;
761 int i;
762 long patGray[8];
763 DWORD rgb;
764
765 pbmi = (BITMAPINFO *)malloc(sizeof(BITMAPINFOHEADER) + 16*sizeof(RGBQUAD));
766 memset(pbmi, 0, (sizeof(BITMAPINFOHEADER) + 16*sizeof(RGBQUAD)));
767
768 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
769 pbmi->bmiHeader.biWidth = 8;
770 pbmi->bmiHeader.biHeight = 8;
771 pbmi->bmiHeader.biPlanes = 1;
772 pbmi->bmiHeader.biBitCount = 1;
773 pbmi->bmiHeader.biCompression = BI_RGB;
774
775// rgb = GetSysColor(COLOR_BTNFACE);
776 rgb = RGB(192,192,192);
777
778 pbmi->bmiColors[0].rgbBlue = GetBValue(rgb);
779 pbmi->bmiColors[0].rgbGreen = GetGValue(rgb);
780 pbmi->bmiColors[0].rgbRed = GetRValue(rgb);
781 pbmi->bmiColors[0].rgbReserved = 0;
782
783// rgb = GetSysColor(COLOR_BTNHIGHLIGHT);
784 rgb = RGB(255, 255, 255);
785
786 pbmi->bmiColors[1].rgbBlue = GetBValue(rgb);
787 pbmi->bmiColors[1].rgbGreen = GetGValue(rgb);
788 pbmi->bmiColors[1].rgbRed = GetRValue(rgb);
789 pbmi->bmiColors[1].rgbReserved = 0;
790
791 /* initialize the brushes */
792
793 for (i = 0; i < 8; i++)
794 if (i & 1)
795 patGray[i] = 0xAAAA5555L; // 0x11114444L; // lighter gray
796 else
797 patGray[i] = 0x5555AAAAL; // 0x11114444L; // lighter gray
798
799 hdc = ::GetDC(NULL);
800
801 hbm = CreateDIBitmap(hdc, &pbmi->bmiHeader, CBM_INIT, patGray, pbmi, DIB_RGB_COLORS);
802
803 ReleaseDC(NULL, hdc);
804 free(pbmi);
805
806 return (WXHBITMAP)hbm;
807}
808
809bool wxToolBarMSW::CreateDitherBrush(void)
810{
811 HBITMAP hbmGray;
812 HBRUSH hbrSave;
813 if (m_hbrDither)
814 return TRUE;
815 hbmGray = (HBITMAP) CreateDitherBitmap();
816
817 if (hbmGray)
818 {
819 hbrSave = (HBRUSH) m_hbrDither;
820 m_hbrDither = (WXHBRUSH) CreatePatternBrush(hbmGray);
821 DeleteObject(hbmGray);
822 if (m_hbrDither)
823 {
824 if (hbrSave)
825 {
826 DeleteObject(hbrSave);
827 }
828 return TRUE;
829 }
830 else
831 {
832 m_hbrDither = (WXHBRUSH) hbrSave;
833 }
834 }
835
836 return FALSE;
837}
838
839bool wxToolBarMSW::FreeDitherBrush(void)
840{
841 if (m_hbrDither)
842 DeleteObject((HBRUSH) m_hbrDither);
843 m_hbrDither = 0;
844 return TRUE;
845}
846
847typedef struct tagCOLORMAP2
848{
849 COLORREF bgrfrom;
850 COLORREF bgrto;
851 COLORREF sysColor;
852} COLORMAP2;
853
854// these are the default colors used to map the dib colors
855// to the current system colors
856
857#define BGR_BUTTONTEXT (RGB(000,000,000)) // black
858#define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey
859#define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey
860#define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white
861#define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue
862#define BGR_BACKGROUND (RGB(255,000,255)) // magenta
863#define FlipColor(rgb) (RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb)))
864
865WXHBITMAP wxToolBarMSW::CreateMappedBitmap(WXHINSTANCE WXUNUSED(hInstance), void *info)
866{
867 LPBITMAPINFOHEADER lpBitmapInfo = (LPBITMAPINFOHEADER)info;
868 HDC hdc, hdcMem = NULL;
869
870 DWORD FAR *p;
871 LPSTR lpBits;
872 HBITMAP hbm = NULL, hbmOld;
873 int numcolors, i;
874 int wid, hgt;
875 static COLORMAP2 ColorMap[] = {
876 {BGR_BUTTONTEXT, BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black
877 {BGR_BUTTONSHADOW, BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey
878 {BGR_BUTTONFACE, BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey
879 {BGR_BUTTONHILIGHT, BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white
880 {BGR_BACKGROUNDSEL, BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue
881 {BGR_BACKGROUND, BGR_BACKGROUND, COLOR_WINDOW} // magenta
882 };
883
884 #define NUM_MAPS (sizeof(ColorMap)/sizeof(COLORMAP2))
885
886 if (!lpBitmapInfo)
887 return 0;
888
889 //
890 // So what are the new colors anyway ?
891 //
892 for (i=0; i < (int) NUM_MAPS; i++) {
893 ColorMap[i].bgrto = (long unsigned int) FlipColor(GetSysColor((int)ColorMap[i].sysColor));
894 }
895
896 p = (DWORD FAR *)(((LPSTR)lpBitmapInfo) + lpBitmapInfo->biSize);
897
898 /* Replace button-face and button-shadow colors with the current values
899 */
900 numcolors = 16;
901
902 while (numcolors-- > 0) {
903 for (i = 0; i < (int) NUM_MAPS; i++) {
904 if (*p == ColorMap[i].bgrfrom) {
905 *p = ColorMap[i].bgrto;
906 break;
907 }
908 }
909 p++;
910 }
911
912 /* First skip over the header structure */
913 lpBits = (LPSTR)(lpBitmapInfo + 1);
914
915 /* Skip the color table entries, if any */
916 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
917
918 /* Create a color bitmap compatible with the display device */
919 i = wid = (int)lpBitmapInfo->biWidth;
920 hgt = (int)lpBitmapInfo->biHeight;
921 hdc = ::GetDC(NULL);
922
923 hdcMem = CreateCompatibleDC(hdc);
924 if (hdcMem) {
925// hbm = CreateDiscardableBitmap(hdc, i, hgt);
926 hbm = CreateCompatibleBitmap(hdc, i, hgt);
927 if (hbm) {
c4e7c2aa 928 hbmOld = (HBITMAP) SelectObject(hdcMem, hbm);
2bda0e17
KB
929
930 // set the main image
931 StretchDIBits(hdcMem, 0, 0, wid, hgt, 0, 0, wid, hgt, lpBits,
932 (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
933
934 SelectObject(hdcMem, hbmOld);
935 }
936
937 DeleteObject(hdcMem);
938 }
939
940 ReleaseDC(NULL, hdc);
941
942 return (WXHBITMAP) hbm;
943}
944
945WXHBITMAP wxToolBarMSW::CreateMappedBitmap(WXHINSTANCE hInstance, WXHBITMAP hBitmap)
946{
947 HANDLE hDIB = BitmapToDIB((HBITMAP) hBitmap, 0);
948 if (hDIB)
949 {
950#ifdef __WINDOWS_386__
951 LPBITMAPINFOHEADER lpbmInfoHdr = (LPBITMAPINFOHEADER)MK_FP32(GlobalLock(hDIB));
952#else
953 LPBITMAPINFOHEADER lpbmInfoHdr = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
954#endif
955 HBITMAP newBitmap = (HBITMAP) CreateMappedBitmap((WXHINSTANCE) wxGetInstance(), lpbmInfoHdr);
956 GlobalUnlock(hDIB);
957 GlobalFree(hDIB);
958 return (WXHBITMAP) newBitmap;
959 }
960 return 0;
961}
962
963#endif