]> git.saurik.com Git - wxWidgets.git/blame - src/msw/listctrl.cpp
Changed the "delete win" to the more proper "win->Destroy()" in
[wxWidgets.git] / src / msw / listctrl.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: listctrl.cpp
3// Purpose: wxListCtrl
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
acb62b84 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "listctrl.h"
14#endif
15
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20#pragma hdrstop
21#endif
22
23#ifndef WX_PRECOMP
24#include "wx.h"
25#endif
26
27#if defined(__WIN95__)
28
29#include "wx/listctrl.h"
f8352807 30#include "wx/log.h"
2bda0e17
KB
31
32#include "wx/msw/private.h"
33
34#ifndef __GNUWIN32__
35#include <commctrl.h>
36#endif
37
38#ifdef __GNUWIN32__
39#include "wx/msw/gnuwin32/extra.h"
40#endif
41
42static void wxConvertToMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& tvItem);
43static void wxConvertFromMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& tvItem, HWND getFullInfo = 0);
44
45#if !USE_SHARED_LIBRARY
46IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
47IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
48
49#endif
50
51wxListCtrl::wxListCtrl(void)
52{
acb62b84
VZ
53 m_imageListNormal = NULL;
54 m_imageListSmall = NULL;
55 m_imageListState = NULL;
56 m_baseStyle = 0;
2bda0e17 57 m_colCount = 0;
bbcdf8bc 58 m_textCtrl = NULL;
2bda0e17
KB
59}
60
debe6624
JS
61bool wxListCtrl::Create(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
62 long style, const wxValidator& validator, const wxString& name)
2bda0e17
KB
63{
64 m_imageListNormal = NULL;
65 m_imageListSmall = NULL;
66 m_imageListState = NULL;
bbcdf8bc 67 m_textCtrl = NULL;
2bda0e17
KB
68 m_colCount = 0;
69
2bda0e17
KB
70 SetValidator(validator);
71 SetName(name);
72
73 int x = pos.x;
74 int y = pos.y;
75 int width = size.x;
76 int height = size.y;
77
78 m_windowStyle = style;
79
80 SetParent(parent);
81
82 if (width <= 0)
83 width = 100;
84 if (height <= 0)
85 height = 30;
86 if (x < 0)
87 x = 0;
88 if (y < 0)
89 y = 0;
90
91 m_windowId = (id == -1) ? NewControlId() : id;
92
93 DWORD wstyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP;
94
95 bool want3D;
96 WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ;
97
98 // Even with extended styles, need to combine with WS_BORDER
99 // for them to look right.
c085e333 100 if ( want3D || wxStyleHasBorder(m_windowStyle) )
2bda0e17
KB
101 wstyle |= WS_BORDER;
102
103 wstyle |= LVS_SHAREIMAGELISTS;
104 m_baseStyle = wstyle;
105
106 long oldStyle = 0; // Dummy
107 wstyle |= ConvertToMSWStyle(oldStyle, m_windowStyle);
108
109 // Create the ListView control.
f8352807 110 m_hWnd = (WXHWND)CreateWindowEx(exStyle,
2bda0e17
KB
111 WC_LISTVIEW,
112 "",
113 wstyle,
114 x, y, width, height,
115 (HWND) parent->GetHWND(),
116 (HMENU)m_windowId,
117 wxGetInstance(),
f8352807
VZ
118 NULL);
119
120 if ( !m_hWnd ) {
121 wxLogError("Can't create list control window.");
122
123 return FALSE;
124 }
125
126 wxSystemSettings settings;
127 SetBackgroundColour(settings.GetSystemColour(wxSYS_COLOUR_WINDOW));
fd71308f 128 SetForegroundColour(parent->GetForegroundColour());
2bda0e17 129
2bda0e17
KB
130 if (parent) parent->AddChild(this);
131
132 SubclassWin((WXHWND) m_hWnd);
133
134 return TRUE;
135}
136
137wxListCtrl::~wxListCtrl(void)
138{
bbcdf8bc
JS
139 if (m_textCtrl)
140 {
141 m_textCtrl->UnsubclassWin();
142 m_textCtrl->SetHWND(0);
143 delete m_textCtrl;
144 m_textCtrl = NULL;
145 }
2bda0e17
KB
146}
147
148// Add or remove a single window style
debe6624 149void wxListCtrl::SetSingleStyle(long style, bool add)
2bda0e17 150{
acb62b84
VZ
151 long flag = GetWindowStyleFlag();
152
153 // Get rid of conflicting styles
154 if ( add )
155 {
156 if ( style & wxLC_MASK_TYPE)
157 flag = flag & ~wxLC_MASK_TYPE ;
158 if ( style & wxLC_MASK_ALIGN )
159 flag = flag & ~wxLC_MASK_ALIGN ;
160 if ( style & wxLC_MASK_SORT )
161 flag = flag & ~wxLC_MASK_SORT ;
2bda0e17
KB
162 }
163
acb62b84
VZ
164 if ( flag & style )
165 {
166 if ( !add )
167 flag -= style;
168 }
169 else
170 {
171 if ( add )
172 {
173 flag |= style;
174 }
175 }
2bda0e17 176
acb62b84 177 m_windowStyle = flag;
2bda0e17 178
acb62b84 179 RecreateWindow();
2bda0e17
KB
180}
181
182// Set the whole window style
debe6624 183void wxListCtrl::SetWindowStyleFlag(long flag)
2bda0e17 184{
acb62b84 185 m_windowStyle = flag;
2bda0e17 186
acb62b84 187 RecreateWindow();
2bda0e17
KB
188}
189
190void wxListCtrl::RecreateWindow(void)
191{
acb62b84
VZ
192 if ( GetHWND() )
193 {
194 long oldStyle = 0;
2bda0e17 195 long style = ConvertToMSWStyle(oldStyle, m_windowStyle);
acb62b84 196 style |= m_baseStyle;
2bda0e17
KB
197// ::SetWindowLong((HWND) GetHWND(), GWL_STYLE, style);
198
199 // The following recreation of the window appears to be necessary
acb62b84 200 // because SetWindowLong doesn't seem to do it.
2bda0e17
KB
201
202 int x, y, width, height;
203 GetPosition(&x, &y);
204 GetSize(&width, &height);
205
206 UnsubclassWin();
207 ::DestroyWindow((HWND) GetHWND());
208
209 // Experimental
210 // Recreate the ListView control: unfortunately I can't
acb62b84 211 // make it work by using SetWindowLong.
2bda0e17
KB
212 bool want3D;
213 WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ;
214 HWND hWndListControl = CreateWindowEx(exStyle,
215 WC_LISTVIEW,
216 "",
217 style,
218 x, y, width, height,
219 (HWND) GetParent()->GetHWND(),
220 (HMENU)m_windowId,
221 wxGetInstance(),
222 NULL );
223
224 m_hWnd = (WXHWND) hWndListControl;
225 SubclassWin((WXHWND) m_hWnd);
226
227 if ( m_imageListNormal )
acb62b84 228 SetImageList(m_imageListNormal, wxIMAGE_LIST_NORMAL);
2bda0e17 229 if ( m_imageListSmall )
acb62b84 230 SetImageList(m_imageListSmall, wxIMAGE_LIST_SMALL);
2bda0e17 231 if ( m_imageListState )
acb62b84
VZ
232 SetImageList(m_imageListState, wxIMAGE_LIST_STATE);
233 }
2bda0e17
KB
234}
235
236// Can be just a single style, or a bitlist
debe6624 237long wxListCtrl::ConvertToMSWStyle(long& oldStyle, long style) const
2bda0e17
KB
238{
239 long wstyle = 0;
240 if ( style & wxLC_ICON )
241 {
acb62b84
VZ
242 if ( (oldStyle & LVS_TYPEMASK) == LVS_SMALLICON )
243 oldStyle -= LVS_SMALLICON;
244 if ( (oldStyle & LVS_TYPEMASK) == LVS_REPORT )
245 oldStyle -= LVS_REPORT;
246 if ( (oldStyle & LVS_TYPEMASK) == LVS_LIST )
247 oldStyle -= LVS_LIST;
248 wstyle |= LVS_ICON;
2bda0e17
KB
249 }
250
251 if ( style & wxLC_SMALL_ICON )
252 {
acb62b84
VZ
253 if ( (oldStyle & LVS_TYPEMASK) == LVS_ICON )
254 oldStyle -= LVS_ICON;
255 if ( (oldStyle & LVS_TYPEMASK) == LVS_REPORT )
256 oldStyle -= LVS_REPORT;
257 if ( (oldStyle & LVS_TYPEMASK) == LVS_LIST )
258 oldStyle -= LVS_LIST;
259 wstyle |= LVS_SMALLICON;
2bda0e17
KB
260 }
261
262 if ( style & wxLC_LIST )
263 {
acb62b84
VZ
264 if ( (oldStyle & LVS_TYPEMASK) == LVS_ICON )
265 oldStyle -= LVS_ICON;
266 if ( (oldStyle & LVS_TYPEMASK) == LVS_REPORT )
267 oldStyle -= LVS_REPORT;
268 if ( (oldStyle & LVS_TYPEMASK) == LVS_SMALLICON )
269 oldStyle -= LVS_SMALLICON;
270 wstyle |= LVS_LIST;
2bda0e17
KB
271 }
272
273 if ( style & wxLC_REPORT )
274 {
acb62b84
VZ
275 if ( (oldStyle & LVS_TYPEMASK) == LVS_ICON )
276 oldStyle -= LVS_ICON;
277 if ( (oldStyle & LVS_TYPEMASK) == LVS_LIST )
278 oldStyle -= LVS_LIST;
279 if ( (oldStyle & LVS_TYPEMASK) == LVS_SMALLICON )
280 oldStyle -= LVS_SMALLICON;
281 wstyle |= LVS_REPORT;
2bda0e17
KB
282 }
283
284 if ( style & wxLC_ALIGN_LEFT )
285 {
acb62b84
VZ
286 if ( oldStyle & LVS_ALIGNTOP )
287 oldStyle -= LVS_ALIGNTOP;
288 wstyle |= LVS_ALIGNLEFT;
2bda0e17
KB
289 }
290
291 if ( style & wxLC_ALIGN_TOP )
292 {
acb62b84
VZ
293 if ( oldStyle & LVS_ALIGNLEFT )
294 oldStyle -= LVS_ALIGNLEFT;
295 wstyle |= LVS_ALIGNTOP;
2bda0e17
KB
296 }
297
298 if ( style & wxLC_AUTOARRANGE )
acb62b84 299 wstyle |= LVS_AUTOARRANGE;
2bda0e17
KB
300
301 // Apparently, no such style (documentation wrong?)
302/*
303 if ( style & wxLC_BUTTON )
acb62b84 304 wstyle |= LVS_BUTTON;
2bda0e17
KB
305*/
306
307 if ( style & wxLC_NO_SORT_HEADER )
acb62b84 308 wstyle |= LVS_NOSORTHEADER;
2bda0e17
KB
309
310 if ( style & wxLC_NO_HEADER )
acb62b84 311 wstyle |= LVS_NOCOLUMNHEADER;
2bda0e17
KB
312
313 if ( style & wxLC_EDIT_LABELS )
acb62b84 314 wstyle |= LVS_EDITLABELS;
2bda0e17
KB
315
316 if ( style & wxLC_SINGLE_SEL )
acb62b84 317 wstyle |= LVS_SINGLESEL;
2bda0e17
KB
318
319 if ( style & wxLC_SORT_ASCENDING )
320 {
acb62b84
VZ
321 if ( oldStyle & LVS_SORTDESCENDING )
322 oldStyle -= LVS_SORTDESCENDING;
323 wstyle |= LVS_SORTASCENDING;
2bda0e17
KB
324 }
325
326 if ( style & wxLC_SORT_DESCENDING )
327 {
acb62b84
VZ
328 if ( oldStyle & LVS_SORTASCENDING )
329 oldStyle -= LVS_SORTASCENDING;
330 wstyle |= LVS_SORTDESCENDING;
2bda0e17
KB
331 }
332
333 return wstyle;
334}
335
336// Sets the background colour (GetBackgroundColour already implicit in
337// wxWindow class)
338void wxListCtrl::SetBackgroundColour(const wxColour& col)
339{
acb62b84 340 wxWindow::SetBackgroundColour(col);
2bda0e17 341
acb62b84 342 ListView_SetBkColor((HWND) GetHWND(), PALETTERGB(col.Red(), col.Green(), col.Blue()));
2bda0e17
KB
343}
344
345// Gets information about this column
debe6624 346bool wxListCtrl::GetColumn(int col, wxListItem& item) const
2bda0e17 347{
acb62b84
VZ
348 LV_COLUMN lvCol;
349 lvCol.mask = 0;
350 lvCol.fmt = 0;
351 lvCol.pszText = NULL;
352
353 if ( item.m_mask & wxLIST_MASK_TEXT )
354 {
355 lvCol.mask |= LVCF_TEXT;
356 lvCol.pszText = new char[513];
357 lvCol.cchTextMax = 512;
358 }
359
360 bool success = (ListView_GetColumn((HWND) GetHWND(), col, & lvCol) != 0);
361
362// item.m_subItem = lvCol.iSubItem;
363 item.m_width = lvCol.cx;
364
365 if ( (item.m_mask & wxLIST_MASK_TEXT) && lvCol.pszText )
366 {
367 item.m_text = lvCol.pszText;
368 delete[] lvCol.pszText;
369 }
370
371 if ( item.m_mask & wxLIST_MASK_FORMAT )
372 {
373 if (lvCol.fmt == LVCFMT_LEFT)
374 item.m_format = wxLIST_FORMAT_LEFT;
375 else if (lvCol.fmt == LVCFMT_RIGHT)
376 item.m_format = wxLIST_FORMAT_RIGHT;
377 else if (lvCol.fmt == LVCFMT_CENTER)
378 item.m_format = wxLIST_FORMAT_CENTRE;
2bda0e17
KB
379 }
380
acb62b84 381 return success;
2bda0e17
KB
382}
383
384// Sets information about this column
debe6624 385bool wxListCtrl::SetColumn(int col, wxListItem& item)
2bda0e17 386{
acb62b84
VZ
387 LV_COLUMN lvCol;
388 lvCol.mask = 0;
389 lvCol.fmt = 0;
390 lvCol.pszText = NULL;
391
392 if ( item.m_mask & wxLIST_MASK_TEXT )
393 {
394 lvCol.mask |= LVCF_TEXT;
395 lvCol.pszText = WXSTRINGCAST item.m_text;
396 lvCol.cchTextMax = 0; // Ignored
397 }
398 if ( item.m_mask & wxLIST_MASK_FORMAT )
399 {
400 lvCol.mask |= LVCF_FMT;
401
402 if ( item.m_format == wxLIST_FORMAT_LEFT )
403 lvCol.fmt = LVCFMT_LEFT;
404 if ( item.m_format == wxLIST_FORMAT_RIGHT )
405 lvCol.fmt = LVCFMT_RIGHT;
406 if ( item.m_format == wxLIST_FORMAT_CENTRE )
407 lvCol.fmt = LVCFMT_CENTER;
2bda0e17
KB
408 }
409
acb62b84
VZ
410 if ( item.m_mask & wxLIST_MASK_WIDTH )
411 {
412 lvCol.mask |= LVCF_WIDTH;
413 lvCol.cx = item.m_width;
2bda0e17 414
acb62b84
VZ
415 if ( lvCol.cx == wxLIST_AUTOSIZE)
416 lvCol.cx = LVSCW_AUTOSIZE;
417 else if ( lvCol.cx == wxLIST_AUTOSIZE_USEHEADER)
418 lvCol.cx = LVSCW_AUTOSIZE_USEHEADER;
419 }
420 lvCol.mask |= LVCF_SUBITEM;
421 lvCol.iSubItem = col;
422 return (ListView_SetColumn((HWND) GetHWND(), col, & lvCol) != 0);
2bda0e17
KB
423}
424
425// Gets the column width
debe6624 426int wxListCtrl::GetColumnWidth(int col) const
2bda0e17 427{
acb62b84 428 return ListView_GetColumnWidth((HWND) GetHWND(), col);
2bda0e17
KB
429}
430
431// Sets the column width
debe6624 432bool wxListCtrl::SetColumnWidth(int col, int width)
2bda0e17 433{
acb62b84
VZ
434 int col2 = col;
435 if ( m_windowStyle & wxLC_LIST )
436 col2 = -1;
2bda0e17 437
acb62b84
VZ
438 int width2 = width;
439 if ( width2 == wxLIST_AUTOSIZE)
440 width2 = LVSCW_AUTOSIZE;
441 else if ( width2 == wxLIST_AUTOSIZE_USEHEADER)
442 width2 = LVSCW_AUTOSIZE_USEHEADER;
2bda0e17 443
acb62b84 444 return (ListView_SetColumnWidth((HWND) GetHWND(), col2, width2) != 0);
2bda0e17
KB
445}
446
447// Gets the number of items that can fit vertically in the
448// visible area of the list control (list or report view)
449// or the total number of items in the list control (icon
450// or small icon view)
451int wxListCtrl::GetCountPerPage(void) const
452{
acb62b84 453 return ListView_GetCountPerPage((HWND) GetHWND());
2bda0e17
KB
454}
455
456// Gets the edit control for editing labels.
bbcdf8bc 457wxTextCtrl* wxListCtrl::GetEditControl(void) const
2bda0e17 458{
bbcdf8bc 459 return m_textCtrl;
2bda0e17
KB
460}
461
462// Gets information about the item
463bool wxListCtrl::GetItem(wxListItem& info) const
464{
acb62b84 465 LV_ITEM lvItem;
386af6a2
JS
466#ifdef __MINGW32__
467 memset(&lvItem, 0, sizeof(lvItem));
468#else
acb62b84 469 ZeroMemory(&lvItem, sizeof(lvItem)); // must set all fields to 0
386af6a2 470#endif
2bda0e17 471
acb62b84
VZ
472 lvItem.iItem = info.m_itemId;
473
474 if ( info.m_mask & wxLIST_MASK_TEXT )
475 {
476 lvItem.mask |= LVIF_TEXT;
477 lvItem.pszText = new char[513];
478 lvItem.cchTextMax = 512;
479 }
480 else
481 {
482 lvItem.pszText = NULL;
483 }
2bda0e17 484
acb62b84
VZ
485 if ( info.m_mask & wxLIST_MASK_STATE )
486 {
487 lvItem.mask |= LVIF_STATE;
488 // the other bits are hardly interesting anyhow
489 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
490 }
2bda0e17 491
acb62b84
VZ
492 bool success = ListView_GetItem((HWND)GetHWND(), &lvItem) != 0;
493 if ( !success )
494 {
495 wxLogError(_("Couldn't retrieve information about list control item %d."),
496 lvItem.iItem);
497 }
498 else
499 {
2bda0e17 500 wxConvertFromMSWListItem(this, info, lvItem);
acb62b84 501 }
2bda0e17 502
acb62b84
VZ
503 if (lvItem.pszText)
504 delete[] lvItem.pszText;
2bda0e17 505
acb62b84 506 return success;
2bda0e17
KB
507}
508
509// Sets information about the item
510bool wxListCtrl::SetItem(wxListItem& info)
511{
acb62b84 512 LV_ITEM item;
2bda0e17 513 wxConvertToMSWListItem(this, info, item);
acb62b84
VZ
514 item.cchTextMax = 0;
515 return (ListView_SetItem((HWND) GetHWND(), &item) != 0);
2bda0e17
KB
516}
517
debe6624 518long wxListCtrl::SetItem(long index, int col, const wxString& label, int imageId)
2bda0e17 519{
acb62b84
VZ
520 wxListItem info;
521 info.m_text = label;
522 info.m_mask = wxLIST_MASK_TEXT;
523 info.m_itemId = index;
524 info.m_col = col;
525 if ( imageId > -1 )
526 {
527 info.m_image = imageId;
528 info.m_mask |= wxLIST_MASK_IMAGE;
529 }
530 return SetItem(info);
2bda0e17
KB
531}
532
533
534// Gets the item state
debe6624 535int wxListCtrl::GetItemState(long item, long stateMask) const
2bda0e17 536{
acb62b84 537 wxListItem info;
2bda0e17 538
acb62b84
VZ
539 info.m_mask = wxLIST_MASK_STATE ;
540 info.m_stateMask = stateMask;
541 info.m_itemId = item;
2bda0e17 542
acb62b84
VZ
543 if (!GetItem(info))
544 return 0;
2bda0e17 545
acb62b84 546 return info.m_state;
2bda0e17
KB
547}
548
549// Sets the item state
debe6624 550bool wxListCtrl::SetItemState(long item, long state, long stateMask)
2bda0e17 551{
acb62b84 552 wxListItem info;
2bda0e17 553
acb62b84
VZ
554 info.m_mask = wxLIST_MASK_STATE ;
555 info.m_state = state;
556 info.m_stateMask = stateMask;
557 info.m_itemId = item;
2bda0e17 558
acb62b84 559 return SetItem(info);
2bda0e17
KB
560}
561
562// Sets the item image
debe6624 563bool wxListCtrl::SetItemImage(long item, int image, int selImage)
2bda0e17 564{
acb62b84 565 wxListItem info;
2bda0e17 566
acb62b84
VZ
567 info.m_mask = wxLIST_MASK_IMAGE ;
568 info.m_image = image;
569 info.m_itemId = item;
2bda0e17 570
acb62b84 571 return SetItem(info);
2bda0e17
KB
572}
573
574// Gets the item text
debe6624 575wxString wxListCtrl::GetItemText(long item) const
2bda0e17 576{
acb62b84 577 wxListItem info;
2bda0e17 578
acb62b84
VZ
579 info.m_mask = wxLIST_MASK_TEXT ;
580 info.m_itemId = item;
2bda0e17 581
acb62b84
VZ
582 if (!GetItem(info))
583 return wxString("");
584 return info.m_text;
2bda0e17
KB
585}
586
587// Sets the item text
debe6624 588void wxListCtrl::SetItemText(long item, const wxString& str)
2bda0e17 589{
acb62b84 590 wxListItem info;
2bda0e17 591
acb62b84
VZ
592 info.m_mask = wxLIST_MASK_TEXT ;
593 info.m_itemId = item;
594 info.m_text = str;
2bda0e17 595
acb62b84 596 SetItem(info);
2bda0e17
KB
597}
598
599// Gets the item data
debe6624 600long wxListCtrl::GetItemData(long item) const
2bda0e17 601{
acb62b84 602 wxListItem info;
2bda0e17 603
acb62b84
VZ
604 info.m_mask = wxLIST_MASK_DATA ;
605 info.m_itemId = item;
2bda0e17 606
acb62b84
VZ
607 if (!GetItem(info))
608 return 0;
609 return info.m_data;
2bda0e17
KB
610}
611
612// Sets the item data
debe6624 613bool wxListCtrl::SetItemData(long item, long data)
2bda0e17 614{
acb62b84 615 wxListItem info;
2bda0e17 616
acb62b84
VZ
617 info.m_mask = wxLIST_MASK_DATA ;
618 info.m_itemId = item;
619 info.m_data = data;
2bda0e17 620
acb62b84 621 return SetItem(info);
2bda0e17
KB
622}
623
624// Gets the item rectangle
16e93305 625bool wxListCtrl::GetItemRect(long item, wxRect& rect, int code) const
2bda0e17 626{
acb62b84 627 RECT rect2;
2bda0e17 628
acb62b84
VZ
629 int code2 = LVIR_BOUNDS;
630 if ( code == wxLIST_RECT_BOUNDS )
631 code2 = LVIR_BOUNDS;
632 else if ( code == wxLIST_RECT_ICON )
633 code2 = LVIR_ICON;
634 else if ( code == wxLIST_RECT_LABEL )
635 code2 = LVIR_LABEL;
2bda0e17 636
acb62b84 637 bool success = (ListView_GetItemRect((HWND) GetHWND(), (int) item, &rect2, code2) != 0);
2bda0e17 638
acb62b84
VZ
639 rect.x = rect2.left;
640 rect.y = rect2.top;
641 rect.width = rect2.right - rect2.left;
642 rect.height = rect2.bottom - rect2.left;
643 return success;
2bda0e17
KB
644}
645
646// Gets the item position
debe6624 647bool wxListCtrl::GetItemPosition(long item, wxPoint& pos) const
2bda0e17 648{
acb62b84 649 POINT pt;
2bda0e17 650
acb62b84 651 bool success = (ListView_GetItemPosition((HWND) GetHWND(), (int) item, &pt) != 0);
2bda0e17 652
acb62b84
VZ
653 pos.x = pt.x; pos.y = pt.y;
654 return success;
2bda0e17
KB
655}
656
657// Sets the item position.
debe6624 658bool wxListCtrl::SetItemPosition(long item, const wxPoint& pos)
2bda0e17 659{
acb62b84 660 return (ListView_SetItemPosition((HWND) GetHWND(), (int) item, pos.x, pos.y) != 0);
2bda0e17
KB
661}
662
663// Gets the number of items in the list control
664int wxListCtrl::GetItemCount(void) const
665{
acb62b84 666 return ListView_GetItemCount((HWND) GetHWND());
2bda0e17
KB
667}
668
669// Retrieves the spacing between icons in pixels.
670// If small is TRUE, gets the spacing for the small icon
671// view, otherwise the large icon view.
672int wxListCtrl::GetItemSpacing(bool isSmall) const
673{
acb62b84 674 return ListView_GetItemSpacing((HWND) GetHWND(), (BOOL) isSmall);
2bda0e17
KB
675}
676
677// Gets the number of selected items in the list control
678int wxListCtrl::GetSelectedItemCount(void) const
679{
acb62b84 680 return ListView_GetSelectedCount((HWND) GetHWND());
2bda0e17
KB
681}
682
683// Gets the text colour of the listview
684wxColour wxListCtrl::GetTextColour(void) const
685{
acb62b84
VZ
686 COLORREF ref = ListView_GetTextColor((HWND) GetHWND());
687 wxColour col(GetRValue(ref), GetGValue(ref), GetBValue(ref));
688 return col;
2bda0e17
KB
689}
690
691// Sets the text colour of the listview
692void wxListCtrl::SetTextColour(const wxColour& col)
693{
acb62b84 694 ListView_SetTextColor((HWND) GetHWND(), PALETTERGB(col.Red(), col.Blue(), col.Green()));
2bda0e17
KB
695}
696
697// Gets the index of the topmost visible item when in
698// list or report view
699long wxListCtrl::GetTopItem(void) const
700{
acb62b84 701 return (long) ListView_GetTopIndex((HWND) GetHWND());
2bda0e17
KB
702}
703
704// Searches for an item, starting from 'item'.
705// 'geometry' is one of
706// wxLIST_NEXT_ABOVE/ALL/BELOW/LEFT/RIGHT.
707// 'state' is a state bit flag, one or more of
708// wxLIST_STATE_DROPHILITED/FOCUSED/SELECTED/CUT.
709// item can be -1 to find the first item that matches the
710// specified flags.
711// Returns the item or -1 if unsuccessful.
debe6624 712long wxListCtrl::GetNextItem(long item, int geom, int state) const
2bda0e17 713{
acb62b84 714 long flags = 0;
2bda0e17 715
acb62b84
VZ
716 if ( geom == wxLIST_NEXT_ABOVE )
717 flags |= LVNI_ABOVE;
718 if ( geom == wxLIST_NEXT_ALL )
719 flags |= LVNI_ALL;
720 if ( geom == wxLIST_NEXT_BELOW )
721 flags |= LVNI_BELOW;
722 if ( geom == wxLIST_NEXT_LEFT )
723 flags |= LVNI_TOLEFT;
724 if ( geom == wxLIST_NEXT_RIGHT )
725 flags |= LVNI_TORIGHT;
2bda0e17 726
acb62b84
VZ
727 if ( state & wxLIST_STATE_CUT )
728 flags |= LVNI_CUT;
729 if ( state & wxLIST_STATE_DROPHILITED )
730 flags |= LVNI_DROPHILITED;
731 if ( state & wxLIST_STATE_FOCUSED )
732 flags |= LVNI_FOCUSED;
733 if ( state & wxLIST_STATE_SELECTED )
734 flags |= LVNI_SELECTED;
2bda0e17 735
acb62b84 736 return (long) ListView_GetNextItem((HWND) GetHWND(), item, flags);
2bda0e17
KB
737}
738
739
debe6624 740wxImageList *wxListCtrl::GetImageList(int which) const
2bda0e17 741{
acb62b84 742 if ( which == wxIMAGE_LIST_NORMAL )
2bda0e17 743 {
acb62b84
VZ
744 return m_imageListNormal;
745 }
746 else if ( which == wxIMAGE_LIST_SMALL )
2bda0e17 747 {
acb62b84
VZ
748 return m_imageListSmall;
749 }
750 else if ( which == wxIMAGE_LIST_STATE )
2bda0e17 751 {
acb62b84
VZ
752 return m_imageListState;
753 }
754 return NULL;
2bda0e17
KB
755}
756
debe6624 757void wxListCtrl::SetImageList(wxImageList *imageList, int which)
2bda0e17 758{
acb62b84
VZ
759 int flags = 0;
760 if ( which == wxIMAGE_LIST_NORMAL )
2bda0e17 761 {
acb62b84
VZ
762 flags = LVSIL_NORMAL;
763 m_imageListNormal = imageList;
764 }
765 else if ( which == wxIMAGE_LIST_SMALL )
2bda0e17 766 {
acb62b84
VZ
767 flags = LVSIL_SMALL;
768 m_imageListSmall = imageList;
769 }
770 else if ( which == wxIMAGE_LIST_STATE )
2bda0e17 771 {
acb62b84
VZ
772 flags = LVSIL_STATE;
773 m_imageListState = imageList;
774 }
775 ListView_SetImageList((HWND) GetHWND(), (HIMAGELIST) imageList ? imageList->GetHIMAGELIST() : 0, flags);
2bda0e17
KB
776}
777
778// Operations
779////////////////////////////////////////////////////////////////////////////
780
781// Arranges the items
debe6624 782bool wxListCtrl::Arrange(int flag)
2bda0e17 783{
acb62b84
VZ
784 UINT code = 0;
785 if ( flag == wxLIST_ALIGN_LEFT )
786 code = LVA_ALIGNLEFT;
787 else if ( flag == wxLIST_ALIGN_TOP )
788 code = LVA_ALIGNTOP;
789 else if ( flag == wxLIST_ALIGN_DEFAULT )
790 code = LVA_DEFAULT;
791 else if ( flag == wxLIST_ALIGN_SNAP_TO_GRID )
792 code = LVA_SNAPTOGRID;
2bda0e17 793
acb62b84 794 return (ListView_Arrange((HWND) GetHWND(), code) != 0);
2bda0e17
KB
795}
796
797// Deletes an item
debe6624 798bool wxListCtrl::DeleteItem(long item)
2bda0e17 799{
acb62b84 800 return (ListView_DeleteItem((HWND) GetHWND(), (int) item) != 0);
2bda0e17
KB
801}
802
803// Deletes all items
804bool wxListCtrl::DeleteAllItems(void)
805{
acb62b84 806 return (ListView_DeleteAllItems((HWND) GetHWND()) != 0);
2bda0e17
KB
807}
808
809// Deletes all items
810bool wxListCtrl::DeleteAllColumns(void)
811{
acb62b84 812 int i;
2bda0e17
KB
813 for ( i = 0; i < m_colCount; i++)
814 {
acb62b84 815 if (ListView_DeleteColumn((HWND) GetHWND(), 0) != 0)
2bda0e17
KB
816 m_colCount --;
817 }
818 return (m_colCount == 0);
819}
820
821// Deletes a column
debe6624 822bool wxListCtrl::DeleteColumn(int col)
2bda0e17 823{
acb62b84 824 bool success = (ListView_DeleteColumn((HWND) GetHWND(), col) != 0);
2bda0e17
KB
825
826 if ( success && (m_colCount > 0) )
827 m_colCount --;
828 return success;
829}
830
831// Clears items, and columns if there are any.
832void wxListCtrl::ClearAll(void)
833{
834 DeleteAllItems();
835 if ( m_colCount > 0 )
836 DeleteAllColumns();
837}
838
bbcdf8bc
JS
839wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass)
840{
841 wxASSERT( (textControlClass->IsKindOf(CLASSINFO(wxTextCtrl))) );
842
843 HWND hWnd = (HWND) ListView_EditLabel((HWND) GetHWND(), item);
844
845 if (m_textCtrl)
846 {
847 m_textCtrl->UnsubclassWin();
848 m_textCtrl->SetHWND(0);
849 delete m_textCtrl;
850 m_textCtrl = NULL;
851 }
852
853 m_textCtrl = (wxTextCtrl*) textControlClass->CreateObject();
854 m_textCtrl->SetHWND((WXHWND) hWnd);
855 m_textCtrl->SubclassWin((WXHWND) hWnd);
856
857 return m_textCtrl;
858}
859
860// End label editing, optionally cancelling the edit
861bool wxListCtrl::EndEditLabel(bool cancel)
2bda0e17 862{
341287bf 863 wxFAIL;
bbcdf8bc
JS
864
865/* I don't know how to implement this: there's no such macro as ListView_EndEditLabelNow.
866 * ???
867 bool success = (ListView_EndEditLabelNow((HWND) GetHWND(), cancel) != 0);
868
869 if (m_textCtrl)
870 {
871 m_textCtrl->UnsubclassWin();
872 m_textCtrl->SetHWND(0);
873 delete m_textCtrl;
874 m_textCtrl = NULL;
875 }
876 return success;
877*/
878 return FALSE;
2bda0e17
KB
879}
880
bbcdf8bc 881
2bda0e17 882// Ensures this item is visible
debe6624 883bool wxListCtrl::EnsureVisible(long item)
2bda0e17 884{
acb62b84 885 return (ListView_EnsureVisible((HWND) GetHWND(), (int) item, FALSE) != 0);
2bda0e17
KB
886}
887
888// Find an item whose label matches this string, starting from the item after 'start'
889// or the beginning if 'start' is -1.
debe6624 890long wxListCtrl::FindItem(long start, const wxString& str, bool partial)
2bda0e17 891{
acb62b84 892 LV_FINDINFO findInfo;
2bda0e17 893
acb62b84
VZ
894 findInfo.flags = LVFI_STRING;
895 if ( partial )
896 findInfo.flags |= LVFI_STRING;
897 findInfo.psz = WXSTRINGCAST str;
2bda0e17 898
acb62b84 899 return ListView_FindItem((HWND) GetHWND(), (int) start, & findInfo);
2bda0e17
KB
900}
901
902// Find an item whose data matches this data, starting from the item after 'start'
903// or the beginning if 'start' is -1.
debe6624 904long wxListCtrl::FindItem(long start, long data)
2bda0e17 905{
acb62b84 906 LV_FINDINFO findInfo;
2bda0e17 907
acb62b84
VZ
908 findInfo.flags = LVFI_PARAM;
909 findInfo.lParam = data;
2bda0e17 910
acb62b84 911 return ListView_FindItem((HWND) GetHWND(), (int) start, & findInfo);
2bda0e17
KB
912}
913
914// Find an item nearest this position in the specified direction, starting from
915// the item after 'start' or the beginning if 'start' is -1.
debe6624 916long wxListCtrl::FindItem(long start, const wxPoint& pt, int direction)
2bda0e17 917{
acb62b84 918 LV_FINDINFO findInfo;
2bda0e17 919
acb62b84
VZ
920 findInfo.flags = LVFI_NEARESTXY;
921 findInfo.pt.x = pt.x;
922 findInfo.pt.y = pt.y;
923 findInfo.vkDirection = VK_RIGHT;
2bda0e17 924
acb62b84
VZ
925 if ( direction == wxLIST_FIND_UP )
926 findInfo.vkDirection = VK_UP;
927 else if ( direction == wxLIST_FIND_DOWN )
928 findInfo.vkDirection = VK_DOWN;
929 else if ( direction == wxLIST_FIND_LEFT )
930 findInfo.vkDirection = VK_LEFT;
931 else if ( direction == wxLIST_FIND_RIGHT )
932 findInfo.vkDirection = VK_RIGHT;
2bda0e17 933
acb62b84 934 return ListView_FindItem((HWND) GetHWND(), (int) start, & findInfo);
2bda0e17
KB
935}
936
937// Determines which item (if any) is at the specified point,
938// giving details in 'flags' (see wxLIST_HITTEST_... flags above)
939long wxListCtrl::HitTest(const wxPoint& point, int& flags)
940{
941 LV_HITTESTINFO hitTestInfo;
acb62b84
VZ
942 hitTestInfo.pt.x = (int) point.x;
943 hitTestInfo.pt.y = (int) point.y;
2bda0e17
KB
944
945 ListView_HitTest((HWND) GetHWND(), & hitTestInfo);
946
acb62b84
VZ
947 flags = 0;
948 if ( hitTestInfo.flags & LVHT_ABOVE )
949 flags |= wxLIST_HITTEST_ABOVE;
950 if ( hitTestInfo.flags & LVHT_BELOW )
951 flags |= wxLIST_HITTEST_BELOW;
952 if ( hitTestInfo.flags & LVHT_NOWHERE )
953 flags |= wxLIST_HITTEST_NOWHERE;
954 if ( hitTestInfo.flags & LVHT_ONITEMICON )
955 flags |= wxLIST_HITTEST_ONITEMICON;
956 if ( hitTestInfo.flags & LVHT_ONITEMLABEL )
957 flags |= wxLIST_HITTEST_ONITEMLABEL;
958 if ( hitTestInfo.flags & LVHT_ONITEMSTATEICON )
959 flags |= wxLIST_HITTEST_ONITEMSTATEICON;
960 if ( hitTestInfo.flags & LVHT_TOLEFT )
961 flags |= wxLIST_HITTEST_TOLEFT;
962 if ( hitTestInfo.flags & LVHT_TORIGHT )
963 flags |= wxLIST_HITTEST_TORIGHT;
964
965 return (long) hitTestInfo.iItem ;
2bda0e17
KB
966}
967
968// Inserts an item, returning the index of the new item if successful,
969// -1 otherwise.
2bda0e17
KB
970long wxListCtrl::InsertItem(wxListItem& info)
971{
acb62b84
VZ
972 LV_ITEM item;
973 wxConvertToMSWListItem(this, info, item);
2bda0e17 974
acb62b84 975 return (long) ListView_InsertItem((HWND) GetHWND(), & item);
2bda0e17
KB
976}
977
debe6624 978long wxListCtrl::InsertItem(long index, const wxString& label)
2bda0e17 979{
acb62b84
VZ
980 wxListItem info;
981 info.m_text = label;
982 info.m_mask = wxLIST_MASK_TEXT;
983 info.m_itemId = index;
984 return InsertItem(info);
2bda0e17
KB
985}
986
987// Inserts an image item
debe6624 988long wxListCtrl::InsertItem(long index, int imageIndex)
2bda0e17 989{
acb62b84
VZ
990 wxListItem info;
991 info.m_image = imageIndex;
992 info.m_mask = wxLIST_MASK_IMAGE;
993 info.m_itemId = index;
994 return InsertItem(info);
2bda0e17
KB
995}
996
997// Inserts an image/string item
debe6624 998long wxListCtrl::InsertItem(long index, const wxString& label, int imageIndex)
2bda0e17 999{
acb62b84
VZ
1000 wxListItem info;
1001 info.m_image = imageIndex;
1002 info.m_text = label;
1003 info.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
1004 info.m_itemId = index;
1005 return InsertItem(info);
2bda0e17
KB
1006}
1007
1008// For list view mode (only), inserts a column.
debe6624 1009long wxListCtrl::InsertColumn(long col, wxListItem& item)
2bda0e17 1010{
acb62b84
VZ
1011 LV_COLUMN lvCol;
1012 lvCol.mask = 0;
1013 lvCol.fmt = 0;
1014 lvCol.pszText = NULL;
1015
1016 if ( item.m_mask & wxLIST_MASK_TEXT )
1017 {
1018 lvCol.mask |= LVCF_TEXT;
1019 lvCol.pszText = WXSTRINGCAST item.m_text;
1020 lvCol.cchTextMax = 0; // Ignored
1021 }
1022 if ( item.m_mask & wxLIST_MASK_FORMAT )
1023 {
1024 lvCol.mask |= LVCF_FMT;
1025
1026 if ( item.m_format == wxLIST_FORMAT_LEFT )
1027 lvCol.fmt = LVCFMT_LEFT;
1028 if ( item.m_format == wxLIST_FORMAT_RIGHT )
1029 lvCol.fmt = LVCFMT_RIGHT;
1030 if ( item.m_format == wxLIST_FORMAT_CENTRE )
1031 lvCol.fmt = LVCFMT_CENTER;
2bda0e17
KB
1032 }
1033
acb62b84
VZ
1034 if ( item.m_mask & wxLIST_MASK_WIDTH )
1035 {
1036 lvCol.mask |= LVCF_WIDTH;
1037 lvCol.cx = item.m_width;
2bda0e17 1038
acb62b84
VZ
1039 if ( lvCol.cx == wxLIST_AUTOSIZE)
1040 lvCol.cx = LVSCW_AUTOSIZE;
1041 else if ( lvCol.cx == wxLIST_AUTOSIZE_USEHEADER)
1042 lvCol.cx = LVSCW_AUTOSIZE_USEHEADER;
1043 }
1044 lvCol.mask |= LVCF_SUBITEM;
1045 lvCol.iSubItem = col;
2bda0e17 1046
acb62b84 1047 bool success = (ListView_InsertColumn((HWND) GetHWND(), col, & lvCol) != 0);
2bda0e17
KB
1048 if ( success )
1049 m_colCount ++;
1050 return success;
1051}
1052
debe6624
JS
1053long wxListCtrl::InsertColumn(long col, const wxString& heading, int format,
1054 int width)
2bda0e17 1055{
acb62b84
VZ
1056 wxListItem item;
1057 item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
1058 item.m_text = heading;
1059 if ( width > -1 )
1060 {
1061 item.m_mask |= wxLIST_MASK_WIDTH;
1062 item.m_width = width;
1063 }
1064 item.m_format = format;
2bda0e17 1065
acb62b84 1066 return InsertColumn(col, item);
2bda0e17
KB
1067}
1068
1069// Scrolls the list control. If in icon, small icon or report view mode,
1070// x specifies the number of pixels to scroll. If in list view mode, x
1071// specifies the number of columns to scroll.
1072// If in icon, small icon or list view mode, y specifies the number of pixels
1073// to scroll. If in report view mode, y specifies the number of lines to scroll.
debe6624 1074bool wxListCtrl::ScrollList(int dx, int dy)
2bda0e17 1075{
acb62b84 1076 return (ListView_Scroll((HWND) GetHWND(), dx, dy) != 0);
2bda0e17
KB
1077}
1078
1079// Sort items.
1080
1081// fn is a function which takes 3 long arguments: item1, item2, data.
1082// item1 is the long data associated with a first item (NOT the index).
1083// item2 is the long data associated with a second item (NOT the index).
1084// data is the same value as passed to SortItems.
1085// The return value is a negative number if the first item should precede the second
1086// item, a positive number of the second item should precede the first,
1087// or zero if the two items are equivalent.
1088
1089// data is arbitrary data to be passed to the sort function.
1090bool wxListCtrl::SortItems(wxListCtrlCompare fn, long data)
1091{
acb62b84 1092 return (ListView_SortItems((HWND) GetHWND(), (PFNLVCOMPARE) fn, data) != 0);
2bda0e17
KB
1093}
1094
debe6624 1095bool wxListCtrl::MSWCommand(WXUINT cmd, WXWORD id)
2bda0e17
KB
1096{
1097 if (cmd == EN_UPDATE)
1098 {
1099 wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, id);
1100 event.SetEventObject( this );
1101 ProcessCommand(event);
1102 return TRUE;
1103 }
1104 else if (cmd == EN_KILLFOCUS)
1105 {
1106 wxCommandEvent event(wxEVT_KILL_FOCUS, id);
1107 event.SetEventObject( this );
1108 ProcessCommand(event);
1109 return TRUE;
1110 }
1111 else return FALSE;
1112}
1113
fd3f686c 1114bool wxListCtrl::MSWNotify(WXWPARAM wParam, WXLPARAM lParam, WXLPARAM *result)
2bda0e17 1115{
acb62b84
VZ
1116 wxListEvent event(wxEVT_NULL, m_windowId);
1117 wxEventType eventType = wxEVT_NULL;
1118 NMHDR *hdr1 = (NMHDR *) lParam;
1119 switch ( hdr1->code )
1120 {
fd3f686c
VZ
1121 case LVN_BEGINRDRAG:
1122 eventType = wxEVT_COMMAND_LIST_BEGIN_RDRAG;
1123 // fall through
1124
acb62b84 1125 case LVN_BEGINDRAG:
fd3f686c
VZ
1126 if ( eventType == wxEVT_NULL )
1127 {
1128 eventType = wxEVT_COMMAND_LIST_BEGIN_DRAG;
1129 }
1130
1131 {
1132 NM_LISTVIEW *hdr = (NM_LISTVIEW *)lParam;
1133 event.m_itemIndex = hdr->iItem;
1134 event.m_pointDrag.x = hdr->ptAction.x;
1135 event.m_pointDrag.y = hdr->ptAction.y;
1136 }
1137 break;
1138
acb62b84
VZ
1139 case LVN_BEGINLABELEDIT:
1140 {
1141 eventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
1142 LV_DISPINFO *info = (LV_DISPINFO *)lParam;
1143 wxConvertFromMSWListItem(this, event.m_item, info->item, (HWND) GetHWND());
1144 break;
1145 }
fd3f686c 1146
acb62b84
VZ
1147 case LVN_COLUMNCLICK:
1148 {
1149 eventType = wxEVT_COMMAND_LIST_COL_CLICK;
1150 NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
1151 event.m_itemIndex = -1;
1152 event.m_col = hdr->iSubItem;
1153 break;
1154 }
1155 case LVN_DELETEALLITEMS:
1156 {
1157 eventType = wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS;
1158// NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
1159 event.m_itemIndex = -1;
1160 break;
1161 }
1162 case LVN_DELETEITEM:
1163 {
1164 eventType = wxEVT_COMMAND_LIST_DELETE_ITEM;
1165 NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
1166 event.m_itemIndex = hdr->iItem;
1167 break;
1168 }
1169 case LVN_ENDLABELEDIT:
1170 {
1171 eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
1172 LV_DISPINFO *info = (LV_DISPINFO *)lParam;
1173 wxConvertFromMSWListItem(this, event.m_item, info->item, (HWND) GetHWND());
1174 if ( info->item.pszText == NULL || info->item.iItem == -1 )
1175 event.m_cancelled = TRUE;
1176 break;
1177 }
1178 case LVN_GETDISPINFO:
1179 {
1180// return FALSE;
1181 // TODO: some text buffering here, I think
1182 // TODO: API for getting Windows to retrieve values
1183 // on demand.
1184 eventType = wxEVT_COMMAND_LIST_GET_INFO;
1185 LV_DISPINFO *info = (LV_DISPINFO *)lParam;
1186 wxConvertFromMSWListItem(this, event.m_item, info->item, (HWND) GetHWND());
1187 break;
1188 }
1189 case LVN_INSERTITEM:
1190 {
1191 eventType = wxEVT_COMMAND_LIST_INSERT_ITEM;
1192 NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
1193 event.m_itemIndex = hdr->iItem;
1194 break;
1195 }
1196 case LVN_ITEMCHANGED:
1197 {
1198 // This needs to be sent to wxListCtrl as a rather more
1199 // concrete event. For now, just detect a selection
1200 // or deselection.
1201 NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
1202 if ( (hdr->uNewState & LVIS_SELECTED) && !(hdr->uOldState & LVIS_SELECTED) )
1203 {
1204 eventType = wxEVT_COMMAND_LIST_ITEM_SELECTED;
1205 event.m_itemIndex = hdr->iItem;
1206 }
1207 else if ( !(hdr->uNewState & LVIS_SELECTED) && (hdr->uOldState & LVIS_SELECTED) )
1208 {
1209 eventType = wxEVT_COMMAND_LIST_ITEM_DESELECTED;
1210 event.m_itemIndex = hdr->iItem;
1211 }
1212 else
1213 return FALSE;
1214 break;
1215 }
1216 case LVN_KEYDOWN:
1217 {
1218 eventType = wxEVT_COMMAND_LIST_KEY_DOWN;
1219 LV_KEYDOWN *info = (LV_KEYDOWN *)lParam;
1220 event.m_code = wxCharCodeMSWToWX(info->wVKey);
1221 break;
1222 }
1223 case LVN_SETDISPINFO:
1224 {
1225 eventType = wxEVT_COMMAND_LIST_SET_INFO;
1226 LV_DISPINFO *info = (LV_DISPINFO *)lParam;
1227 wxConvertFromMSWListItem(this, event.m_item, info->item, (HWND) GetHWND());
1228 break;
1229 }
1230
1231 default :
fd3f686c 1232 return wxControl::MSWNotify(wParam, lParam, result);
acb62b84
VZ
1233 }
1234
1235 event.SetEventObject( this );
1236 event.SetEventType(eventType);
1237
1238 if ( !GetEventHandler()->ProcessEvent(event) )
1239 return FALSE;
1240
1241 if (hdr1->code == LVN_GETDISPINFO)
1242 {
1243 LV_DISPINFO *info = (LV_DISPINFO *)lParam;
1244 if ( info->item.mask & LVIF_TEXT )
1245 {
1246 if ( !event.m_item.m_text.IsNull() )
1247 {
1248 info->item.pszText = AddPool(event.m_item.m_text);
1249 info->item.cchTextMax = strlen(info->item.pszText) + 1;
1250 }
1251 }
1252// wxConvertToMSWListItem(this, event.m_item, info->item);
1253 }
1254
fd3f686c
VZ
1255 *result = !event.IsAllowed();
1256
1257 return TRUE;
2bda0e17
KB
1258}
1259
1260char *wxListCtrl::AddPool(const wxString& str)
1261{
acb62b84
VZ
1262 // Remove the first element if 3 strings exist
1263 if ( m_stringPool.Number() == 3 )
1264 {
1265 wxNode *node = m_stringPool.First();
1266 delete[] (char *)node->Data();
1267 delete node;
1268 }
1269 wxNode *node = m_stringPool.Add((char *) (const char *)str);
1270 return (char *)node->Data();
2bda0e17
KB
1271}
1272
1273// List item structure
1274wxListItem::wxListItem(void)
1275{
1276 m_mask = 0;
1277 m_itemId = 0;
1278 m_col = 0;
1279 m_state = 0;
1280 m_stateMask = 0;
1281 m_image = 0;
acb62b84 1282 m_data = 0;
2bda0e17 1283
acb62b84
VZ
1284 m_format = wxLIST_FORMAT_CENTRE;
1285 m_width = 0;
2bda0e17
KB
1286}
1287
1288static void wxConvertFromMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& lvItem, HWND getFullInfo)
1289{
acb62b84
VZ
1290 info.m_data = lvItem.lParam;
1291 info.m_mask = 0;
1292 info.m_state = 0;
1293 info.m_stateMask = 0;
1294 info.m_itemId = lvItem.iItem;
1295
1296 long oldMask = lvItem.mask;
1297
1298 bool needText = FALSE;
1299 if (getFullInfo != 0)
1300 {
1301 if ( lvItem.mask & LVIF_TEXT )
1302 needText = FALSE;
1303 else
1304 needText = TRUE;
1305
1306 if ( needText )
1307 {
1308 lvItem.pszText = new char[513];
1309 lvItem.cchTextMax = 512;
1310 }
1311// lvItem.mask |= TVIF_HANDLE | TVIF_STATE | TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_CHILDREN | TVIF_PARAM ;
1312 lvItem.mask |= LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM ;
1313 ::SendMessage(getFullInfo, LVM_GETITEM, 0, (LPARAM)& lvItem) ;
1314 }
1315
1316 if ( lvItem.mask & LVIF_STATE )
1317 {
1318 info.m_mask |= wxLIST_MASK_STATE;
1319
1320 if ( lvItem.stateMask & LVIS_CUT)
1321 {
1322 info.m_stateMask |= wxLIST_STATE_CUT ;
1323 if ( lvItem.state & LVIS_CUT )
1324 info.m_state |= wxLIST_STATE_CUT ;
1325 }
1326 if ( lvItem.stateMask & LVIS_DROPHILITED)
1327 {
1328 info.m_stateMask |= wxLIST_STATE_DROPHILITED ;
1329 if ( lvItem.state & LVIS_DROPHILITED )
1330 info.m_state |= wxLIST_STATE_DROPHILITED ;
1331 }
1332 if ( lvItem.stateMask & LVIS_FOCUSED)
1333 {
1334 info.m_stateMask |= wxLIST_STATE_FOCUSED ;
1335 if ( lvItem.state & LVIS_FOCUSED )
1336 info.m_state |= wxLIST_STATE_FOCUSED ;
1337 }
1338 if ( lvItem.stateMask & LVIS_SELECTED)
1339 {
1340 info.m_stateMask |= wxLIST_STATE_SELECTED ;
1341 if ( lvItem.state & LVIS_SELECTED )
1342 info.m_state |= wxLIST_STATE_SELECTED ;
1343 }
1344 }
1345
1346 if ( lvItem.mask & LVIF_TEXT )
1347 {
1348 info.m_mask |= wxLIST_MASK_TEXT;
1349 info.m_text = lvItem.pszText;
1350 }
1351 if ( lvItem.mask & LVIF_IMAGE )
1352 {
1353 info.m_mask |= wxLIST_MASK_IMAGE;
1354 info.m_image = lvItem.iImage;
1355 }
1356 if ( lvItem.mask & LVIF_PARAM )
1357 info.m_mask |= wxLIST_MASK_DATA;
1358 if ( lvItem.mask & LVIF_DI_SETITEM )
1359 info.m_mask |= wxLIST_SET_ITEM;
1360 info.m_col = lvItem.iSubItem;
1361
1362 if (needText)
1363 {
1364 if (lvItem.pszText)
1365 delete[] lvItem.pszText;
1366 }
1367 lvItem.mask = oldMask ;
2bda0e17
KB
1368}
1369
1370static void wxConvertToMSWListItem(const wxListCtrl *ctrl, wxListItem& info, LV_ITEM& lvItem)
1371{
acb62b84
VZ
1372 lvItem.iItem = (int) info.m_itemId ;
1373
1374 lvItem.iImage = info.m_image ;
1375 lvItem.lParam = info.m_data;
1376 lvItem.stateMask = 0;
1377 lvItem.state = 0;
1378 lvItem.mask = 0;
1379 lvItem.iSubItem = info.m_col;
1380
1381 if (info.m_mask & wxLIST_MASK_STATE)
1382 {
1383 lvItem.mask |= LVIF_STATE ;
1384 if (info.m_stateMask & wxLIST_STATE_CUT)
1385 {
1386 lvItem.stateMask |= LVIS_CUT ;
1387 if (info.m_state & wxLIST_STATE_CUT)
1388 lvItem.state |= LVIS_CUT;
1389 }
1390 if (info.m_stateMask & wxLIST_STATE_DROPHILITED)
1391 {
1392 lvItem.stateMask |= LVIS_DROPHILITED;
1393 if (info.m_state & wxLIST_STATE_DROPHILITED)
1394 lvItem.state |= LVIS_DROPHILITED;
1395 }
1396 if (info.m_stateMask & wxLIST_STATE_FOCUSED)
1397 {
1398 lvItem.stateMask |= LVIS_FOCUSED;
1399 if (info.m_state & wxLIST_STATE_FOCUSED)
1400 lvItem.state |= LVIS_FOCUSED;
1401 }
1402 if (info.m_stateMask & wxLIST_STATE_SELECTED)
1403 {
1404 lvItem.stateMask |= LVIS_SELECTED;
1405 if (info.m_state & wxLIST_STATE_SELECTED)
1406 lvItem.state |= LVIS_SELECTED;
1407 }
1408 }
1409
1410 if (info.m_mask & wxLIST_MASK_TEXT)
1411 {
1412 lvItem.mask |= LVIF_TEXT ;
1413 if ( ctrl->GetWindowStyleFlag() & wxLC_USER_TEXT )
1414 {
1415 lvItem.pszText = LPSTR_TEXTCALLBACK;
1416 }
1417 else
1418 {
1419 lvItem.pszText = (char *) (const char *)info.m_text ;
1420 if ( lvItem.pszText )
1421 lvItem.cchTextMax = info.m_text.Length();
1422 else
1423 lvItem.cchTextMax = 0;
1424 }
1425 }
1426 if (info.m_mask & wxLIST_MASK_IMAGE)
1427 lvItem.mask |= LVIF_IMAGE ;
1428 if (info.m_mask & wxLIST_MASK_DATA)
1429 lvItem.mask |= LVIF_PARAM ;
2bda0e17
KB
1430}
1431
1432// List event
92976ab6 1433IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
2bda0e17 1434
fd3f686c
VZ
1435wxListEvent::wxListEvent(wxEventType commandType, int id)
1436 : wxNotifyEvent(commandType, id)
2bda0e17 1437{
acb62b84
VZ
1438 m_code = 0;
1439 m_itemIndex = 0;
1440 m_col = 0;
1441 m_cancelled = FALSE;
2bda0e17
KB
1442}
1443
1444#endif
1445