]> git.saurik.com Git - wxWidgets.git/blame - src/msw/tbarmsw.cpp
Added (untested) support for sub-locales.
[wxWidgets.git] / src / msw / tbarmsw.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: tbarmsw.cpp
3// Purpose: wxToolBarMSW
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "tbarmsw.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
2432b92d 24#include "wx/wx.h"
2bda0e17
KB
25#endif
26
47d67540 27#if wxUSE_BUTTONBAR && wxUSE_TOOLBAR
2bda0e17 28
ce3ed50d 29#if !defined(__GNUWIN32__) && !defined(__SALFORDC__)
2bda0e17
KB
30#include "malloc.h"
31#endif
32
ce3ed50d 33#if !defined(__MWERKS__) && !defined(__SALFORDC__)
2bda0e17 34#include <memory.h>
17dff81c 35#endif
ce3ed50d 36
2bda0e17
KB
37#include <stdlib.h>
38
39#include "wx/tbarmsw.h"
2432b92d 40#include "wx/event.h"
2bda0e17 41#include "wx/app.h"
2432b92d 42#include "wx/bitmap.h"
2bda0e17
KB
43#include "wx/msw/private.h"
44#include "wx/msw/dib.h"
45
81d66cf3
JS
46#define DEFAULTBITMAPX 16
47#define DEFAULTBITMAPY 15
48#define DEFAULTBUTTONX 24
49#define DEFAULTBUTTONY 22
50#define DEFAULTBARHEIGHT 27
51
2bda0e17
KB
52/////// Non-Windows 95 implementation
53
f97c9854 54#if !wxUSE_IMAGE_LOADING_IN_MSW
47d67540 55#error If wxUSE_IMAGE_LOADING_IN_MSW is set to 0, then wxUSE_BUTTONBAR must be set to 0 too.
2bda0e17
KB
56#endif
57
58#if !USE_SHARED_LIBRARY
59IMPLEMENT_DYNAMIC_CLASS(wxToolBarMSW, wxToolBarBase)
60
61BEGIN_EVENT_TABLE(wxToolBarMSW, wxToolBarBase)
62 EVT_SIZE(wxToolBarMSW::OnSize)
63 EVT_PAINT(wxToolBarMSW::OnPaint)
64 EVT_MOUSE_EVENTS(wxToolBarMSW::OnMouseEvent)
65END_EVENT_TABLE()
66#endif
67
68wxToolBarMSW::wxToolBarMSW(void)
69{
70 m_hbrDither = 0;
71 m_rgbFace = 0;
72 m_rgbShadow = 0;
73 m_rgbHilight = 0;
74 m_rgbFrame = 0;
75 m_hdcMono = 0;
76 m_hbmMono = 0;
77 m_hbmDefault = 0;
78 m_defaultWidth = DEFAULTBITMAPX;
79 m_defaultHeight = DEFAULTBITMAPY;
80}
81
debe6624 82bool wxToolBarMSW::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
81d66cf3 83 long style, const wxString& name)
2bda0e17
KB
84{
85 if ( ! wxWindow::Create(parent, id, pos, size, style, name) )
86 return FALSE;
87
81d66cf3 88 if ( style & wxTB_HORIZONTAL )
2bda0e17
KB
89 { m_lastX = 3; m_lastY = 7; }
90 else
91 { m_lastX = 7; m_lastY = 3; }
92 m_maxWidth = m_maxHeight = 0;
93 m_pressedTool = m_currentTool = -1;
94 m_xMargin = 0;
95 m_yMargin = 0;
96 m_toolPacking = 1;
97 m_toolSeparation = 5;
98
99 // Set it to grey
100 SetBackgroundColour(wxColour(192, 192, 192));
101
102 m_hbrDither = 0;
103 m_rgbFace = 0;
104 m_rgbShadow = 0;
105 m_rgbHilight = 0;
106 m_rgbFrame = 0;
107 m_hdcMono = 0;
108 m_hbmMono = 0;
109 m_hbmDefault = 0;
110 m_defaultWidth = DEFAULTBITMAPX;
111 m_defaultHeight = DEFAULTBITMAPY;
112
113 InitGlobalObjects();
114
115 return TRUE;
116}
117
118wxToolBarMSW::~wxToolBarMSW(void)
119{
120 FreeGlobalObjects();
121}
122
81d66cf3 123void wxToolBarMSW::SetToolBitmapSize(const wxSize& size)
2bda0e17
KB
124{
125 m_defaultWidth = size.x; m_defaultHeight = size.y;
126 FreeGlobalObjects();
127 InitGlobalObjects();
128}
129
130// The button size is bigger than the bitmap size
81d66cf3 131wxSize wxToolBarMSW::GetToolSize(void) const
2bda0e17
KB
132{
133 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
134}
135
136void wxToolBarMSW::OnPaint(wxPaintEvent& event)
137{
138 wxPaintDC dc(this);
139
140 static int wxOnPaintCount = 0;
141
142 // Prevent reentry of OnPaint which would cause
143 // wxMemoryDC errors.
144 if (wxOnPaintCount > 0)
145 return;
146 wxOnPaintCount ++;
147
148 wxNode *node = m_tools.First();
149 while (node)
150 {
151 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
152 if (tool->m_toolStyle != wxTOOL_STYLE_SEPARATOR)
153 {
154 int state = wxTBSTATE_ENABLED;
155 if (!tool->m_enabled)
156 state = 0;
157 if (tool->m_isToggle && tool->m_toggleState)
158 state |= wxTBSTATE_CHECKED;
159 DrawTool(dc, tool, state);
160 }
161 node = node->Next();
162 }
163 wxOnPaintCount --;
164}
165
166void wxToolBarMSW::OnSize(wxSizeEvent& event)
167{
168 wxToolBarBase::OnSize(event);
169}
170
171// If a Button is disabled, then NO function (besides leaving
172// or entering) should be carried out. Therefore the additions
173// of 'enabled' testing (Stefan Hammes).
174void wxToolBarMSW::OnMouseEvent(wxMouseEvent& event)
175{
176 static wxToolBarTool *eventCurrentTool = NULL;
177 wxClientDC dc(this);
178
179 if (event.Leaving())
180 {
181 m_currentTool = -1;
182 if (eventCurrentTool && eventCurrentTool->m_enabled)
183 {
184 ::ReleaseCapture();
185 int state = wxTBSTATE_ENABLED;
186 if (eventCurrentTool->m_toggleState)
187 state |= wxTBSTATE_CHECKED;
188 DrawTool(dc, eventCurrentTool, state);
189 eventCurrentTool = NULL;
190 }
191 OnMouseEnter(-1);
192 return;
193 }
194
195 long x, y;
196 event.Position(&x, &y);
197 wxToolBarTool *tool = FindToolForPosition(x, y);
198
199 if (!tool)
200 {
201 if (eventCurrentTool && eventCurrentTool->m_enabled)
202 {
203 ::ReleaseCapture();
204
205 int state = wxTBSTATE_ENABLED;
206 if (eventCurrentTool->m_toggleState)
207 state |= wxTBSTATE_CHECKED;
208 DrawTool(dc, eventCurrentTool, state);
209 eventCurrentTool = NULL;
210 }
211 if (m_currentTool > -1)
212 {
213 m_currentTool = -1;
214 OnMouseEnter(-1);
215 }
216 return;
217 }
218
219 if (!event.Dragging() && !event.IsButton())
220 {
221 if (tool->m_index != m_currentTool)
222 {
223 OnMouseEnter(tool->m_index);
224 m_currentTool = tool->m_index;
225 return;
226 }
227 }
228 if (event.Dragging() && tool->m_enabled)
229 {
230 if (eventCurrentTool)
231 {
232 // Might have dragged outside tool
233 if (eventCurrentTool != tool)
234 {
235 int state = wxTBSTATE_ENABLED;
236 if (tool->m_toggleState)
237 state |= wxTBSTATE_CHECKED;
238 DrawTool(dc, tool, state);
239 eventCurrentTool = NULL;
240 return;
241 }
242 }
243 else
244 {
245 if (tool && event.LeftIsDown() && tool->m_enabled)
246 {
247 eventCurrentTool = tool;
248 ::SetCapture((HWND) GetHWND());
249 int state = wxTBSTATE_ENABLED|wxTBSTATE_PRESSED;
250 if (tool->m_toggleState)
251 state |= wxTBSTATE_CHECKED;
252 DrawTool(dc, tool, state);
253 }
254 }
255 }
256 if (event.LeftDown() && tool->m_enabled)
257 {
258 eventCurrentTool = tool;
259 ::SetCapture((HWND) GetHWND());
260 int state = wxTBSTATE_ENABLED|wxTBSTATE_PRESSED;
261 if (tool->m_toggleState)
262 state |= wxTBSTATE_CHECKED;
263 DrawTool(dc, tool, state);
264 }
265 else if (event.LeftUp() && tool->m_enabled)
266 {
267 if (eventCurrentTool)
268 ::ReleaseCapture();
269 if (eventCurrentTool == tool)
270 {
271 if (tool->m_isToggle)
272 {
273 tool->m_toggleState = !tool->m_toggleState;
274 if (!OnLeftClick(tool->m_index, tool->m_toggleState))
275 {
276 tool->m_toggleState = !tool->m_toggleState;
277 }
278 int state = wxTBSTATE_ENABLED;
279 if (tool->m_toggleState)
280 state |= wxTBSTATE_CHECKED;
281 DrawTool(dc, tool, state);
282 }
283 else
284 {
285 int state = wxTBSTATE_ENABLED;
286 if (tool->m_toggleState)
287 state |= wxTBSTATE_CHECKED;
288 DrawTool(dc, tool, state);
289 OnLeftClick(tool->m_index, tool->m_toggleState);
290 }
291 }
292 eventCurrentTool = NULL;
293 }
294 else if (event.RightDown() && tool->m_enabled)
295 {
296 OnRightClick(tool->m_index, x, y);
297 }
298}
299
300// This function enables/disables a toolbar tool and redraws it.
301// If that would not be done, the enabling/disabling wouldn't be
302// visible on the screen.
debe6624 303void wxToolBarMSW::EnableTool(int toolIndex, bool enable)
2bda0e17
KB
304{
305 wxNode *node = m_tools.Find((long)toolIndex);
306 if (node)
307 {
308 wxClientDC dc(this);
309
310 // at first do the enabling/disabling in the base class
311 wxToolBarBase::EnableTool(toolIndex,enable);
312 // then calculate the state of the tool and draw it
313 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
314 int state = 0;
315 if(tool->m_toggleState) state |= wxTBSTATE_CHECKED;
316 if(tool->m_enabled) state |= wxTBSTATE_ENABLED;
317 // how can i access the PRESSED state???
318 DrawTool(dc, tool,state);
319 }
320}
321
322void wxToolBarMSW::DrawTool(wxDC& dc, wxToolBarTool *tool, int state)
323{
324 DrawButton(dc.GetHDC(), (int)tool->m_x, (int)tool->m_y, (int)tool->GetWidth(), (int)tool->GetHeight(), tool, state);
325}
326
327void wxToolBarMSW::DrawTool(wxDC& dc, wxMemoryDC& , wxToolBarTool *tool)
328{
329 int state = wxTBSTATE_ENABLED;
330 if (!tool->m_enabled)
331 state = 0;
332 if (tool->m_toggleState)
333 state |= wxTBSTATE_CHECKED;
334 DrawTool(dc, tool, state);
335}
336
337// If pushedBitmap is NULL, a reversed version of bitmap is
338// created and used as the pushed/toggled image.
339// If toggle is TRUE, the button toggles between the two states.
debe6624
JS
340wxToolBarTool *wxToolBarMSW::AddTool(int index, const wxBitmap& bitmap, const wxBitmap& pushedBitmap,
341 bool toggle, long xPos, long yPos, wxObject *clientData, const wxString& helpString1, const wxString& helpString2)
2bda0e17
KB
342{
343 // Using bitmap2 can cause problems (don't know why!)
344
345 // TODO: use the mapping code from wxToolBar95 to get it right in this class
346#if !defined(__WIN32__) && !defined(__WIN386__)
1e6d9499 347 wxBitmap bitmap2;
2bda0e17
KB
348 if (toggle)
349 {
1e6d9499 350 bitmap2.SetHBITMAP( (WXHBITMAP) CreateMappedBitmap(wxGetInstance(), (HBITMAP) ((wxBitmap& )bitmap).GetHBITMAP()));
2bda0e17
KB
351 }
352
1e6d9499 353 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, bitmap2, toggle, xPos, yPos, helpString1, helpString2);
2bda0e17 354#else
c0ed460c 355 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, wxNullBitmap, toggle, xPos, yPos, helpString1, helpString2);
2bda0e17
KB
356#endif
357
358 tool->m_clientData = clientData;
359
360 if (xPos > -1)
361 tool->m_x = xPos;
362 else
363 tool->m_x = m_xMargin;
364
365 if (yPos > -1)
366 tool->m_y = yPos;
367 else
368 tool->m_y = m_yMargin;
369
370 tool->m_deleteSecondBitmap = TRUE;
81d66cf3 371 tool->SetSize(GetToolSize().x, GetToolSize().y);
2bda0e17
KB
372
373 // Calculate reasonable max size in case Layout() not called
374 if ((tool->m_x + bitmap.GetWidth() + m_xMargin) > m_maxWidth)
375 m_maxWidth = (tool->m_x + tool->GetWidth() + m_xMargin);
376
377 if ((tool->m_y + bitmap.GetHeight() + m_yMargin) > m_maxHeight)
378 m_maxHeight = (tool->m_y + tool->GetHeight() + m_yMargin);
379
380 m_tools.Append((long)index, tool);
381 return tool;
382}
383
81d66cf3
JS
384void wxToolBarMSW::Layout(void)
385{
386 m_currentRowsOrColumns = 0;
387 m_lastX = m_xMargin;
388 m_lastY = m_yMargin;
389 int maxToolWidth = 0;
390 int maxToolHeight = 0;
391 m_maxWidth = 0;
392 m_maxHeight = 0;
393
394 // Find the maximum tool width and height
395 wxNode *node = m_tools.First();
396 while (node)
397 {
398 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
399 if (tool->GetWidth() > maxToolWidth)
400 maxToolWidth = (int)tool->GetWidth();
401 if (tool->GetHeight() > maxToolHeight)
402 maxToolHeight = (int)tool->GetHeight();
403 node = node->Next();
404 }
405
406 int separatorSize = m_toolSeparation;
407
408 node = m_tools.First();
409 while (node)
410 {
411 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
412 if (tool->m_toolStyle == wxTOOL_STYLE_SEPARATOR)
413 {
414 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
415 {
416 if (m_currentRowsOrColumns >= m_maxCols)
417 m_lastY += separatorSize;
418 else
419 m_lastX += separatorSize;
420 }
421 else
422 {
423 if (m_currentRowsOrColumns >= m_maxRows)
424 m_lastX += separatorSize;
425 else
426 m_lastY += separatorSize;
427 }
428 }
429 else if (tool->m_toolStyle == wxTOOL_STYLE_BUTTON)
430 {
431 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
432 {
433 if (m_currentRowsOrColumns >= m_maxCols)
434 {
435 m_currentRowsOrColumns = 0;
436 m_lastX = m_xMargin;
437 m_lastY += maxToolHeight + m_toolPacking;
438 }
439 tool->m_x = (long) (m_lastX + (maxToolWidth - tool->GetWidth())/2.0);
440 tool->m_y = (long) (m_lastY + (maxToolHeight - tool->GetHeight())/2.0);
441
442 m_lastX += maxToolWidth + m_toolPacking;
443 }
444 else
445 {
446 if (m_currentRowsOrColumns >= m_maxRows)
447 {
448 m_currentRowsOrColumns = 0;
449 m_lastX += (maxToolWidth + m_toolPacking);
450 m_lastY = m_yMargin;
451 }
452 tool->m_x = (long) (m_lastX + (maxToolWidth - tool->GetWidth())/2.0);
453 tool->m_y = (long) (m_lastY + (maxToolHeight - tool->GetHeight())/2.0);
454
455 m_lastY += maxToolHeight + m_toolPacking;
456 }
457 m_currentRowsOrColumns ++;
458 }
459
460 if (m_lastX > m_maxWidth)
461 m_maxWidth = m_lastX;
462 if (m_lastY > m_maxHeight)
463 m_maxHeight = m_lastY;
464
465 node = node->Next();
466 }
467 if ( GetWindowStyleFlag() & wxTB_HORIZONTAL )
468 m_maxWidth += maxToolWidth;
469 else
470 m_maxHeight += maxToolHeight;
471
472 m_maxWidth += m_xMargin;
473 m_maxHeight += m_yMargin;
474}
475
476
2bda0e17
KB
477bool 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
81d66cf3 487 m_hbmMono = (WXHBITMAP) CreateBitmap((int)GetToolSize().x, (int)GetToolSize().y, 1, 1, NULL);
2bda0e17
KB
488 if (!m_hbmMono)
489 return FALSE;
490
491 m_hbmDefault = (WXHBITMAP) SelectObject((HDC) m_hdcMono, (HBITMAP) m_hbmMono);
492 return TRUE;
493}
494
495void 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
515void 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
533void 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);
c4e7c2aa 542 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, hBitmap);
2bda0e17
KB
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);
81d66cf3 551 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
2bda0e17
KB
552 hdcGlyphs, 0, 0, SRCCOPY);
553 // convert this to 1's
554 SetBkColor(hdcGlyphs, m_rgbHilight);
555 // OR in the new 1's
81d66cf3 556 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
2bda0e17
KB
557 hdcGlyphs, 0, 0, SRCPAINT);
558
559 SelectObject(hdcGlyphs, bitmapOld);
560 DeleteObject(hBitmap);
561 DeleteDC(hdcGlyphs);
562}
563
564void 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
593void 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())
c4e7c2aa 631 bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap2.GetHBITMAP());
2bda0e17 632 else
c4e7c2aa 633 bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap1.GetHBITMAP());
2bda0e17 634#else
c4e7c2aa 635 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap1.GetHBITMAP());
2bda0e17
KB
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;
81d66cf3 641 xCenterOffset = (dxFace - (int)GetToolBitmapSize().x)/2;
2bda0e17
KB
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
81d66cf3 652 BitBlt((HDC) hdc, x+xCenterOffset, y + yOffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
2bda0e17
KB
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) {
c4e7c2aa 667 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
2bda0e17
KB
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) {
c4e7c2aa 680 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
2bda0e17
KB
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
c4e7c2aa 696 hbrOld = (HBRUSH) SelectObject((HDC) hdc, (HBRUSH) m_hbrDither);
2bda0e17
KB
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
716void 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
748WXHBITMAP 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
801bool 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
831bool wxToolBarMSW::FreeDitherBrush(void)
832{
833 if (m_hbrDither)
834 DeleteObject((HBRUSH) m_hbrDither);
835 m_hbrDither = 0;
836 return TRUE;
837}
838
839typedef 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
857WXHBITMAP 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) {
c4e7c2aa 920 hbmOld = (HBITMAP) SelectObject(hdcMem, hbm);
2bda0e17
KB
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
937WXHBITMAP 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