]> git.saurik.com Git - wxWidgets.git/blob - src/msw/tbarmsw.cpp
Added (untested) support for sub-locales.
[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 #if !defined(__GNUWIN32__) && !defined(__SALFORDC__)
30 #include "malloc.h"
31 #endif
32
33 #if !defined(__MWERKS__) && !defined(__SALFORDC__)
34 #include <memory.h>
35 #endif
36
37 #include <stdlib.h>
38
39 #include "wx/tbarmsw.h"
40 #include "wx/event.h"
41 #include "wx/app.h"
42 #include "wx/bitmap.h"
43 #include "wx/msw/private.h"
44 #include "wx/msw/dib.h"
45
46 #define DEFAULTBITMAPX 16
47 #define DEFAULTBITMAPY 15
48 #define DEFAULTBUTTONX 24
49 #define DEFAULTBUTTONY 22
50 #define DEFAULTBARHEIGHT 27
51
52 /////// Non-Windows 95 implementation
53
54 #if !wxUSE_IMAGE_LOADING_IN_MSW
55 #error If wxUSE_IMAGE_LOADING_IN_MSW is set to 0, then wxUSE_BUTTONBAR must be set to 0 too.
56 #endif
57
58 #if !USE_SHARED_LIBRARY
59 IMPLEMENT_DYNAMIC_CLASS(wxToolBarMSW, wxToolBarBase)
60
61 BEGIN_EVENT_TABLE(wxToolBarMSW, wxToolBarBase)
62 EVT_SIZE(wxToolBarMSW::OnSize)
63 EVT_PAINT(wxToolBarMSW::OnPaint)
64 EVT_MOUSE_EVENTS(wxToolBarMSW::OnMouseEvent)
65 END_EVENT_TABLE()
66 #endif
67
68 wxToolBarMSW::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
82 bool wxToolBarMSW::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
83 long style, const wxString& name)
84 {
85 if ( ! wxWindow::Create(parent, id, pos, size, style, name) )
86 return FALSE;
87
88 if ( style & wxTB_HORIZONTAL )
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
118 wxToolBarMSW::~wxToolBarMSW(void)
119 {
120 FreeGlobalObjects();
121 }
122
123 void wxToolBarMSW::SetToolBitmapSize(const wxSize& size)
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
131 wxSize wxToolBarMSW::GetToolSize(void) const
132 {
133 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
134 }
135
136 void 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
166 void 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).
174 void 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.
303 void wxToolBarMSW::EnableTool(int toolIndex, bool enable)
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
322 void 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
327 void 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.
340 wxToolBarTool *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)
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__)
347 wxBitmap bitmap2;
348 if (toggle)
349 {
350 bitmap2.SetHBITMAP( (WXHBITMAP) CreateMappedBitmap(wxGetInstance(), (HBITMAP) ((wxBitmap& )bitmap).GetHBITMAP()));
351 }
352
353 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, bitmap2, toggle, xPos, yPos, helpString1, helpString2);
354 #else
355 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, wxNullBitmap, toggle, xPos, yPos, helpString1, helpString2);
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;
371 tool->SetSize(GetToolSize().x, GetToolSize().y);
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
384 void 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 )
468 m_maxWidth += maxToolWidth;
469 else
470 m_maxHeight += maxToolHeight;
471
472 m_maxWidth += m_xMargin;
473 m_maxHeight += m_yMargin;
474 }
475
476
477 bool wxToolBarMSW::InitGlobalObjects(void)
478 {
479 GetSysColors();
480 if (!CreateDitherBrush())
481 return FALSE;
482
483 m_hdcMono = (WXHDC) CreateCompatibleDC(NULL);
484 if (!m_hdcMono)
485 return FALSE;
486
487 m_hbmMono = (WXHBITMAP) CreateBitmap((int)GetToolSize().x, (int)GetToolSize().y, 1, 1, NULL);
488 if (!m_hbmMono)
489 return FALSE;
490
491 m_hbmDefault = (WXHBITMAP) SelectObject((HDC) m_hdcMono, (HBITMAP) m_hbmMono);
492 return TRUE;
493 }
494
495 void wxToolBarMSW::FreeGlobalObjects(void)
496 {
497 FreeDitherBrush();
498
499 if (m_hdcMono) {
500 if (m_hbmDefault)
501 {
502 SelectObject((HDC) m_hdcMono, (HBITMAP) m_hbmDefault);
503 m_hbmDefault = 0;
504 }
505 DeleteDC((HDC) m_hdcMono); // toast the DCs
506 }
507 m_hdcMono = 0;
508
509 if (m_hbmMono)
510 DeleteObject((HBITMAP) m_hbmMono);
511 m_hbmMono = 0;
512 }
513
514
515 void wxToolBarMSW::PatB(WXHDC hdc,int x,int y,int dx,int dy, long rgb)
516 {
517 RECT rc;
518
519 rc.left = x;
520 rc.top = y;
521 rc.right = x + dx;
522 rc.bottom = y + dy;
523
524 SetBkColor((HDC) hdc,rgb);
525 ExtTextOut((HDC) hdc,0,0,ETO_OPAQUE,&rc,NULL,0,NULL);
526 }
527
528
529 // create a mono bitmap mask:
530 // 1's where color == COLOR_BTNFACE || COLOR_HILIGHT
531 // 0's everywhere else
532
533 void wxToolBarMSW::CreateMask(WXHDC hdc, int xoffset, int yoffset, int dx, int dy)
534 {
535 HDC globalDC = ::GetDC(NULL);
536 HDC hdcGlyphs = CreateCompatibleDC((HDC) globalDC);
537 ReleaseDC(NULL, (HDC) globalDC);
538
539 // krj - create a new bitmap and copy the image from hdc.
540 //HBITMAP bitmapOld = SelectObject(hdcGlyphs, hBitmap);
541 HBITMAP hBitmap = CreateCompatibleBitmap((HDC) hdc, dx, dy);
542 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, hBitmap);
543 BitBlt(hdcGlyphs, 0,0, dx, dy, (HDC) hdc, 0, 0, SRCCOPY);
544
545 // initalize whole area with 1's
546 PatBlt((HDC) m_hdcMono, 0, 0, dx, dy, WHITENESS);
547
548 // create mask based on color bitmap
549 // convert this to 1's
550 SetBkColor(hdcGlyphs, m_rgbFace);
551 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
552 hdcGlyphs, 0, 0, SRCCOPY);
553 // convert this to 1's
554 SetBkColor(hdcGlyphs, m_rgbHilight);
555 // OR in the new 1's
556 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
557 hdcGlyphs, 0, 0, SRCPAINT);
558
559 SelectObject(hdcGlyphs, bitmapOld);
560 DeleteObject(hBitmap);
561 DeleteDC(hdcGlyphs);
562 }
563
564 void wxToolBarMSW::DrawBlankButton(WXHDC hdc, int x, int y, int dx, int dy, int state)
565 {
566 // face color
567 PatB(hdc, x, y, dx, dy, m_rgbFace);
568
569 if (state & wxTBSTATE_PRESSED) {
570 PatB(hdc, x + 1, y, dx - 2, 1, m_rgbFrame);
571 PatB(hdc, x + 1, y + dy - 1, dx - 2, 1, m_rgbFrame);
572 PatB(hdc, x, y + 1, 1, dy - 2, m_rgbFrame);
573 PatB(hdc, x + dx - 1, y +1, 1, dy - 2, m_rgbFrame);
574 PatB(hdc, x + 1, y + 1, 1, dy-2, m_rgbShadow);
575 PatB(hdc, x + 1, y + 1, dx-2, 1, m_rgbShadow);
576 }
577 else {
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 dx -= 2;
583 dy -= 2;
584 PatB(hdc, x + 1, y + 1, 1, dy - 1, m_rgbHilight);
585 PatB(hdc, x + 1, y + 1, dx - 1, 1, m_rgbHilight);
586 PatB(hdc, x + dx, y + 1, 1, dy, m_rgbShadow);
587 PatB(hdc, x + 1, y + dy, dx, 1, m_rgbShadow);
588 PatB(hdc, x + dx - 1, y + 2, 1, dy - 2, m_rgbShadow);
589 PatB(hdc, x + 2, y + dy - 1, dx - 2, 1, m_rgbShadow);
590 }
591 }
592
593 void wxToolBarMSW::DrawButton(WXHDC hdc, int x, int y, int dx, int dy, wxToolBarTool *tool, int state)
594 {
595 int yOffset;
596 HBRUSH hbrOld, hbr;
597 BOOL bMaskCreated = FALSE;
598 int xButton = 0; // assume button is down
599 int dxFace, dyFace;
600 int xCenterOffset;
601
602 dxFace = dx;
603 dyFace = dy;
604
605 // HBITMAP hBitmap = (HBITMAP) tool->m_bitmap1.GetHBITMAP();
606 HDC globalDC = ::GetDC(NULL);
607 HDC hdcGlyphs = CreateCompatibleDC(globalDC);
608 ReleaseDC(NULL, globalDC);
609
610 // get the proper button look - up or down.
611 if (!(state & (wxTBSTATE_PRESSED | wxTBSTATE_CHECKED))) {
612 xButton = dx; // use 'up' version of button
613 dxFace -= 2;
614 dyFace -= 2; // extents to ignore button highlight
615 }
616
617 DrawBlankButton(hdc, x, y, dx, dy, state);
618
619
620 // move coordinates inside border and away from upper left highlight.
621 // the extents change accordingly.
622 x += 2;
623 y += 2;
624 dxFace -= 3;
625 dyFace -= 3;
626
627 // Using bitmap2 can cause problems (don't know why!)
628 #if !defined(__WIN32__) && !defined(__WIN386__)
629 HBITMAP bitmapOld;
630 if (tool->m_bitmap2.Ok())
631 bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap2.GetHBITMAP());
632 else
633 bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap1.GetHBITMAP());
634 #else
635 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap1.GetHBITMAP());
636 #endif
637
638 // calculate offset of face from (x,y). y is always from the top,
639 // so the offset is easy. x needs to be centered in face.
640 yOffset = 1;
641 xCenterOffset = (dxFace - (int)GetToolBitmapSize().x)/2;
642 if (state & (wxTBSTATE_PRESSED | wxTBSTATE_CHECKED))
643 {
644 // pressed state moves down and to the right
645 // (x moves automatically as face size grows)
646 yOffset++;
647 }
648
649 // now put on the face
650 if (state & wxTBSTATE_ENABLED) {
651 // regular version
652 BitBlt((HDC) hdc, x+xCenterOffset, y + yOffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
653 hdcGlyphs, 0, 0, SRCCOPY);
654 } else {
655 // disabled version (or indeterminate)
656 bMaskCreated = TRUE;
657 CreateMask((WXHDC) hdcGlyphs, xCenterOffset, yOffset, dxFace, dyFace);
658 // CreateMask(hBitmap, xCenterOffset, yOffset, dxFace, dyFace);
659
660 SetTextColor((HDC) hdc, 0L); // 0's in mono -> 0 (for ROP)
661 SetBkColor((HDC) hdc, 0x00FFFFFF); // 1's in mono -> 1
662
663 // draw glyph's white understrike
664 if (!(state & wxTBSTATE_INDETERMINATE)) {
665 hbr = CreateSolidBrush(m_rgbHilight);
666 if (hbr) {
667 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
668 if (hbrOld) {
669 // draw hilight color where we have 0's in the mask
670 BitBlt((HDC) hdc, x + 1, y + 1, dxFace, dyFace, (HDC) m_hdcMono, 0, 0, 0x00B8074A);
671 SelectObject((HDC) hdc, hbrOld);
672 }
673 DeleteObject(hbr);
674 }
675 }
676
677 // gray out glyph
678 hbr = CreateSolidBrush(m_rgbShadow);
679 if (hbr) {
680 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
681 if (hbrOld) {
682 // draw the shadow color where we have 0's in the mask
683 BitBlt((HDC) hdc, x, y, dxFace, dyFace, (HDC) m_hdcMono, 0, 0, 0x00B8074A);
684 SelectObject((HDC) hdc, hbrOld);
685 }
686 DeleteObject(hbr);
687 }
688
689 if (state & wxTBSTATE_CHECKED) {
690 BitBlt((HDC) m_hdcMono, 1, 1, dxFace - 1, dyFace - 1, (HDC) m_hdcMono, 0, 0, SRCAND);
691 }
692 }
693
694 if (state & (wxTBSTATE_CHECKED | wxTBSTATE_INDETERMINATE)) {
695
696 hbrOld = (HBRUSH) SelectObject((HDC) hdc, (HBRUSH) m_hbrDither);
697 if (hbrOld) {
698
699 if (!bMaskCreated)
700 CreateMask((WXHDC) hdcGlyphs, xCenterOffset, yOffset, dxFace, dyFace);
701 // CreateMask(hBitmap, xCenterOffset, yOffset, dxFace, dyFace);
702
703 SetTextColor((HDC) hdc, 0L); // 0 -> 0
704 SetBkColor((HDC) hdc, 0x00FFFFFF); // 1 -> 1
705
706 // only draw the dither brush where the mask is 1's
707 BitBlt((HDC) hdc, x, y, dxFace, dyFace, (HDC) m_hdcMono, 0, 0, 0x00E20746);
708
709 SelectObject((HDC) hdc, hbrOld);
710 }
711 }
712 SelectObject(hdcGlyphs, bitmapOld);
713 DeleteDC(hdcGlyphs);
714 }
715
716 void wxToolBarMSW::GetSysColors(void)
717 {
718 static COLORREF rgbSaveFace = 0xffffffffL,
719 rgbSaveShadow = 0xffffffffL,
720 rgbSaveHilight = 0xffffffffL,
721 rgbSaveFrame = 0xffffffffL;
722
723 // For now, override these because the colour replacement isn't working,
724 // and we get inconsistent colours. Assume all buttons are grey for the moment.
725
726 // m_rgbFace = GetSysColor(COLOR_BTNFACE);
727 m_rgbFace = RGB(192,192,192);
728 // m_rgbShadow = GetSysColor(COLOR_BTNSHADOW);
729 m_rgbShadow = RGB(128,128,128);
730 // m_rgbHilight = GetSysColor(COLOR_BTNHIGHLIGHT);
731 m_rgbHilight = RGB(255, 255, 255);
732
733 m_rgbFrame = GetSysColor(COLOR_WINDOWFRAME);
734
735 if (rgbSaveFace!=m_rgbFace || rgbSaveShadow!=m_rgbShadow
736 || rgbSaveHilight!=m_rgbHilight || rgbSaveFrame!=m_rgbFrame)
737 {
738 rgbSaveFace = m_rgbFace;
739 rgbSaveShadow = m_rgbShadow;
740 rgbSaveHilight = m_rgbHilight;
741 rgbSaveFrame = m_rgbFrame;
742
743 // Update the brush for pushed-in buttons
744 CreateDitherBrush();
745 }
746 }
747
748 WXHBITMAP wxToolBarMSW::CreateDitherBitmap()
749 {
750 BITMAPINFO* pbmi;
751 HBITMAP hbm;
752 HDC hdc;
753 int i;
754 long patGray[8];
755 DWORD rgb;
756
757 pbmi = (BITMAPINFO *)malloc(sizeof(BITMAPINFOHEADER) + 16*sizeof(RGBQUAD));
758 memset(pbmi, 0, (sizeof(BITMAPINFOHEADER) + 16*sizeof(RGBQUAD)));
759
760 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
761 pbmi->bmiHeader.biWidth = 8;
762 pbmi->bmiHeader.biHeight = 8;
763 pbmi->bmiHeader.biPlanes = 1;
764 pbmi->bmiHeader.biBitCount = 1;
765 pbmi->bmiHeader.biCompression = BI_RGB;
766
767 // rgb = GetSysColor(COLOR_BTNFACE);
768 rgb = RGB(192,192,192);
769
770 pbmi->bmiColors[0].rgbBlue = GetBValue(rgb);
771 pbmi->bmiColors[0].rgbGreen = GetGValue(rgb);
772 pbmi->bmiColors[0].rgbRed = GetRValue(rgb);
773 pbmi->bmiColors[0].rgbReserved = 0;
774
775 // rgb = GetSysColor(COLOR_BTNHIGHLIGHT);
776 rgb = RGB(255, 255, 255);
777
778 pbmi->bmiColors[1].rgbBlue = GetBValue(rgb);
779 pbmi->bmiColors[1].rgbGreen = GetGValue(rgb);
780 pbmi->bmiColors[1].rgbRed = GetRValue(rgb);
781 pbmi->bmiColors[1].rgbReserved = 0;
782
783 /* initialize the brushes */
784
785 for (i = 0; i < 8; i++)
786 if (i & 1)
787 patGray[i] = 0xAAAA5555L; // 0x11114444L; // lighter gray
788 else
789 patGray[i] = 0x5555AAAAL; // 0x11114444L; // lighter gray
790
791 hdc = ::GetDC(NULL);
792
793 hbm = CreateDIBitmap(hdc, &pbmi->bmiHeader, CBM_INIT, patGray, pbmi, DIB_RGB_COLORS);
794
795 ReleaseDC(NULL, hdc);
796 free(pbmi);
797
798 return (WXHBITMAP)hbm;
799 }
800
801 bool wxToolBarMSW::CreateDitherBrush(void)
802 {
803 HBITMAP hbmGray;
804 HBRUSH hbrSave;
805 if (m_hbrDither)
806 return TRUE;
807 hbmGray = (HBITMAP) CreateDitherBitmap();
808
809 if (hbmGray)
810 {
811 hbrSave = (HBRUSH) m_hbrDither;
812 m_hbrDither = (WXHBRUSH) CreatePatternBrush(hbmGray);
813 DeleteObject(hbmGray);
814 if (m_hbrDither)
815 {
816 if (hbrSave)
817 {
818 DeleteObject(hbrSave);
819 }
820 return TRUE;
821 }
822 else
823 {
824 m_hbrDither = (WXHBRUSH) hbrSave;
825 }
826 }
827
828 return FALSE;
829 }
830
831 bool wxToolBarMSW::FreeDitherBrush(void)
832 {
833 if (m_hbrDither)
834 DeleteObject((HBRUSH) m_hbrDither);
835 m_hbrDither = 0;
836 return TRUE;
837 }
838
839 typedef struct tagCOLORMAP2
840 {
841 COLORREF bgrfrom;
842 COLORREF bgrto;
843 COLORREF sysColor;
844 } COLORMAP2;
845
846 // these are the default colors used to map the dib colors
847 // to the current system colors
848
849 #define BGR_BUTTONTEXT (RGB(000,000,000)) // black
850 #define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey
851 #define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey
852 #define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white
853 #define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue
854 #define BGR_BACKGROUND (RGB(255,000,255)) // magenta
855 #define FlipColor(rgb) (RGB(GetBValue(rgb), GetGValue(rgb), GetRValue(rgb)))
856
857 WXHBITMAP wxToolBarMSW::CreateMappedBitmap(WXHINSTANCE WXUNUSED(hInstance), void *info)
858 {
859 LPBITMAPINFOHEADER lpBitmapInfo = (LPBITMAPINFOHEADER)info;
860 HDC hdc, hdcMem = NULL;
861
862 DWORD FAR *p;
863 LPSTR lpBits;
864 HBITMAP hbm = NULL, hbmOld;
865 int numcolors, i;
866 int wid, hgt;
867 static COLORMAP2 ColorMap[] = {
868 {BGR_BUTTONTEXT, BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black
869 {BGR_BUTTONSHADOW, BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey
870 {BGR_BUTTONFACE, BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey
871 {BGR_BUTTONHILIGHT, BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white
872 {BGR_BACKGROUNDSEL, BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue
873 {BGR_BACKGROUND, BGR_BACKGROUND, COLOR_WINDOW} // magenta
874 };
875
876 #define NUM_MAPS (sizeof(ColorMap)/sizeof(COLORMAP2))
877
878 if (!lpBitmapInfo)
879 return 0;
880
881 //
882 // So what are the new colors anyway ?
883 //
884 for (i=0; i < (int) NUM_MAPS; i++) {
885 ColorMap[i].bgrto = (long unsigned int) FlipColor(GetSysColor((int)ColorMap[i].sysColor));
886 }
887
888 p = (DWORD FAR *)(((LPSTR)lpBitmapInfo) + lpBitmapInfo->biSize);
889
890 /* Replace button-face and button-shadow colors with the current values
891 */
892 numcolors = 16;
893
894 while (numcolors-- > 0) {
895 for (i = 0; i < (int) NUM_MAPS; i++) {
896 if (*p == ColorMap[i].bgrfrom) {
897 *p = ColorMap[i].bgrto;
898 break;
899 }
900 }
901 p++;
902 }
903
904 /* First skip over the header structure */
905 lpBits = (LPSTR)(lpBitmapInfo + 1);
906
907 /* Skip the color table entries, if any */
908 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
909
910 /* Create a color bitmap compatible with the display device */
911 i = wid = (int)lpBitmapInfo->biWidth;
912 hgt = (int)lpBitmapInfo->biHeight;
913 hdc = ::GetDC(NULL);
914
915 hdcMem = CreateCompatibleDC(hdc);
916 if (hdcMem) {
917 // hbm = CreateDiscardableBitmap(hdc, i, hgt);
918 hbm = CreateCompatibleBitmap(hdc, i, hgt);
919 if (hbm) {
920 hbmOld = (HBITMAP) SelectObject(hdcMem, hbm);
921
922 // set the main image
923 StretchDIBits(hdcMem, 0, 0, wid, hgt, 0, 0, wid, hgt, lpBits,
924 (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
925
926 SelectObject(hdcMem, hbmOld);
927 }
928
929 DeleteObject(hdcMem);
930 }
931
932 ReleaseDC(NULL, hdc);
933
934 return (WXHBITMAP) hbm;
935 }
936
937 WXHBITMAP wxToolBarMSW::CreateMappedBitmap(WXHINSTANCE hInstance, WXHBITMAP hBitmap)
938 {
939 HANDLE hDIB = BitmapToDIB((HBITMAP) hBitmap, 0);
940 if (hDIB)
941 {
942 #ifdef __WINDOWS_386__
943 LPBITMAPINFOHEADER lpbmInfoHdr = (LPBITMAPINFOHEADER)MK_FP32(GlobalLock(hDIB));
944 #else
945 LPBITMAPINFOHEADER lpbmInfoHdr = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
946 #endif
947 HBITMAP newBitmap = (HBITMAP) CreateMappedBitmap((WXHINSTANCE) wxGetInstance(), lpbmInfoHdr);
948 GlobalUnlock(hDIB);
949 GlobalFree(hDIB);
950 return (WXHBITMAP) newBitmap;
951 }
952 return 0;
953 }
954
955 #endif