]> git.saurik.com Git - wxWidgets.git/blame - src/msw/tbarmsw.cpp
More SC++ fixes; HelpGen starting to compile with VC++; image sample now compiles...
[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
KB
28
29#ifndef __GNUWIN32__
30#include "malloc.h"
31#endif
32
17dff81c 33#ifndef __MWERKS__
2bda0e17 34#include <memory.h>
17dff81c 35#endif
2bda0e17
KB
36#include <stdlib.h>
37
38#include "wx/tbarmsw.h"
2432b92d 39#include "wx/event.h"
2bda0e17 40#include "wx/app.h"
2432b92d 41#include "wx/bitmap.h"
2bda0e17
KB
42#include "wx/msw/private.h"
43#include "wx/msw/dib.h"
44
81d66cf3
JS
45#define DEFAULTBITMAPX 16
46#define DEFAULTBITMAPY 15
47#define DEFAULTBUTTONX 24
48#define DEFAULTBUTTONY 22
49#define DEFAULTBARHEIGHT 27
50
2bda0e17
KB
51/////// Non-Windows 95 implementation
52
f97c9854 53#if !wxUSE_IMAGE_LOADING_IN_MSW
47d67540 54#error If wxUSE_IMAGE_LOADING_IN_MSW is set to 0, then wxUSE_BUTTONBAR must be set to 0 too.
2bda0e17
KB
55#endif
56
57#if !USE_SHARED_LIBRARY
58IMPLEMENT_DYNAMIC_CLASS(wxToolBarMSW, wxToolBarBase)
59
60BEGIN_EVENT_TABLE(wxToolBarMSW, wxToolBarBase)
61 EVT_SIZE(wxToolBarMSW::OnSize)
62 EVT_PAINT(wxToolBarMSW::OnPaint)
63 EVT_MOUSE_EVENTS(wxToolBarMSW::OnMouseEvent)
64END_EVENT_TABLE()
65#endif
66
67wxToolBarMSW::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
debe6624 81bool wxToolBarMSW::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
81d66cf3 82 long style, const wxString& name)
2bda0e17
KB
83{
84 if ( ! wxWindow::Create(parent, id, pos, size, style, name) )
85 return FALSE;
86
81d66cf3 87 if ( style & wxTB_HORIZONTAL )
2bda0e17
KB
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
117wxToolBarMSW::~wxToolBarMSW(void)
118{
119 FreeGlobalObjects();
120}
121
81d66cf3 122void wxToolBarMSW::SetToolBitmapSize(const wxSize& size)
2bda0e17
KB
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
81d66cf3 130wxSize wxToolBarMSW::GetToolSize(void) const
2bda0e17
KB
131{
132 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
133}
134
135void 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
165void 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).
173void 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.
debe6624 302void wxToolBarMSW::EnableTool(int toolIndex, bool enable)
2bda0e17
KB
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
321void 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
326void 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.
debe6624
JS
339wxToolBarTool *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)
2bda0e17
KB
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__)
1e6d9499 346 wxBitmap bitmap2;
2bda0e17
KB
347 if (toggle)
348 {
1e6d9499 349 bitmap2.SetHBITMAP( (WXHBITMAP) CreateMappedBitmap(wxGetInstance(), (HBITMAP) ((wxBitmap& )bitmap).GetHBITMAP()));
2bda0e17
KB
350 }
351
1e6d9499 352 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, bitmap2, toggle, xPos, yPos, helpString1, helpString2);
2bda0e17 353#else
c0ed460c 354 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, wxNullBitmap, toggle, xPos, yPos, helpString1, helpString2);
2bda0e17
KB
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;
81d66cf3 370 tool->SetSize(GetToolSize().x, GetToolSize().y);
2bda0e17
KB
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
81d66cf3
JS
383void 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
2bda0e17
KB
476bool 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
81d66cf3 486 m_hbmMono = (WXHBITMAP) CreateBitmap((int)GetToolSize().x, (int)GetToolSize().y, 1, 1, NULL);
2bda0e17
KB
487 if (!m_hbmMono)
488 return FALSE;
489
490 m_hbmDefault = (WXHBITMAP) SelectObject((HDC) m_hdcMono, (HBITMAP) m_hbmMono);
491 return TRUE;
492}
493
494void 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
514void 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
532void 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);
c4e7c2aa 541 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, hBitmap);
2bda0e17
KB
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);
81d66cf3 550 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
2bda0e17
KB
551 hdcGlyphs, 0, 0, SRCCOPY);
552 // convert this to 1's
553 SetBkColor(hdcGlyphs, m_rgbHilight);
554 // OR in the new 1's
81d66cf3 555 BitBlt((HDC) m_hdcMono, xoffset, yoffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
2bda0e17
KB
556 hdcGlyphs, 0, 0, SRCPAINT);
557
558 SelectObject(hdcGlyphs, bitmapOld);
559 DeleteObject(hBitmap);
560 DeleteDC(hdcGlyphs);
561}
562
563void 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
592void 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())
c4e7c2aa 630 bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap2.GetHBITMAP());
2bda0e17 631 else
c4e7c2aa 632 bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap1.GetHBITMAP());
2bda0e17 633#else
c4e7c2aa 634 HBITMAP bitmapOld = (HBITMAP) SelectObject(hdcGlyphs, (HBITMAP) tool->m_bitmap1.GetHBITMAP());
2bda0e17
KB
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;
81d66cf3 640 xCenterOffset = (dxFace - (int)GetToolBitmapSize().x)/2;
2bda0e17
KB
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
81d66cf3 651 BitBlt((HDC) hdc, x+xCenterOffset, y + yOffset, (int)GetToolBitmapSize().x, (int)GetToolBitmapSize().y,
2bda0e17
KB
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) {
c4e7c2aa 666 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
2bda0e17
KB
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) {
c4e7c2aa 679 hbrOld = (HBRUSH) SelectObject((HDC) hdc, hbr);
2bda0e17
KB
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
c4e7c2aa 695 hbrOld = (HBRUSH) SelectObject((HDC) hdc, (HBRUSH) m_hbrDither);
2bda0e17
KB
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
715void 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
747WXHBITMAP 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
800bool 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
830bool wxToolBarMSW::FreeDitherBrush(void)
831{
832 if (m_hbrDither)
833 DeleteObject((HBRUSH) m_hbrDither);
834 m_hbrDither = 0;
835 return TRUE;
836}
837
838typedef 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
856WXHBITMAP 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) {
c4e7c2aa 919 hbmOld = (HBITMAP) SelectObject(hdcMem, hbm);
2bda0e17
KB
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
936WXHBITMAP 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