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