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