]> git.saurik.com Git - wxWidgets.git/blame - src/msw/tbar95.cpp
added datetime.h/cpp to filelist and regenerated the makefiles
[wxWidgets.git] / src / msw / tbar95.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
1c383dba 2// Name: msw/tbar95.cpp
2bda0e17
KB
3// Purpose: wxToolBar95
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
89b892a2 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
1c383dba
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
1c383dba 21 #pragma implementation "tbar95.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
1c383dba 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
1c383dba
VZ
32 #include "wx/log.h"
33 #include "wx/intl.h"
34 #include "wx/dynarray.h"
4e15f6c5 35 #include "wx/settings.h"
381dd4bf 36 #include "wx/bitmap.h"
2bda0e17
KB
37#endif
38
47d67540 39#if wxUSE_BUTTONBAR && wxUSE_TOOLBAR && defined(__WIN95__)
2bda0e17 40
ce3ed50d 41#if !defined(__GNUWIN32__) && !defined(__SALFORDC__)
1c383dba 42 #include "malloc.h"
2bda0e17
KB
43#endif
44
1c383dba 45#include "wx/msw/private.h"
2bda0e17 46
57c208c5 47#ifndef __TWIN32__
1c383dba
VZ
48
49#ifdef __GNUWIN32_OLD__
50 #include "wx/msw/gnuwin32/extra.h"
51#else
52 #include <commctrl.h>
65fd5cb0 53#endif
2bda0e17 54
1c383dba
VZ
55#endif // __TWIN32__
56
2bda0e17 57#include "wx/msw/dib.h"
c1dd939d 58#include "wx/msw/tbar95.h"
1c383dba
VZ
59#include "wx/app.h" // for GetComCtl32Version
60
61// ----------------------------------------------------------------------------
62// constants
63// ----------------------------------------------------------------------------
64
65// these standard constants are not always defined in compilers headers
2bda0e17 66
6a23cbce 67// Styles
bb6290e3 68#ifndef TBSTYLE_FLAT
1c383dba
VZ
69 #define TBSTYLE_LIST 0x1000
70 #define TBSTYLE_FLAT 0x0800
71 #define TBSTYLE_TRANSPARENT 0x8000
bb6290e3
JS
72#endif
73 // use TBSTYLE_TRANSPARENT if you use TBSTYLE_FLAT
74
6a23cbce
JS
75// Messages
76#ifndef TB_GETSTYLE
1c383dba
VZ
77 #define TB_GETSTYLE (WM_USER + 57)
78 #define TB_SETSTYLE (WM_USER + 56)
6a23cbce
JS
79#endif
80
1c383dba 81// these values correspond to those used by comctl32.dll
81d66cf3
JS
82#define DEFAULTBITMAPX 16
83#define DEFAULTBITMAPY 15
84#define DEFAULTBUTTONX 24
85#define DEFAULTBUTTONY 24
86#define DEFAULTBARHEIGHT 27
87
1c383dba
VZ
88// ----------------------------------------------------------------------------
89// function prototypes
90// ----------------------------------------------------------------------------
91
92static void wxMapBitmap(HBITMAP hBitmap, int width, int height);
93
94// ----------------------------------------------------------------------------
95// wxWin macros
96// ----------------------------------------------------------------------------
97
7c0ea335 98 IMPLEMENT_DYNAMIC_CLASS(wxToolBar, wxToolBarBase)
2bda0e17
KB
99
100BEGIN_EVENT_TABLE(wxToolBar95, wxToolBarBase)
89b892a2 101 EVT_MOUSE_EVENTS(wxToolBar95::OnMouseEvent)
2bda0e17
KB
102 EVT_SYS_COLOUR_CHANGED(wxToolBar95::OnSysColourChanged)
103END_EVENT_TABLE()
2bda0e17 104
1c383dba
VZ
105// ============================================================================
106// implementation
107// ============================================================================
2bda0e17 108
1c383dba
VZ
109// ----------------------------------------------------------------------------
110// wxToolBar95 construction
111// ----------------------------------------------------------------------------
112
113void wxToolBar95::Init()
2bda0e17 114{
1c383dba
VZ
115 m_maxWidth = -1;
116 m_maxHeight = -1;
117 m_hBitmap = 0;
118 m_defaultWidth = DEFAULTBITMAPX;
119 m_defaultHeight = DEFAULTBITMAPY;
2bda0e17
KB
120}
121
89b892a2
VZ
122bool wxToolBar95::Create(wxWindow *parent,
123 wxWindowID id,
124 const wxPoint& pos,
125 const wxSize& size,
126 long style,
127 const wxString& name)
2bda0e17 128{
1c383dba
VZ
129 wxASSERT_MSG( (style & wxTB_VERTICAL) == 0,
130 wxT("Sorry, wxToolBar95 under Windows 95 only "
131 "supports horizontal orientation.") );
edccf428 132
1c383dba
VZ
133 // common initialisation
134 if ( !CreateControl(parent, id, pos, size, style, name) )
135 return FALSE;
89b892a2 136
1c383dba
VZ
137 // prepare flags
138 DWORD msflags = 0; // WS_VISIBLE | WS_CHILD always included
139 if (style & wxBORDER)
140 msflags |= WS_BORDER;
141 msflags |= TBSTYLE_TOOLTIPS;
2bda0e17 142
1c383dba
VZ
143 if (style & wxTB_FLAT)
144 {
145 if (wxTheApp->GetComCtl32Version() > 400)
c8f1f088 146 msflags |= TBSTYLE_FLAT;
1c383dba 147 }
2bda0e17 148
1c383dba
VZ
149 // MSW-specific initialisation
150 if ( !wxControl::MSWCreateControl(TOOLBARCLASSNAME, msflags) )
151 return FALSE;
2bda0e17 152
c8f1f088 153 // toolbar-specific post initialisation
1c383dba 154 ::SendMessage(GetHwnd(), TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
89b892a2 155
c8f1f088
VZ
156 // set up the colors and fonts
157 wxRGBToColour(m_backgroundColour, GetSysColor(COLOR_BTNFACE));
158 m_foregroundColour = *wxBLACK;
159
160 SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
161
1c383dba
VZ
162 // position it
163 int x = pos.x;
164 int y = pos.y;
165 int width = size.x;
166 int height = size.y;
2bda0e17 167
1c383dba
VZ
168 if (width <= 0)
169 width = 100;
170 if (height <= 0)
171 height = m_defaultHeight;
172 if (x < 0)
173 x = 0;
174 if (y < 0)
175 y = 0;
bb6290e3 176
1c383dba 177 SetSize(x, y, width, height);
2bda0e17 178
1c383dba 179 return TRUE;
2bda0e17
KB
180}
181
89b892a2 182wxToolBar95::~wxToolBar95()
2bda0e17 183{
1c383dba 184 UnsubclassWin();
2bda0e17 185
1c383dba
VZ
186 if (m_hBitmap)
187 {
188 ::DeleteObject((HBITMAP) m_hBitmap);
189 }
190}
191
bdc72a22
VZ
192// ----------------------------------------------------------------------------
193// adding/removing buttons
194// ----------------------------------------------------------------------------
195
1c383dba
VZ
196void wxToolBar95::ClearTools()
197{
198 // TODO: Don't know how to reset the toolbar bitmap, as yet.
199 // But adding tools and calling CreateTools should probably
200 // recreate a buttonbar OK.
201 wxToolBarBase::ClearTools();
202}
203
bdc72a22
VZ
204bool wxToolBar95::DeleteTool(int id)
205{
206 int index = GetIndexFromId(id);
207 wxASSERT_MSG( index != wxNOT_FOUND, _T("invalid toolbar button id") );
208
209 if ( !SendMessage(GetHwnd(), TB_DELETEBUTTON, index, 0) )
210 {
211 wxLogLastError("TB_DELETEBUTTON");
212
213 return FALSE;
214 }
215
216 wxNode *node = m_tools.Nth(index);
217 delete (wxToolBarTool *)node->Data();
218 m_tools.DeleteNode(node);
219
220 m_ids.RemoveAt(index);
221
222 return TRUE;
223}
224
1c383dba
VZ
225bool wxToolBar95::AddControl(wxControl *control)
226{
227 wxCHECK_MSG( control, FALSE, _T("toolbar: can't insert NULL control") );
228
229 wxCHECK_MSG( control->GetParent() == this, FALSE,
230 _T("control must have toolbar as parent") );
231
232 wxToolBarTool *tool = new wxToolBarTool(control);
233
234 m_tools.Append(control->GetId(), tool);
bdc72a22 235 m_ids.Add(control->GetId());
1c383dba
VZ
236
237 return TRUE;
238}
239
240wxToolBarTool *wxToolBar95::AddTool(int index,
241 const wxBitmap& bitmap,
242 const wxBitmap& pushedBitmap,
243 bool toggle,
244 long xPos, long yPos,
245 wxObject *clientData,
246 const wxString& helpString1,
247 const wxString& helpString2)
248{
249 wxToolBarTool *tool = new wxToolBarTool(index, bitmap, wxNullBitmap,
250 toggle, xPos, yPos,
251 helpString1, helpString2);
252 tool->m_clientData = clientData;
253
254 if (xPos > -1)
255 tool->m_x = xPos;
256 else
257 tool->m_x = m_xMargin;
258
259 if (yPos > -1)
260 tool->m_y = yPos;
261 else
262 tool->m_y = m_yMargin;
263
264 tool->SetSize(GetToolSize().x, GetToolSize().y);
265
266 m_tools.Append((long)index, tool);
bdc72a22 267 m_ids.Add(index);
1c383dba
VZ
268
269 return tool;
2bda0e17
KB
270}
271
89b892a2 272bool wxToolBar95::CreateTools()
2bda0e17 273{
1c383dba
VZ
274 size_t nTools = m_tools.GetCount();
275 if ( nTools == 0 )
276 return FALSE;
2bda0e17 277
1c383dba 278 HBITMAP oldToolBarBitmap = (HBITMAP) m_hBitmap;
89b892a2 279
1c383dba
VZ
280 int totalBitmapWidth = (int)(m_defaultWidth * nTools);
281 int totalBitmapHeight = (int)m_defaultHeight;
2bda0e17 282
1c383dba
VZ
283 // Create a bitmap for all the tool bitmaps
284 HDC dc = ::GetDC(NULL);
285 m_hBitmap = (WXHBITMAP) ::CreateCompatibleBitmap(dc,
286 totalBitmapWidth,
287 totalBitmapHeight);
288 ::ReleaseDC(NULL, dc);
89b892a2 289
1c383dba
VZ
290 // Now blit all the tools onto this bitmap
291 HDC memoryDC = ::CreateCompatibleDC(NULL);
292 HBITMAP oldBitmap = (HBITMAP) ::SelectObject(memoryDC, (HBITMAP)m_hBitmap);
2bda0e17 293
1c383dba 294 HDC memoryDC2 = ::CreateCompatibleDC(NULL);
2bda0e17 295
1c383dba
VZ
296 // the button position
297 wxCoord x = 0;
2bda0e17 298
1c383dba
VZ
299 // the number of buttons (not separators)
300 int noButtons = 0;
301
302 wxNode *node = m_tools.First();
303 while (node)
051205e6 304 {
1c383dba
VZ
305 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
306 if ( tool->m_toolStyle == wxTOOL_STYLE_BUTTON && tool->m_bitmap1.Ok() )
307 {
308 HBITMAP hbmp = GetHbitmapOf(tool->m_bitmap1);
309 if ( hbmp )
310 {
311 HBITMAP oldBitmap2 = (HBITMAP)::SelectObject(memoryDC2, hbmp);
312 if ( !BitBlt(memoryDC, x, 0, m_defaultWidth, m_defaultHeight,
313 memoryDC2, 0, 0, SRCCOPY) )
314 {
315 wxLogLastError("BitBlt");
316 }
317
318 ::SelectObject(memoryDC2, oldBitmap2);
319
320 x += m_defaultWidth;
321 noButtons++;
322 }
323 }
324 node = node->Next();
051205e6 325 }
2bda0e17 326
1c383dba
VZ
327 ::SelectObject(memoryDC, oldBitmap);
328 ::DeleteDC(memoryDC);
329 ::DeleteDC(memoryDC2);
2bda0e17 330
1c383dba
VZ
331 // Map to system colours
332 wxMapBitmap((HBITMAP) m_hBitmap, totalBitmapWidth, totalBitmapHeight);
333
334 if ( oldToolBarBitmap )
2bda0e17 335 {
1c383dba
VZ
336 TBREPLACEBITMAP replaceBitmap;
337 replaceBitmap.hInstOld = NULL;
338 replaceBitmap.hInstNew = NULL;
339 replaceBitmap.nIDOld = (UINT) oldToolBarBitmap;
340 replaceBitmap.nIDNew = (UINT) (HBITMAP) m_hBitmap;
341 replaceBitmap.nButtons = noButtons;
342 if ( ::SendMessage(GetHwnd(), TB_REPLACEBITMAP,
343 0, (LPARAM) &replaceBitmap) == -1 )
344 {
345 wxFAIL_MSG(wxT("Could not add bitmap to toolbar"));
346 }
347
348 ::DeleteObject((HBITMAP) oldToolBarBitmap);
349
350 // Now delete all the buttons
351 int i = 0;
352 while ( TRUE )
353 {
354 // TODO: What about separators???? They don't have an id!
355 if ( ! ::SendMessage( GetHwnd(), TB_DELETEBUTTON, i, 0 ) )
356 break;
357 }
2bda0e17 358 }
1c383dba 359 else
051205e6 360 {
1c383dba
VZ
361 TBADDBITMAP addBitmap;
362 addBitmap.hInst = 0;
363 addBitmap.nID = (UINT)m_hBitmap;
364 if ( ::SendMessage(GetHwnd(), TB_ADDBITMAP,
365 (WPARAM) noButtons, (LPARAM)&addBitmap) == -1 )
366 {
367 wxFAIL_MSG(wxT("Could not add bitmap to toolbar"));
368 }
051205e6 369 }
2bda0e17 370
1c383dba
VZ
371 // Now add the buttons.
372 TBBUTTON *buttons = new TBBUTTON[nTools];
2bda0e17 373
1c383dba
VZ
374 // this array will holds the indices of all controls in the toolbar
375 wxArrayInt controlIds;
376
377 int i = 0;
378 int bitmapId = 0;
379
380 node = m_tools.First();
381 while (node)
2bda0e17 382 {
1c383dba
VZ
383 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
384 TBBUTTON& button = buttons[i];
385
386 wxZeroMemory(button);
387
388 switch ( tool->m_toolStyle )
389 {
390 case wxTOOL_STYLE_CONTROL:
391 controlIds.Add(i);
392 button.idCommand = tool->m_index;
393 // fall through: create just a separator too
394
395 case wxTOOL_STYLE_SEPARATOR:
396 button.fsState = TBSTATE_ENABLED;
397 button.fsStyle = TBSTYLE_SEP;
398 break;
399
400 case wxTOOL_STYLE_BUTTON:
401 button.iBitmap = bitmapId;
402 button.idCommand = tool->m_index;
403
404 if (tool->m_enabled)
405 button.fsState |= TBSTATE_ENABLED;
406 if (tool->m_toggleState)
407 button.fsState |= TBSTATE_CHECKED;
408 button.fsStyle = tool->m_isToggle ? TBSTYLE_CHECK
409 : TBSTYLE_BUTTON;
410
411 bitmapId++;
412 break;
413 }
2bda0e17 414
1c383dba
VZ
415 i++;
416 node = node->Next();
2bda0e17 417 }
1c383dba
VZ
418
419 if ( !::SendMessage(GetHwnd(), TB_ADDBUTTONS,
420 (WPARAM)i, (LPARAM)buttons) )
2bda0e17 421 {
1c383dba 422 wxLogLastError("TB_ADDBUTTONS");
2bda0e17 423 }
89b892a2 424
1c383dba 425 delete [] buttons;
2bda0e17 426
1c383dba
VZ
427 // adjust the controls size to fit nicely in the toolbar
428 size_t nControls = controlIds.GetCount();
429 for ( size_t nCtrl = 0; nCtrl < nControls; nCtrl++ )
430 {
431 wxToolBarTool *tool = (wxToolBarTool *)
432 m_tools.Nth(controlIds[nCtrl])->Data();
433 wxControl *control = tool->GetControl();
434
435 wxSize size = control->GetSize();
436
bdc72a22
VZ
437 // the position of the leftmost controls corner
438 int left = -1;
439
440 // TB_SETBUTTONINFO message is only supported by comctl32.dll 4.71+
441 #if defined(_WIN32_IE) && (_WIN32_IE >= 0x400 )
442 // available in headers, now check whether it is available now
443 // (during run-time)
444 if ( wxTheApp->GetComCtl32Version() >= 471 )
445 {
446 // set the (underlying) separators width to be that of the
447 // control
448 TBBUTTONINFO tbbi;
449 tbbi.cbSize = sizeof(tbbi);
450 tbbi.dwMask = TBIF_SIZE;
451 tbbi.cx = size.x;
452 if ( !SendMessage(GetHwnd(), TB_SETBUTTONINFO,
453 tool->m_index, (LPARAM)&tbbi) )
454 {
455 // the index is probably invalid
456 wxLogLastError("TB_SETBUTTONINFO");
457 }
458
459 }
460 else
461 #endif // comctl32.dll 4.71
462 // TB_SETBUTTONINFO unavailable
463 {
464 int index = GetIndexFromId(tool->m_index);
465 wxASSERT_MSG( index != wxNOT_FOUND,
466 _T("control wasn't added to the tbar?") );
467
468 // try adding several separators to fit the controls width
469 RECT r;
470 if ( !SendMessage(GetHwnd(), TB_GETRECT,
471 tool->m_index, (LPARAM)(LPRECT)&r) )
472 {
473 wxLogLastError("TB_GETITEMRECT");
474 }
475
476 int widthSep = r.right - r.left;
477 left = r.left;
478
479 TBBUTTON tbb;
480 wxZeroMemory(tbb);
481 tbb.idCommand = 0;
482 tbb.fsState = TBSTATE_ENABLED;
483 tbb.fsStyle = TBSTYLE_SEP;
484
485 size_t nSeparators = size.x / widthSep;
486 for ( size_t nSep = 0; nSep < nSeparators; nSep++ )
487 {
488 m_ids.Insert(0, (size_t)index);
489
490 if ( !SendMessage(GetHwnd(), TB_INSERTBUTTON,
491 index, (LPARAM)&tbb) )
492 {
493 wxLogLastError("TB_INSERTBUTTON");
494 }
495 }
496
497 // adjust the controls width to exactly cover the separators
498 control->SetSize((nSeparators + 1)*widthSep, -1);
499 }
1c383dba
VZ
500
501 // and position the control itself correctly vertically
502 RECT r;
c8f1f088
VZ
503 if ( !SendMessage(GetHwnd(), TB_GETRECT,
504 tool->m_index, (LPARAM)(LPRECT)&r) )
505 {
506 wxLogLastError("TB_GETRECT");
507 }
1c383dba
VZ
508
509 int height = r.bottom - r.top;
510 int diff = height - size.y;
511 if ( diff < 0 )
512 {
513 // the control is too high, resize to fit
514 control->SetSize(-1, height - 2);
515
516 diff = 2;
517 }
2bda0e17 518
bdc72a22 519 control->Move(left == -1 ? r.left : left, r.top + diff / 2);
1c383dba 520 }
89b892a2 521
1c383dba 522 (void)::SendMessage(GetHwnd(), TB_AUTOSIZE, (WPARAM)0, (LPARAM) 0);
89b892a2 523
1c383dba 524 SetRows(m_maxRows);
2bda0e17 525
1c383dba 526 return TRUE;
2bda0e17
KB
527}
528
1c383dba
VZ
529// ----------------------------------------------------------------------------
530// message handlers
531// ----------------------------------------------------------------------------
532
debe6624 533bool wxToolBar95::MSWCommand(WXUINT cmd, WXWORD id)
2bda0e17 534{
1c383dba
VZ
535 wxNode *node = m_tools.Find((long)id);
536 if (!node)
537 return FALSE;
538
539 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
540 if (tool->m_isToggle)
541 {
542 LRESULT state = ::SendMessage(GetHwnd(), TB_GETSTATE, id, 0);
543 tool->m_toggleState = state & TBSTATE_CHECKED;
544 }
545
546 BOOL ret = OnLeftClick((int)id, tool->m_toggleState);
547 if ( ret == FALSE && tool->m_isToggle )
548 {
549 tool->m_toggleState = !tool->m_toggleState;
550 ::SendMessage(GetHwnd(), TB_CHECKBUTTON,
551 (WPARAM)id, (LPARAM)MAKELONG(tool->m_toggleState, 0));
552 }
553
554 return TRUE;
2bda0e17
KB
555}
556
a23fd0e1 557bool wxToolBar95::MSWOnNotify(int WXUNUSED(idCtrl),
fd3f686c
VZ
558 WXLPARAM lParam,
559 WXLPARAM *result)
2bda0e17 560{
89b892a2 561 // First check if this applies to us
2bda0e17 562 NMHDR *hdr = (NMHDR *)lParam;
2bda0e17 563
1c383dba
VZ
564 // the tooltips control created by the toolbar is sometimes Unicode, even
565 // in an ANSI application - this seems to be a bug in comctl32.dll v5
a17e237f
VZ
566 int code = (int)hdr->code;
567 if ( (code != TTN_NEEDTEXTA) && (code != TTN_NEEDTEXTW) )
89b892a2 568 return FALSE;
2bda0e17 569
89b892a2
VZ
570 HWND toolTipWnd = (HWND)::SendMessage((HWND)GetHWND(), TB_GETTOOLTIPS, 0, 0);
571 if ( toolTipWnd != hdr->hwndFrom )
572 return FALSE;
2bda0e17 573
89b892a2
VZ
574 LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam;
575 int id = (int)ttText->hdr.idFrom;
576 wxNode *node = m_tools.Find((long)id);
577 if (!node)
578 return FALSE;
579
580 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
2bda0e17 581
8df13671
VZ
582 const wxString& help = tool->m_shortHelpString;
583
584 if ( !help.IsEmpty() )
89b892a2 585 {
a17e237f 586 if ( code == TTN_NEEDTEXTA )
89b892a2 587 {
837e5743 588 ttText->lpszText = (wxChar *)help.c_str();
89b892a2
VZ
589 }
590#if (_WIN32_IE >= 0x0300)
591 else
592 {
593 // FIXME this is a temp hack only until I understand better what
594 // must be done in both ANSI and Unicode builds
8df13671
VZ
595
596 size_t lenAnsi = help.Len();
b2cce0c4 597 #ifdef __MWERKS__
8df13671
VZ
598 // MetroWerks doesn't like calling mbstowcs with NULL argument
599 size_t lenUnicode = 2*lenAnsi;
b2cce0c4 600 #else
8df13671 601 size_t lenUnicode = mbstowcs(NULL, help, lenAnsi);
b2cce0c4 602 #endif
8df13671
VZ
603
604 // using the pointer of right type avoids us doing all sorts of
605 // pointer arithmetics ourselves
606 wchar_t *dst = (wchar_t *)ttText->szText,
607 *pwz = new wchar_t[lenUnicode + 1];
608 mbstowcs(pwz, help, lenAnsi + 1);
609 memcpy(dst, pwz, lenUnicode*sizeof(wchar_t));
610
611 // put the terminating _wide_ NUL
612 dst[lenUnicode] = 0;
89b892a2
VZ
613
614 delete [] pwz;
615 }
616#endif // _WIN32_IE >= 0x0300
2bda0e17 617 }
89b892a2
VZ
618
619 // For backward compatibility...
620 OnMouseEnter(tool->m_index);
621
622 return TRUE;
2bda0e17
KB
623}
624
1c383dba
VZ
625// ----------------------------------------------------------------------------
626// sizing stuff
627// ----------------------------------------------------------------------------
628
81d66cf3 629void wxToolBar95::SetToolBitmapSize(const wxSize& size)
2bda0e17 630{
1c383dba
VZ
631 wxToolBarBase::SetToolBitmapSize(size);
632
633 ::SendMessage(GetHwnd(), TB_SETBITMAPSIZE, 0, MAKELONG(size.x, size.y));
2bda0e17
KB
634}
635
debe6624 636void wxToolBar95::SetRows(int nRows)
2bda0e17 637{
1c383dba
VZ
638 // TRUE in wParam means to create at least as many rows
639 RECT rect;
640 ::SendMessage(GetHwnd(), TB_SETROWS,
641 MAKEWPARAM(nRows, TRUE), (LPARAM) &rect);
642
643 m_maxWidth = (rect.right - rect.left + 2);
644 m_maxHeight = (rect.bottom - rect.top + 2);
645
646 m_maxRows = nRows;
2bda0e17
KB
647}
648
89b892a2 649wxSize wxToolBar95::GetMaxSize() const
2bda0e17 650{
1c383dba
VZ
651 if ( (m_maxWidth == -1) || (m_maxHeight == -1) )
652 {
653 // it has a side effect of filling m_maxWidth/Height variables
654 ((wxToolBar95 *)this)->SetRows(m_maxRows); // const_cast
655 }
656
657 return wxSize(m_maxWidth, m_maxHeight);
2bda0e17
KB
658}
659
2bda0e17 660// The button size is bigger than the bitmap size
89b892a2 661wxSize wxToolBar95::GetToolSize() const
2bda0e17 662{
1c383dba
VZ
663 // FIXME: this is completely bogus (VZ)
664 return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
2bda0e17
KB
665}
666
1c383dba
VZ
667// ----------------------------------------------------------------------------
668// tool state
669// ----------------------------------------------------------------------------
670
debe6624 671void wxToolBar95::EnableTool(int toolIndex, bool enable)
2bda0e17 672{
1c383dba
VZ
673 wxNode *node = m_tools.Find((long)toolIndex);
674 if (node)
675 {
676 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
677 tool->m_enabled = enable;
678 ::SendMessage(GetHwnd(), TB_ENABLEBUTTON,
679 (WPARAM)toolIndex, (LPARAM)MAKELONG(enable, 0));
680 }
2bda0e17
KB
681}
682
debe6624 683void wxToolBar95::ToggleTool(int toolIndex, bool toggle)
2bda0e17 684{
1c383dba
VZ
685 wxNode *node = m_tools.Find((long)toolIndex);
686 if (node)
2bda0e17 687 {
1c383dba
VZ
688 wxToolBarTool *tool = (wxToolBarTool *)node->Data();
689 if (tool->m_isToggle)
690 {
691 tool->m_toggleState = toggle;
692 ::SendMessage(GetHwnd(), TB_CHECKBUTTON,
693 (WPARAM)toolIndex, (LPARAM)MAKELONG(toggle, 0));
694 }
2bda0e17 695 }
2bda0e17
KB
696}
697
088a95f5
JS
698bool wxToolBar95::GetToolState(int toolIndex) const
699{
bdc72a22
VZ
700 wxASSERT_MSG( GetIndexFromId(toolIndex) != wxNOT_FOUND,
701 _T("invalid toolbar button id") );
702
703 return ::SendMessage(GetHwnd(), TB_ISBUTTONCHECKED,
704 (WPARAM)toolIndex, (LPARAM)0) != 0;
2bda0e17
KB
705}
706
1c383dba
VZ
707// ----------------------------------------------------------------------------
708// event handlers
709// ----------------------------------------------------------------------------
2bda0e17
KB
710
711// Responds to colour changes, and passes event on to children.
712void wxToolBar95::OnSysColourChanged(wxSysColourChangedEvent& event)
713{
714 m_backgroundColour = wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)),
89b892a2 715 GetGValue(GetSysColor(COLOR_BTNFACE)), GetBValue(GetSysColor(COLOR_BTNFACE)));
2bda0e17
KB
716
717 // Remap the buttons
718 CreateTools();
719
2bda0e17
KB
720 Refresh();
721
722 // Propagate the event to the non-top-level children
723 wxWindow::OnSysColourChanged(event);
724}
725
e6460682
JS
726void wxToolBar95::OnMouseEvent(wxMouseEvent& event)
727{
728 if (event.RightDown())
729 {
730 // For now, we don't have an id. Later we could
731 // try finding the tool.
732 OnRightClick((int)-1, event.GetX(), event.GetY());
733 }
734 else
735 {
42e69d6b 736 event.Skip();
e6460682
JS
737 }
738}
739
bdc72a22
VZ
740
741// ----------------------------------------------------------------------------
742// helpers
743// ----------------------------------------------------------------------------
744
745int wxToolBar95::GetIndexFromId(int id) const
746{
747 size_t count = m_ids.GetCount();
748 for ( size_t n = 0; n < count; n++ )
749 {
750 if ( m_ids[n] == id )
751 return n;
752 }
753
754 return wxNOT_FOUND;
755}
756
1c383dba
VZ
757// ----------------------------------------------------------------------------
758// private functions
759// ----------------------------------------------------------------------------
760
bdc72a22
VZ
761// These are the default colors used to map the bitmap colors to the current
762// system colors. Note that they are in BGR format because this is what Windows
763// wants (and not RGB)
2bda0e17
KB
764
765#define BGR_BUTTONTEXT (RGB(000,000,000)) // black
766#define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey
767#define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey
768#define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white
ad81651f 769#define BGR_BACKGROUNDSEL (RGB(000,000,255)) // blue
2bda0e17
KB
770#define BGR_BACKGROUND (RGB(255,000,255)) // magenta
771
772void wxMapBitmap(HBITMAP hBitmap, int width, int height)
773{
1c383dba
VZ
774 COLORMAP ColorMap[] =
775 {
2bda0e17
KB
776 {BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black
777 {BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey
778 {BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey
779 {BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white
780 {BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue
781 {BGR_BACKGROUND, COLOR_WINDOW} // magenta
782 };
783
784 int NUM_MAPS = (sizeof(ColorMap)/sizeof(COLORMAP));
785 int n;
786 for ( n = 0; n < NUM_MAPS; n++)
787 {
788 ColorMap[n].to = ::GetSysColor(ColorMap[n].to);
789 }
790
791 HBITMAP hbmOld;
792 HDC hdcMem = CreateCompatibleDC(NULL);
793
794 if (hdcMem)
795 {
c4e7c2aa 796 hbmOld = (HBITMAP) SelectObject(hdcMem, hBitmap);
2bda0e17
KB
797
798 int i, j, k;
799 for ( i = 0; i < width; i++)
800 {
801 for ( j = 0; j < height; j++)
802 {
803 COLORREF pixel = ::GetPixel(hdcMem, i, j);
804/*
805 BYTE red = GetRValue(pixel);
806 BYTE green = GetGValue(pixel);
807 BYTE blue = GetBValue(pixel);
808*/
809
810 for ( k = 0; k < NUM_MAPS; k ++)
811 {
812 if ( ColorMap[k].from == pixel )
813 {
814 /* COLORREF actualPixel = */ ::SetPixel(hdcMem, i, j, ColorMap[k].to);
815 break;
816 }
817 }
818 }
819 }
820
821
822 SelectObject(hdcMem, hbmOld);
823 DeleteObject(hdcMem);
824 }
825
826}
827
828// Some experiments...
829#if 0
830 // What we want to do is create another bitmap which has a depth of 4,
831 // and set the bits. So probably we want to convert this HBITMAP into a
832 // DIB, then call SetDIBits.
833 // AAAGH. The stupid thing is that if newBitmap has a depth of 4 (less than that of
834 // the screen), then SetDIBits fails.
835 HBITMAP newBitmap = ::CreateBitmap(totalBitmapWidth, totalBitmapHeight, 1, 4, NULL);
836 HANDLE newDIB = ::BitmapToDIB((HBITMAP) m_hBitmap, NULL);
837 LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) GlobalLock(newDIB);
838
839 dc = ::GetDC(NULL);
840// LPBITMAPINFOHEADER lpbmi = (LPBITMAPINFOHEADER) newDIB;
841
842 int result = ::SetDIBits(dc, newBitmap, 0, lpbmi->biHeight, FindDIBBits((LPSTR)lpbmi), (LPBITMAPINFO)lpbmi,
843 DIB_PAL_COLORS);
844 DWORD err = GetLastError();
845
846 ::ReleaseDC(NULL, dc);
847
848 // Delete the DIB
849 GlobalUnlock (newDIB);
850 GlobalFree (newDIB);
851
852// WXHBITMAP hBitmap2 = wxCreateMappedBitmap((WXHINSTANCE) wxGetInstance(), (WXHBITMAP) m_hBitmap);
853 // Substitute our new bitmap for the old one
854 ::DeleteObject((HBITMAP) m_hBitmap);
855 m_hBitmap = (WXHBITMAP) newBitmap;
856#endif
857
858
1c383dba 859#endif // !(wxUSE_TOOLBAR && Win95)