]> git.saurik.com Git - wxWidgets.git/blame - src/msw/tabctrl.cpp
handle NULL BSTRs as empty ones per Microsoft convention
[wxWidgets.git] / src / msw / tabctrl.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
8ecd5de2 2// Name: src/msw/tabctrl.cpp
2bda0e17
KB
3// Purpose: wxTabCtrl
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
2bda0e17
KB
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
670f9935 16 #pragma hdrstop
2bda0e17
KB
17#endif
18
db6d3918
VZ
19#if wxUSE_TAB_DIALOG
20
2bda0e17 21#ifndef WX_PRECOMP
57bd4c60 22 #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
670f9935
WS
23 #include "wx/wx.h"
24 #include "wx/app.h"
2bda0e17
KB
25#endif
26
4676948b 27#include "wx/msw/private.h"
2bda0e17 28
186ef90c 29#include "wx/tabctrl.h"
2bda0e17
KB
30#include "wx/msw/imaglist.h"
31
2bda0e17 32IMPLEMENT_DYNAMIC_CLASS(wxTabCtrl, wxControl)
2b5f62a0 33IMPLEMENT_DYNAMIC_CLASS(wxTabEvent, wxNotifyEvent)
2bda0e17 34
2e4df4bf
VZ
35DEFINE_EVENT_TYPE(wxEVT_COMMAND_TAB_SEL_CHANGED)
36DEFINE_EVENT_TYPE(wxEVT_COMMAND_TAB_SEL_CHANGING)
37
2bda0e17 38BEGIN_EVENT_TABLE(wxTabCtrl, wxControl)
2bda0e17
KB
39 EVT_SYS_COLOUR_CHANGED(wxTabCtrl::OnSysColourChanged)
40END_EVENT_TABLE()
2bda0e17 41
ee4f8c2a 42wxTabCtrl::wxTabCtrl()
2bda0e17
KB
43{
44 m_imageList = NULL;
45}
46
ee4f8c2a
JS
47bool wxTabCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
48 long style, const wxString& name)
2bda0e17
KB
49{
50 m_imageList = NULL;
51
52 m_backgroundColour = wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)),
42e69d6b 53 GetGValue(GetSysColor(COLOR_BTNFACE)), GetBValue(GetSysColor(COLOR_BTNFACE)));
2bda0e17
KB
54 m_foregroundColour = *wxBLACK ;
55
2bda0e17
KB
56 SetName(name);
57
58 int x = pos.x;
59 int y = pos.y;
60 int width = size.x;
61 int height = size.y;
62
63 m_windowStyle = style;
64
2bda0e17
KB
65 SetParent(parent);
66
2bda0e17
KB
67 if (width <= 0)
68 width = 100;
69 if (height <= 0)
70 height = 30;
71 if (x < 0)
72 x = 0;
73 if (y < 0)
74 y = 0;
75
76 m_windowId = (id < 0 ? NewControlId() : id);
77
96df9ed9 78 long tabStyle = WS_CHILD | WS_VISIBLE;
2bda0e17
KB
79 if (m_windowStyle & wxTC_MULTILINE)
80 tabStyle |= TCS_MULTILINE;
81 if (m_windowStyle & wxTC_RIGHTJUSTIFY)
82 tabStyle |= TCS_RIGHTJUSTIFY;
83 if (m_windowStyle & wxTC_FIXEDWIDTH)
84 tabStyle |= TCS_FIXEDWIDTH;
85 if (m_windowStyle & wxTC_OWNERDRAW)
86 tabStyle |= TCS_OWNERDRAWFIXED;
2b5f62a0
VZ
87 if (m_windowStyle & wxBORDER)
88 tabStyle |= WS_BORDER;
2bda0e17 89
4676948b 90#ifndef __WXWINCE__
2bda0e17 91 tabStyle |= TCS_TOOLTIPS;
4676948b 92#endif
2bda0e17
KB
93
94 // Create the toolbar control.
95 HWND hWndTabCtrl = CreateWindowEx(0L, // No extended styles.
96 WC_TABCONTROL, // Class name for the tab control
fda7962d 97 wxEmptyString, // No default text.
2b5f62a0 98 tabStyle, // Styles and defaults.
2bda0e17
KB
99 x, y, width, height, // Standard size and position.
100 (HWND) parent->GetHWND(), // Parent window
101 (HMENU)m_windowId, // ID.
102 wxGetInstance(), // Current instance.
103 NULL ); // No class data.
104
105 m_hWnd = (WXHWND) hWndTabCtrl;
106 if (parent) parent->AddChild(this);
bfbb0b4c 107
2bda0e17
KB
108 SubclassWin((WXHWND) hWndTabCtrl);
109
2b5f62a0
VZ
110 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
111
bfbb0b4c 112 return true;
2bda0e17
KB
113}
114
ee4f8c2a 115wxTabCtrl::~wxTabCtrl()
2bda0e17
KB
116{
117 UnsubclassWin();
118}
119
a23fd0e1 120bool wxTabCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
2bda0e17 121{
42e69d6b 122 wxTabEvent event(wxEVT_NULL, m_windowId);
5cb598ae 123 wxEventType eventType wxDUMMY_INITIALIZE(wxEVT_NULL);
42e69d6b
VZ
124 NMHDR* hdr1 = (NMHDR*) lParam;
125 switch ( hdr1->code )
126 {
127 case TCN_SELCHANGE:
128 eventType = wxEVT_COMMAND_TAB_SEL_CHANGED;
129 break;
130
131 case TCN_SELCHANGING:
132 eventType = wxEVT_COMMAND_TAB_SEL_CHANGING;
133 break;
fd3f686c 134
4676948b 135#ifndef __WXWINCE__
2bda0e17
KB
136 case TTN_NEEDTEXT:
137 {
138 // TODO
f31a4098 139// if (!tool->m_shortHelpString.empty())
2bda0e17 140// ttText->lpszText = (char *) (const char *)tool->m_shortHelpString;
2bda0e17 141 }
4676948b 142#endif
42e69d6b
VZ
143 default :
144 return wxControl::MSWOnNotify(idCtrl, lParam, result);
145 }
2bda0e17 146
42e69d6b
VZ
147 event.SetEventObject( this );
148 event.SetEventType(eventType);
149 event.SetInt(idCtrl) ;
2b5f62a0 150 event.SetSelection(idCtrl);
2bda0e17 151
eafd76b0 152 return GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
153}
154
155// Responds to colour changes, and passes event on to children.
156void wxTabCtrl::OnSysColourChanged(wxSysColourChangedEvent& event)
157{
158 m_backgroundColour = wxColour(GetRValue(GetSysColor(COLOR_BTNFACE)),
42e69d6b
VZ
159 GetGValue(GetSysColor(COLOR_BTNFACE)),
160 GetBValue(GetSysColor(COLOR_BTNFACE)));
2bda0e17
KB
161
162 Refresh();
163
164 // Propagate the event to the non-top-level children
165 wxWindow::OnSysColourChanged(event);
166}
167
168// Delete all items
ee4f8c2a 169bool wxTabCtrl::DeleteAllItems()
2bda0e17
KB
170{
171 return ( TabCtrl_DeleteAllItems( (HWND) GetHWND() ) != FALSE );
172}
173
174// Delete an item
ee4f8c2a 175bool wxTabCtrl::DeleteItem(int item)
2bda0e17
KB
176{
177 return ( TabCtrl_DeleteItem( (HWND) GetHWND(), item) != FALSE );
178}
179
180// Get the selection
ee4f8c2a 181int wxTabCtrl::GetSelection() const
2bda0e17
KB
182{
183 return (int) TabCtrl_GetCurSel( (HWND) GetHWND() );
184}
185
da87a1ca
JS
186// Get the tab with the current keyboard focus
187int wxTabCtrl::GetCurFocus() const
188{
189 return (int) TabCtrl_GetCurFocus( (HWND) GetHWND() );
190}
191
2bda0e17 192// Get the associated image list
ee4f8c2a 193wxImageList* wxTabCtrl::GetImageList() const
2bda0e17
KB
194{
195 return m_imageList;
196}
197
198// Get the number of items
ee4f8c2a 199int wxTabCtrl::GetItemCount() const
2bda0e17
KB
200{
201 return (int) TabCtrl_GetItemCount( (HWND) GetHWND() );
202}
203
204// Get the rect corresponding to the tab
ee4f8c2a 205bool wxTabCtrl::GetItemRect(int item, wxRect& wxrect) const
2bda0e17
KB
206{
207 RECT rect;
208 if ( !TabCtrl_GetItemRect( (HWND) GetHWND(), item, & rect) )
bfbb0b4c 209 return false;
2bda0e17
KB
210 else
211 {
212 wxrect.x = rect.left; wxrect.y = rect.top;
213 wxrect.width = rect.right - rect.left;
214 wxrect.height = rect.bottom - rect.top;
bfbb0b4c 215 return true;
2bda0e17
KB
216 }
217}
218
219// Get the number of rows
ee4f8c2a 220int wxTabCtrl::GetRowCount() const
2bda0e17
KB
221{
222 return (int) TabCtrl_GetRowCount( (HWND) GetHWND() );
223}
224
225// Get the item text
ee4f8c2a 226wxString wxTabCtrl::GetItemText(int item) const
2bda0e17 227{
837e5743 228 wxChar buf[256];
fda7962d 229 wxString str(wxEmptyString);
2bda0e17
KB
230 TC_ITEM tcItem;
231 tcItem.mask = TCIF_TEXT;
232 tcItem.pszText = buf;
233 tcItem.cchTextMax = 256;
234
235 if (TabCtrl_GetItem( (HWND) GetHWND(), item, & tcItem) )
236 str = tcItem.pszText;
237
238 return str;
239}
240
241// Get the item image
ee4f8c2a 242int wxTabCtrl::GetItemImage(int item) const
2bda0e17
KB
243{
244 TC_ITEM tcItem;
245 tcItem.mask = TCIF_IMAGE;
246
247 if (TabCtrl_GetItem( (HWND) GetHWND(), item, & tcItem) )
248 return tcItem.iImage;
249 else
250 return -1;
251}
252
253// Get the item data
ee4f8c2a 254void* wxTabCtrl::GetItemData(int item) const
2bda0e17
KB
255{
256 TC_ITEM tcItem;
257 tcItem.mask = TCIF_PARAM;
258
259 if (TabCtrl_GetItem( (HWND) GetHWND(), item, & tcItem) )
260 return (void*) tcItem.lParam;
261 else
262 return 0;
263}
264
265// Hit test
266int wxTabCtrl::HitTest(const wxPoint& pt, long& flags)
267{
268 TC_HITTESTINFO hitTestInfo;
269 hitTestInfo.pt.x = pt.x;
270 hitTestInfo.pt.y = pt.y;
271 int item = TabCtrl_HitTest( (HWND) GetHWND(), & hitTestInfo ) ;
272 flags = 0;
273
274 if ((hitTestInfo.flags & TCHT_NOWHERE) == TCHT_NOWHERE)
275 flags |= wxTAB_HITTEST_NOWHERE;
276 if ((hitTestInfo.flags & TCHT_ONITEMICON) == TCHT_ONITEMICON)
277 flags |= wxTAB_HITTEST_ONICON;
278 if ((hitTestInfo.flags & TCHT_ONITEMLABEL) == TCHT_ONITEMLABEL)
279 flags |= wxTAB_HITTEST_ONLABEL;
280
281 return item;
282}
283
284// Insert an item
ee4f8c2a 285bool wxTabCtrl::InsertItem(int item, const wxString& text, int imageId, void* data)
2bda0e17 286{
837e5743 287 wxChar buf[256];
2bda0e17
KB
288 TC_ITEM tcItem;
289 tcItem.mask = TCIF_PARAM;
290 tcItem.lParam = (long) data;
489f6cf7 291 if (!text.empty())
2bda0e17
KB
292 {
293 tcItem.mask |= TCIF_TEXT;
837e5743 294 wxStrcpy(buf, (const wxChar*) text);
2bda0e17
KB
295 tcItem.pszText = buf;
296 tcItem.cchTextMax = 256;
297 }
298 if (imageId != -1)
299 {
300 tcItem.mask |= TCIF_IMAGE;
301 tcItem.iImage = imageId;
302 }
303
ee4f8c2a 304 return (TabCtrl_InsertItem( (HWND) GetHWND(), item, & tcItem) != -1);
2bda0e17
KB
305}
306
307// Set the selection
ee4f8c2a 308int wxTabCtrl::SetSelection(int item)
2bda0e17
KB
309{
310 return (int) TabCtrl_SetCurSel( (HWND) GetHWND(), item );
311}
312
313// Set the image list
314void wxTabCtrl::SetImageList(wxImageList* imageList)
315{
316 m_imageList = imageList;
8ecd5de2 317 (void) TabCtrl_SetImageList( (HWND) GetHWND(), (HIMAGELIST) imageList->GetHIMAGELIST() );
2bda0e17
KB
318}
319
320// Set the text for an item
ee4f8c2a 321bool wxTabCtrl::SetItemText(int item, const wxString& text)
2bda0e17 322{
837e5743 323 wxChar buf[256];
2bda0e17
KB
324 TC_ITEM tcItem;
325 tcItem.mask = TCIF_TEXT;
837e5743 326 wxStrcpy(buf, (const wxChar*) text);
2bda0e17
KB
327 tcItem.pszText = buf;
328 tcItem.cchTextMax = 256;
329
330 return ( TabCtrl_SetItem( (HWND) GetHWND(), item, & tcItem) != 0 );
331}
332
333// Set the image for an item
ee4f8c2a 334bool wxTabCtrl::SetItemImage(int item, int image)
2bda0e17
KB
335{
336 TC_ITEM tcItem;
337 tcItem.mask = TCIF_IMAGE;
338 tcItem.iImage = image;
339
340 return ( TabCtrl_SetItem( (HWND) GetHWND(), item, & tcItem) != 0 );
341}
342
343// Set the data for an item
ee4f8c2a 344bool wxTabCtrl::SetItemData(int item, void* data)
2bda0e17
KB
345{
346 TC_ITEM tcItem;
347 tcItem.mask = TCIF_PARAM;
348 tcItem.lParam = (long) data;
349
350 return ( TabCtrl_SetItem( (HWND) GetHWND(), item, & tcItem) != 0 );
351}
352
353// Set the size for a fixed-width tab control
354void wxTabCtrl::SetItemSize(const wxSize& size)
355{
356 TabCtrl_SetItemSize( (HWND) GetHWND(), size.x, size.y );
357}
358
359// Set the padding between tabs
360void wxTabCtrl::SetPadding(const wxSize& padding)
361{
362 TabCtrl_SetPadding( (HWND) GetHWND(), padding.x, padding.y );
363}
364
365#if 0
366// These are the default colors used to map the bitmap colors
367// to the current system colors
368
369#define BGR_BUTTONTEXT (RGB(000,000,000)) // black
370#define BGR_BUTTONSHADOW (RGB(128,128,128)) // dark grey
371#define BGR_BUTTONFACE (RGB(192,192,192)) // bright grey
372#define BGR_BUTTONHILIGHT (RGB(255,255,255)) // white
373#define BGR_BACKGROUNDSEL (RGB(255,000,000)) // blue
374#define BGR_BACKGROUND (RGB(255,000,255)) // magenta
375
376void wxMapBitmap(HBITMAP hBitmap, int width, int height)
377{
378 COLORMAP ColorMap[] = {
379 {BGR_BUTTONTEXT, COLOR_BTNTEXT}, // black
380 {BGR_BUTTONSHADOW, COLOR_BTNSHADOW}, // dark grey
381 {BGR_BUTTONFACE, COLOR_BTNFACE}, // bright grey
382 {BGR_BUTTONHILIGHT, COLOR_BTNHIGHLIGHT},// white
383 {BGR_BACKGROUNDSEL, COLOR_HIGHLIGHT}, // blue
384 {BGR_BACKGROUND, COLOR_WINDOW} // magenta
385 };
386
387 int NUM_MAPS = (sizeof(ColorMap)/sizeof(COLORMAP));
388 int n;
389 for ( n = 0; n < NUM_MAPS; n++)
390 {
391 ColorMap[n].to = ::GetSysColor(ColorMap[n].to);
392 }
393
394 HBITMAP hbmOld;
395 HDC hdcMem = CreateCompatibleDC(NULL);
396
397 if (hdcMem)
398 {
399 hbmOld = SelectObject(hdcMem, hBitmap);
400
401 int i, j, k;
402 for ( i = 0; i < width; i++)
403 {
404 for ( j = 0; j < height; j++)
405 {
406 COLORREF pixel = ::GetPixel(hdcMem, i, j);
407/*
408 BYTE red = GetRValue(pixel);
409 BYTE green = GetGValue(pixel);
410 BYTE blue = GetBValue(pixel);
411*/
412
413 for ( k = 0; k < NUM_MAPS; k ++)
414 {
415 if ( ColorMap[k].from == pixel )
416 {
417 /* COLORREF actualPixel = */ ::SetPixel(hdcMem, i, j, ColorMap[k].to);
418 break;
419 }
420 }
421 }
422 }
423
424
425 SelectObject(hdcMem, hbmOld);
426 DeleteObject(hdcMem);
427 }
428
429}
430#endif
db6d3918
VZ
431
432#endif // wxUSE_TAB_DIALOG