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