]> git.saurik.com Git - wxWidgets.git/blob - src/msw/tbarmsw.cpp
wxWindow::GetBestSize() 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/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(wxToolBar, 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.GetPosition(&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((WXHINSTANCE)wxGetInstance(), (WXHBITMAP) ((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::LayoutTools()
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 {
469 m_maxWidth += maxToolWidth;
470 m_maxHeight += maxToolHeight;
471 }
472 else
473 {
474 m_maxWidth += maxToolWidth;
475 m_maxHeight += maxToolHeight;
476 }
477
478 m_maxWidth += m_xMargin;
479 m_maxHeight += m_yMargin;
480
481 SetSize(m_maxWidth, m_maxHeight);
482 }
483
484
485 bool 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
495 m_hbmMono = (WXHBITMAP) CreateBitmap((int)GetToolSize().x, (int)GetToolSize().y, 1, 1, NULL);
496 if (!m_hbmMono)
497 return FALSE;
498
499 m_hbmDefault = (WXHBITMAP) SelectObject((HDC) m_hdcMono, (HBITMAP) m_hbmMono);
500 return TRUE;
501 }
502
503 void 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
523 void 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
541 void 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);
550 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, hBitmap);
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);
559 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
560 hdcGlyphs, 0, 0, SRCCOPY);
561 // convert this to 1's
562 SetBkColor(hdcGlyphs, m_rgbHilight);
563 // OR in the new 1's
564 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
565 hdcGlyphs, 0, 0, SRCPAINT);
566
567 SelectObject(hdcGlyphs, bitmapOld);
568 DeleteObject(hBitmap);
569 DeleteDC(hdcGlyphs);
570 }
571
572 void 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
601 void 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())
639 bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap2.GetHBITMAP());
640 else
641 bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap1.GetHBITMAP());
642 #else
643 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap1.GetHBITMAP());
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;
649 xCenterOffset = (dxFace - (int)GetToolBitmapSize().x)/2;
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
660 BitBlt((HDC) hdc, x+xCenterOffset, y + yOffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
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) {
675 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
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) {
688 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
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
704 hbrOld = (HBRUSH) SelectObject((HDC) hdc, (HBRUSH) m_hbrDither);
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
724 void 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
756 WXHBITMAP 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
809 bool 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
839 bool wxToolBarMSW::FreeDitherBrush(void)
840 {
841 if (m_hbrDither)
842 DeleteObject((HBRUSH) m_hbrDither);
843 m_hbrDither = 0;
844 return TRUE;
845 }
846
847 typedef 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
865 WXHBITMAP 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) {
928 hbmOld = (HBITMAP) SelectObject(hdcMem, hbm);
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
945 WXHBITMAP wxToolBarMSW::CreateMappedBitmap(WXHINSTANCE hInstance, WXHBITMAP hBitmap)
946 {
947 HANDLE hDIB = wxBitmapToDIB((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