Remove obsolete VisualAge-related files.
[wxWidgets.git] / src / os2 / listctrl.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/listctrl.cpp
3 // Purpose: wxListCtrl
4 // Author: David Webster
5 // Modified by:
6 // Created: 01/21/03
7 // Copyright: (c) David Webster
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // For compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #if wxUSE_LISTCTRL
27
28 #ifndef WX_PRECOMP
29 #include "wx/app.h"
30 #include "wx/intl.h"
31 #include "wx/log.h"
32 #include "wx/settings.h"
33 #include "wx/dcclient.h"
34 #include "wx/textctrl.h"
35 #endif
36
37 #include "wx/imaglist.h"
38 #include "wx/listctrl.h"
39
40 #include "wx/os2/private.h"
41
42 //
43 // FIELDOFFSET in DETAIL view as defined in the OS2TK45 simply doesn't work
44 // We use this, which does!
45 //
46 #undef FIELDOFFSET
47 #define FIELDOFFSET(type, field) ((ULONG)&(((type *)0)->field))
48
49 // ----------------------------------------------------------------------------
50 // private helper classes
51 // ----------------------------------------------------------------------------
52
53 /////////////////////////////////////////////////////////////////////////////
54 // STRUCT SMYRECORD
55 // Under OS/2 we have to use our own RECORDCORE based struct if we have
56 // user data to store in a PM Container Control (and wxListCtrl is a PM
57 // Container in ICON, NAME, TEXT or DETAIL view). m_ulUserData is a four
58 // byte value containing a pointer to our CListIntemInternalData class
59 // instance.
60 //
61 // And now for the big time OS/2 Kludge. In traditional OS/2 PM
62 // applications using containers, programmers determine BEFORE creation
63 // how many records the view will have, initially, and how many columns
64 // the detail view of the container will have, as the container represents
65 // a known data block. Thus the OS/2 PM CV_DETAIL view, i.e.
66 // the wxWidgets wxLC_REPORT view, relies on STATIC structure for its
67 // columnar data. It gets the data to display by telling it the specific
68 // offset of the field in the struct containing the displayable data. That
69 // data has be of OS/2 Types, PSZ (char string), CDATE or CTIME format.
70 // wxWidgets is dynamic in nature, however. We insert columns, one at a
71 // time and do not know how many until the app is done inserting them. So
72 // for OS/2 I have to set a max allowable since they are fixed. We return
73 // an error to the app if they include more than we can handle.
74 //
75 // For example to display the data "Col 4 of Item 6" in a report view, I'd
76 // have to do:
77 // pRecord->m_pzColumn4 = "Col 4 of Item 6";
78 // pField->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn4);
79 // and then call the PM API to set it.
80 //
81 // This really stinks but I can't use a pointer to another struct as the
82 // FIELDOFFSET call could only tell OS/2 the four byte value offset of
83 // pointer field and it would display giberish in the column.
84 /////////////////////////////////////////////////////////////////////////////
85 typedef struct _MYRECORD
86 {
87 RECORDCORE m_vRecord;
88 unsigned long m_ulItemId;
89 unsigned long m_ulUserData; //actually a pointer value to real data (a CListItemInternalData class instance)
90 PSZ m_pzColumn1;
91 PSZ m_pzColumn2;
92 PSZ m_pzColumn3;
93 PSZ m_pzColumn4;
94 PSZ m_pzColumn5;
95 PSZ m_pzColumn6;
96 PSZ m_pzColumn7;
97 PSZ m_pzColumn8;
98 PSZ m_pzColumn9;
99 PSZ m_pzColumn10;
100 } MYRECORD, *PMYRECORD;
101
102 /////////////////////////////////////////////////////////////////////////////
103 // CLASS CListItemInternalData
104 //
105 // Problem:
106 // The MSW version had problems with SetTextColour() et al as the
107 // CListItemAttr's were stored keyed on the item index. If a item was
108 // inserted anywhere but the end of the list the text attributes
109 // (colour etc) for the following items were out of sync.
110 //
111 // Solution:
112 // Under MSW the only way to associate data with a
113 // List item independent of its position in the list is to store a pointer
114 // to it in its lParam attribute. However user programs are already using
115 // this (via the SetItemData() GetItemData() calls).
116 //
117 // However what we can do is store a pointer to a structure which contains
118 // the attributes we want *and* a lParam for the users data, e.g.
119 //
120 // class CListItemInternalData
121 // {
122 // public:
123 // GuiAdvCtrl_CListItemAttr* pAttr;
124 // long lParam; // user data
125 // };
126 //
127 // To conserve memory, a CListItemInternalData is only allocated for a
128 // LV_ITEM if text attributes or user data(lparam) are being set.
129 //
130 // For OS/2, the lParam value points to whatever actual data we have
131 /////////////////////////////////////////////////////////////////////////////
132 class CListItemInternalData
133 {
134 public:
135
136 CListItemInternalData(): m_pAttr(NULL)
137 ,m_lParam(0)
138 {}
139
140 ~CListItemInternalData()
141 {
142 wxDELETE(m_pAttr);
143 }
144
145 wxListItemAttr* m_pAttr;
146 WXLPARAM m_lParam; // user data
147 PMYRECORD m_pMyRecord; // so we can set the m_ulUserData to 0 when this is deleted
148 }; // end of CLASS CListItemInternalData
149
150 /////////////////////////////////////////////////////////////////////////////
151 // STRUCT SInternalDataSort
152 //
153 // Sort items.
154 //
155 // fn is a function which takes 3 long arguments: item1, item2, data.
156 // item1 is the long data associated with a first item (NOT the index).
157 // item2 is the long data associated with a second item (NOT the index).
158 // data is the same value as passed to SortItems.
159 //
160 // The return value is a negative number if the first item should precede the
161 // second item, a positive number of the second item should precede the first,
162 // or zero if the two items are equivalent.
163 //
164 // data is arbitrary data to be passed to the sort function.
165 //
166 // Internal structures for proxying the user compare function
167 // so that we can pass it the *real* user data
168 /////////////////////////////////////////////////////////////////////////////
169 typedef struct internalDataSort
170 {
171 wxListCtrlCompare m_fnUser;
172 long m_lData;
173 } SInternalDataSort; // end of STRUCT SInternalDataSort
174
175 // ----------------------------------------------------------------------------
176 // private helper functions
177 // ----------------------------------------------------------------------------
178
179 /////////////////////////////////////////////////////////////////////////////
180 //
181 // FindOS2ListFieldByColNum
182 //
183 // There is no way, under OS/2 to get a field in a container by index,
184 // directly, so you must get the first one, then cycle through the list
185 // until you get to where you want to be.
186 //
187 // PARAMETERS
188 // hWnd -- window handle of container to search
189 // lIndex -- index to set
190 //
191 // RETURN VALUE
192 // pointer to the FIELDINFO struct at the index in the container record
193 //
194 /////////////////////////////////////////////////////////////////////////////
195 PFIELDINFO FindOS2ListFieldByColNum (
196 HWND hWnd
197 , long lIndex
198 )
199 {
200 PFIELDINFO pFieldInfo = NULL;
201 CNRINFO vCnrInfo;
202 ULONG i;
203
204 if (!::WinSendMsg( hWnd
205 ,CM_QUERYCNRINFO
206 ,MPFROMP(&vCnrInfo)
207 ,(MPARAM)(USHORT)sizeof(CNRINFO)
208 ))
209 return NULL;
210 for (i = 0; i < vCnrInfo.cFields; i++)
211 {
212 if (i == 0)
213 pFieldInfo = (PFIELDINFO)PVOIDFROMMR(::WinSendMsg( hWnd
214 ,CM_QUERYDETAILFIELDINFO
215 ,MPFROMP(pFieldInfo)
216 ,(MPARAM)CMA_FIRST
217 ));
218 else
219 pFieldInfo = (PFIELDINFO)PVOIDFROMMR(::WinSendMsg( hWnd
220 ,CM_QUERYDETAILFIELDINFO
221 ,MPFROMP(pFieldInfo)
222 ,(MPARAM)CMA_NEXT
223 ));
224 if (!pFieldInfo)
225 return NULL;
226 if (i == (ULONG)lIndex)
227 break;
228 }
229 if (!pFieldInfo)
230 return NULL;
231 return pFieldInfo;
232 } // end of FindOS2ListFieldByColNum
233
234 /////////////////////////////////////////////////////////////////////////////
235 //
236 // FindOS2ListRecordByID
237 //
238 // There is no way, under OS/2 to get a record in a container by index,
239 // directly, so you must get the first one, then cycle through the list
240 // until you get to where you want to be.
241 //
242 // PARAMETERS
243 // hWnd -- window handle of container to search
244 // lItemId -- index to set
245 //
246 // RETURN VALUE
247 // pointer to the internal RECORDCORE struct at the index in the container
248 //
249 /////////////////////////////////////////////////////////////////////////////
250 PMYRECORD FindOS2ListRecordByID (
251 HWND hWnd
252 , long lItemId
253 )
254 {
255 PMYRECORD pRecord = NULL;
256 CNRINFO vCnrInfo;
257 unsigned long i;
258
259 if (!::WinSendMsg( hWnd
260 ,CM_QUERYCNRINFO
261 ,MPFROMP(&vCnrInfo)
262 ,(MPARAM)(USHORT)sizeof(CNRINFO)
263 ))
264 return NULL;
265 for (i = 0; i < vCnrInfo.cRecords; i++)
266 {
267 if (i == 0)
268 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
269 ,CM_QUERYRECORD
270 ,MPFROMP(pRecord)
271 ,MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER)
272 ));
273 else
274 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
275 ,CM_QUERYRECORD
276 ,MPFROMP(pRecord)
277 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
278 ));
279 if (!pRecord)
280 return NULL;
281 if (pRecord->m_ulItemId == (ULONG)lItemId)
282 break;
283 }
284 return pRecord;
285 } // end of FindOS2ListRecordByID
286
287 /////////////////////////////////////////////////////////////////////////////
288 //
289 // BumpRecordIds
290 //
291 // Since OS/2 does not keep native record id's but wx insists on inserting
292 // and selecting via ID's, when we insert a record in the middle we need
293 // to bump the id's of each record after the one we just inserted.
294 //
295 // PARAMETERS
296 // hWnd -- window handle of container to search
297 // pRecord -- record after which we starting bumping id's
298 //
299 // RETURN VALUE
300 // none
301 //
302 /////////////////////////////////////////////////////////////////////////////
303 void BumpRecordIds (
304 HWND hWnd
305 , PMYRECORD pRecord
306 )
307 {
308 while(pRecord)
309 {
310 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( hWnd
311 ,CM_QUERYRECORD
312 ,MPFROMP(pRecord)
313 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
314 ));
315 if (pRecord)
316 pRecord->m_ulItemId++;
317 }
318 } // end of BumpRecordIds
319
320 /////////////////////////////////////////////////////////////////////////////
321 //
322 // GetInternalData
323 //
324 // Get the internal data given a handle and an id
325 //
326 // PARAMETERS
327 // hWnd -- window handle to the control in which item is located
328 // lItemId -- ID to get
329 //
330 // RETURN VALUE
331 // pointer to the internal data
332 //
333 // Note:
334 // Under OS/2 PM a container item cannot be obtained via a simple index or
335 // id retrieval. We have to walk the record list if we are looking for
336 // a record at a specific index location
337 /////////////////////////////////////////////////////////////////////////////
338 CListItemInternalData* GetInternalData (
339 HWND hWnd
340 , long lItemId
341 )
342 {
343 PMYRECORD pRecord = FindOS2ListRecordByID( hWnd
344 ,lItemId
345 );
346 //
347 // Internal user data is stored AFTER the last field of the RECORDCORE
348 //
349 if (!pRecord)
350 return NULL;
351 return((CListItemInternalData *)(pRecord->m_ulUserData));
352 } // end of GetInternalData
353
354 /////////////////////////////////////////////////////////////////////////////
355 //
356 // GetInternalData
357 //
358 // Get the internal data given a pointer to a list control and an id
359 //
360 // PARAMETERS
361 // pCtl -- pointer to control inwhich item is located
362 // lItemId -- ID to get
363 //
364 // RETURN VALUE
365 // pointer to the internal data
366 //
367 /////////////////////////////////////////////////////////////////////////////
368 CListItemInternalData* GetInternalData (
369 wxListCtrl* pCtl
370 , long lItemId
371 )
372 {
373 return(GetInternalData( (HWND)pCtl->GetHWND()
374 ,lItemId
375 ));
376 } // end of GetInternalData
377
378 /////////////////////////////////////////////////////////////////////////////
379 //
380 // DeleteInternalData
381 //
382 // Delete the internal data for a record
383 //
384 // PARAMETERS
385 // pCtl -- pointer to the list control containing the record
386 // lItemId -- the record index to delete the internal data from
387 //
388 // RETURN VALUE
389 // pointer to the internal data attribute
390 //
391 /////////////////////////////////////////////////////////////////////////////
392 void DeleteInternalData (
393 wxListCtrl* pCtl
394 , long lItemId
395 )
396 {
397 CListItemInternalData* pData = GetInternalData( pCtl
398 ,lItemId
399 );
400 if (pData)
401 {
402 if (pData->m_pMyRecord)
403 pData->m_pMyRecord->m_ulUserData = 0;
404 delete pData;
405 }
406 } // end of DeleteInternalData
407
408 // #pragma page "GetInternalDataAttr"
409 /////////////////////////////////////////////////////////////////////////////
410 //
411 // GetInternalDataAttr
412 //
413 // Get the internal data item attribute given a pointer to a list control
414 // and an id
415 //
416 // PARAMETERS
417 // pCtl -- pointer to control to set
418 // lItemId -- ID to set
419 //
420 // RETURN VALUE
421 // pointer to the internal data attribute
422 //
423 /////////////////////////////////////////////////////////////////////////////
424 wxListItemAttr* GetInternalDataAttr (
425 wxListCtrl* pCtl
426 , long lItemId
427 )
428 {
429 CListItemInternalData* pData = GetInternalData( pCtl
430 ,lItemId
431 );
432
433 if (pData)
434 return(pData->m_pAttr);
435 else
436 return NULL;
437 } // end of GetInternalDataAttr
438
439 /////////////////////////////////////////////////////////////////////////////
440 //
441 // InternalDataCompareFunc
442 //
443 // This is compare function we pass to PM. It wraps the real compare
444 // function in SInternalDataSort
445 //
446 // PARAMETERS
447 // p1 -- is the first record structure to compare
448 // p2 -- is the second record structure to compare
449 // lStorage -- is the same value as passed to SortItems.
450 //
451 // RETURN VALUE
452 // pointer to the internal data attribute
453 //
454 /////////////////////////////////////////////////////////////////////////////
455 SHORT EXPENTRY InternalDataCompareFunc (
456 PMYRECORD p1
457 , PMYRECORD p2
458 , PVOID pStorage
459 )
460 {
461 SInternalDataSort* pInternalData = (SInternalDataSort *)pStorage;
462 CListItemInternalData* pData1 = (CListItemInternalData *)p1->m_ulUserData;
463 CListItemInternalData* pData2 = (CListItemInternalData *)p2->m_ulUserData;
464 long lD1 = (pData1 == NULL ? 0 : (long)pData1->m_lParam);
465 long lD2 = (pData2 == NULL ? 0 : (long)pData2->m_lParam);
466
467 return(pInternalData->m_fnUser( lD1
468 ,lD2
469 ,pInternalData->m_lData
470 ));
471 } // end of InternalDataCompareFunc
472
473 /////////////////////////////////////////////////////////////////////////////
474 //
475 // ConvertFromOS2ListItem
476 //
477 // Convert from an internal PM List item to a Toolkit List item
478 //
479 // PARAMETERS
480 // hWndListCtrl -- the control's windows handle
481 // rInfo -- the library list control to convert to
482 // pRecord -- the OS list control to convert from
483 //
484 // RETURN VALUE
485 // none
486 //
487 /////////////////////////////////////////////////////////////////////////////
488 void ConvertFromOS2ListItem ( HWND hWndListCtrl,
489 wxListItem& rInfo,
490 PMYRECORD pRecord )
491 {
492 CListItemInternalData* pInternaldata = (CListItemInternalData *)pRecord->m_ulUserData;
493 bool bNeedText = false;
494
495 if (pInternaldata)
496 rInfo.SetData(pInternaldata->m_lParam);
497
498 rInfo.SetMask(0);
499 rInfo.SetState(0);
500 rInfo.SetStateMask(0);
501 rInfo.SetId((long)pRecord->m_ulItemId);
502 if (hWndListCtrl != 0)
503 {
504 pRecord = FindOS2ListRecordByID( hWndListCtrl
505 ,rInfo.GetId()
506 );
507 }
508
509 //
510 // The wxListItem class is really set up to handle the WIN32 list item
511 // and OS/2 are not as complicated. Just set both state members to the
512 // same thing under OS/2
513 //
514 if (pRecord->m_vRecord.flRecordAttr & CRA_DROPONABLE)
515 {
516 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_DROPHILITED);
517 rInfo.SetState(rInfo.m_state | wxLIST_STATE_DROPHILITED);
518 }
519 if (pRecord->m_vRecord.flRecordAttr & CRA_SELECTED)
520 {
521 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_SELECTED);
522 rInfo.SetState(rInfo.m_state | wxLIST_STATE_SELECTED);
523 }
524 if (pRecord->m_vRecord.flRecordAttr & CRA_DISABLED)
525 {
526 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_DISABLED);
527 rInfo.SetState(rInfo.m_state | wxLIST_STATE_DISABLED);
528 }
529 if (pRecord->m_vRecord.flRecordAttr & CRA_FILTERED)
530 {
531 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_FILTERED);
532 rInfo.SetState(rInfo.m_state | wxLIST_STATE_FILTERED);
533 }
534 if (pRecord->m_vRecord.flRecordAttr & CRA_INUSE)
535 {
536 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_INUSE);
537 rInfo.SetState(rInfo.m_state | wxLIST_STATE_INUSE);
538 }
539 if (pRecord->m_vRecord.flRecordAttr & CRA_PICKED)
540 {
541 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_PICKED);
542 rInfo.SetState(rInfo.m_state | wxLIST_STATE_PICKED);
543 }
544 if (pRecord->m_vRecord.flRecordAttr & CRA_SOURCE)
545 {
546 rInfo.SetStateMask(rInfo.m_stateMask | wxLIST_STATE_SOURCE);
547 rInfo.SetState(rInfo.m_state | wxLIST_STATE_SOURCE);
548 }
549
550 if (pRecord->m_vRecord.pszText != (PSZ)NULL)
551 {
552 rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_TEXT);
553 rInfo.SetText(pRecord->m_vRecord.pszText);
554 }
555 if (pRecord->m_vRecord.pszIcon != (PSZ)NULL ||
556 pRecord->m_vRecord.pszName != (PSZ)NULL)
557 {
558 rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_IMAGE);
559 rInfo.SetImage(pRecord->m_vRecord.hptrIcon);
560 }
561 if (pRecord->m_ulUserData)
562 rInfo.SetMask(rInfo.GetMask() | wxLIST_MASK_DATA);
563 } // end of ConvertFromOS2ListItem
564
565 /////////////////////////////////////////////////////////////////////////////
566 //
567 // ConvertToOS2Flags
568 //
569 // Convert from an library states to OS states
570 //
571 // PARAMETERS
572 // lState -- the state
573 // pRecord -- the OS list control to use
574 //
575 // RETURN VALUE
576 // none
577 //
578 /////////////////////////////////////////////////////////////////////////////
579 void ConvertToOS2Flags (
580 long lState
581 , PMYRECORD pRecord
582 )
583 {
584 if (lState & wxLIST_STATE_DROPHILITED)
585 pRecord->m_vRecord.flRecordAttr |= CRA_DROPONABLE;
586 if (lState & wxLIST_STATE_SELECTED)
587 pRecord->m_vRecord.flRecordAttr |= CRA_SELECTED;
588 if (lState & wxLIST_STATE_DISABLED)
589 pRecord->m_vRecord.flRecordAttr |= CRA_DISABLED;
590 if (lState & wxLIST_STATE_FILTERED)
591 pRecord->m_vRecord.flRecordAttr |= CRA_FILTERED;
592 if (lState & wxLIST_STATE_INUSE)
593 pRecord->m_vRecord.flRecordAttr |= CRA_INUSE;
594 if (lState & wxLIST_STATE_PICKED)
595 pRecord->m_vRecord.flRecordAttr |= CRA_PICKED;
596 if (lState & wxLIST_STATE_SOURCE)
597 pRecord->m_vRecord.flRecordAttr |= CRA_SOURCE;
598 } // end of ConvertToOS2Flags
599
600 /////////////////////////////////////////////////////////////////////////////
601 //
602 // ConvertToOS2ListItem
603 //
604 // Convert from a library List item to an internal OS2 List item. We set
605 // only the fields we need to set. Some of them are set by the API when
606 // they are added to the container.
607 //
608 // PARAMETERS
609 // pCtrl -- the control to use
610 // rInfo -- the item to convert
611 // pRecord -- the OS list control to use, should be zeroed out
612 // pFieldinfo -- a field struct that may contain columnar data for detail view
613 //
614 // RETURN VALUE
615 // none
616 //
617 /////////////////////////////////////////////////////////////////////////////
618 void ConvertToOS2ListItem (
619 const wxListCtrl* pCtrl
620 , const wxListItem& rInfo
621 , PMYRECORD pRecord
622 , PFIELDINFO pFieldInfo
623 )
624 {
625 pRecord->m_ulItemId = (ULONG)rInfo.GetId();
626 pRecord->m_vRecord.cb = sizeof(RECORDCORE);
627 if (rInfo.GetMask() & wxLIST_MASK_STATE)
628 {
629 ConvertToOS2Flags( rInfo.m_state
630 ,pRecord
631 );
632 }
633 if (pCtrl->GetWindowStyleFlag() & wxLC_ICON ||
634 pCtrl->GetWindowStyleFlag() & wxLC_SMALL_ICON)
635 {
636 pRecord->m_vRecord.pszIcon = (char*)rInfo.GetText().c_str();
637 }
638 if (pCtrl->GetWindowStyleFlag() & wxLC_LIST) // PM TEXT view
639 {
640 pRecord->m_vRecord.pszText = (char*)rInfo.GetText().c_str();
641 }
642 //
643 // In the case of a report view the text will be the data in the lead column
644 // ???? Don't know why, but that is how it works in other ports.
645 //
646 if (pCtrl->GetWindowStyleFlag() & wxLC_REPORT)
647 {
648 if (pFieldInfo)
649 {
650 switch(rInfo.GetColumn())
651 {
652 case 0:
653 pRecord->m_pzColumn1 = (char*)rInfo.GetText().c_str();
654 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn1);
655 break;
656
657 case 1:
658 pRecord->m_pzColumn2 = (char*)rInfo.GetText().c_str();
659 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn2);
660 break;
661
662 case 2:
663 pRecord->m_pzColumn3 = (char*)rInfo.GetText().c_str();
664 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn3);
665 break;
666
667 case 3:
668 pRecord->m_pzColumn4 = (char*)rInfo.GetText().c_str();
669 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn4);
670 break;
671
672 case 4:
673 pRecord->m_pzColumn5 = (char*)rInfo.GetText().c_str();
674 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn5);
675 break;
676
677 case 5:
678 pRecord->m_pzColumn6 = (char*)rInfo.GetText().c_str();
679 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn6);
680 break;
681
682 case 6:
683 pRecord->m_pzColumn7 = (char*)rInfo.GetText().c_str();
684 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn7);
685 break;
686
687 case 7:
688 pRecord->m_pzColumn8 = (char*)rInfo.GetText().c_str();
689 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn8);
690 break;
691
692 case 8:
693 pRecord->m_pzColumn9 = (char*)rInfo.GetText().c_str();
694 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn9);
695 break;
696
697 case 9:
698 pRecord->m_pzColumn10 = (char*)rInfo.GetText().c_str();
699 pFieldInfo->offStruct = FIELDOFFSET(MYRECORD, m_pzColumn10);
700 break;
701
702 default:
703 wxFAIL_MSG( wxT("wxOS2 does not support more than 10 columns in REPORT view") );
704 break;
705 }
706 }
707 }
708 if (rInfo.GetMask() & wxLIST_MASK_IMAGE)
709 {
710 pRecord->m_vRecord.hptrIcon = (HPOINTER)rInfo.GetImage();
711 pRecord->m_vRecord.hptrMiniIcon = (HPOINTER)rInfo.m_miniImage;
712 }
713 } // end of ConvertToOS2ListItem
714
715 /////////////////////////////////////////////////////////////////////////////
716 //
717 // ConvertToOS2ListCol
718 //
719 // Convert from a library List column to an internal PM List column
720 //
721 // PARAMETERS
722 // lCol -- the columnd to convert
723 // rItem -- the item to convert
724 // pField -- the OS list column to use
725 //
726 // RETURN VALUE
727 // none
728 //
729 /////////////////////////////////////////////////////////////////////////////
730 void ConvertToOS2ListCol (
731 long lCol
732 , const wxListItem& rItem
733 , PFIELDINFO pField
734 )
735 {
736 memset(pField, '\0', sizeof(FIELDINFO));
737 pField->cb = sizeof(FIELDINFO);
738
739 //
740 // Default some settings
741 //
742 pField->flData = CFA_HORZSEPARATOR | CFA_SEPARATOR;
743 pField->flTitle = CFA_CENTER;
744
745 if (rItem.GetMask() & wxLIST_MASK_TEXT)
746 {
747 pField->flData |= CFA_STRING;
748 pField->pTitleData = (PVOID)rItem.GetText().c_str(); // text is column title not data
749 }
750 if (rItem.GetMask() & wxLIST_MASK_FORMAT)
751 {
752 if (rItem.m_format == wxLIST_FORMAT_LEFT)
753 pField->flData |= CFA_LEFT;
754 else if (rItem.m_format == wxLIST_FORMAT_RIGHT)
755 pField->flData |= CFA_RIGHT;
756 else if (rItem.m_format == wxLIST_FORMAT_CENTRE)
757 pField->flData |= CFA_CENTER;
758 }
759 else
760 pField->flData |= CFA_CENTER; // Just ensure the default is centered
761 if (rItem.GetMask() & wxLIST_MASK_WIDTH)
762 {
763 if (!(rItem.GetWidth() == wxLIST_AUTOSIZE ||
764 rItem.GetWidth() == wxLIST_AUTOSIZE_USEHEADER))
765 pField->cxWidth = rItem.GetWidth();
766 // else: OS/2 automatically sets the width if created with the approppriate style
767 }
768
769 //
770 // Still need to set the actual data
771 //
772 pField->offStruct = 0;
773 } // end of ConvertToOS2ListCol
774
775 BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
776 EVT_PAINT(wxListCtrl::OnPaint)
777 END_EVENT_TABLE()
778
779 // ============================================================================
780 // implementation
781 // ============================================================================
782
783 // ----------------------------------------------------------------------------
784 // wxListCtrl construction
785 // ----------------------------------------------------------------------------
786
787 void wxListCtrl::Init ()
788 {
789 m_pImageListNormal = NULL;
790 m_pImageListSmall = NULL;
791 m_pImageListState = NULL;
792 m_bOwnsImageListNormal = false;
793 m_bOwnsImageListSmall = false;
794 m_bOwnsImageListState = false;
795 m_lBaseStyle = 0L;
796 m_nColCount = 0;
797 m_pTextCtrl = NULL;
798 m_bAnyInternalData = false;
799 m_bHasAnyAttr = false;
800 } // end of wxListCtrl::Init
801
802 bool wxListCtrl::Create ( wxWindow* pParent,
803 wxWindowID vId,
804 const wxPoint& rPos,
805 const wxSize& rSize,
806 long lStyle,
807 const wxValidator& rValidator,
808 const wxString& rsName )
809 {
810 int nX = rPos.x;
811 int nY = rPos.y;
812 int nWidth = rSize.x;
813 int nHeight = rSize.y;
814
815 #if wxUSE_VALIDATORS
816 SetValidator(rValidator);
817 #endif // wxUSE_VALIDATORS
818
819 SetName(rsName);
820 SetWindowStyleFlag(lStyle);
821 SetParent(pParent);
822 if (nWidth <= 0)
823 nWidth = 100;
824 if (nHeight <= 0)
825 nHeight = 30;
826 if (nX < 0)
827 nX = 0;
828 if (nY < 0)
829 nY = 0;
830
831 m_windowId = (vId == -1) ? NewControlId() : vId;
832
833 long lSstyle = WS_VISIBLE | WS_TABSTOP;
834
835 if (GetWindowStyleFlag() & wxCLIP_SIBLINGS)
836 lSstyle |= WS_CLIPSIBLINGS;
837 m_lBaseStyle = lSstyle;
838 if (!DoCreateControl( nX
839 ,nY
840 ,nWidth
841 ,nHeight
842 ))
843 return false;
844 if (pParent)
845 pParent->AddChild(this);
846 return true;
847 } // end of wxListCtrl::Create
848
849 bool wxListCtrl::DoCreateControl ( int nX, int nY,
850 int nWidth, int nHeight )
851 {
852 DWORD lWstyle = m_lBaseStyle;
853 long lOldStyle = 0; // Dummy
854
855 CNRINFO vCnrInfo;
856
857 lWstyle |= ConvertToOS2Style( lOldStyle
858 ,GetWindowStyleFlag()
859 );
860
861 m_hWnd = (WXHWND)::WinCreateWindow( GetParent()->GetHWND()
862 ,WC_CONTAINER
863 ,NULL
864 ,m_lBaseStyle
865 ,0, 0, 0, 0
866 ,GetParent()->GetHWND()
867 ,HWND_BOTTOM
868 ,(ULONG)m_windowId
869 ,NULL
870 ,NULL
871 );
872 if (!m_hWnd)
873 {
874 return false;
875 }
876
877 //
878 // Now set the display attributes of the container
879 //
880 if (!::WinSendMsg( GetHWND()
881 ,CM_QUERYCNRINFO
882 ,MPFROMP(&vCnrInfo)
883 ,(MPARAM)(USHORT)sizeof(CNRINFO)
884 ))
885 return false;
886 lWstyle = ConvertViewToOS2Style(GetWindowStyleFlag());
887 vCnrInfo.flWindowAttr |= lWstyle;
888 if (!::WinSendMsg( GetHWND()
889 ,CM_SETCNRINFO
890 ,MPFROMP(&vCnrInfo)
891 ,(MPARAM)CMA_FLWINDOWATTR
892 ))
893 return false;
894
895 //
896 // And now set needed arrangement flags
897 //
898 lWstyle = ConvertArrangeToOS2Style(GetWindowStyleFlag());
899 if (!::WinSendMsg( GetHWND()
900 ,CM_ARRANGE
901 ,(MPARAM)CMA_ARRANGEGRID
902 ,(MPARAM)lWstyle
903 ))
904 return false;
905 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
906 SetForegroundColour(GetParent()->GetForegroundColour());
907 SubclassWin(m_hWnd);
908 SetFont(*wxSMALL_FONT);
909 SetXComp(0);
910 SetYComp(0);
911 SetSize( nX, nY, nWidth, nHeight );
912 return true;
913 } // end of wxListCtrl::DoCreateControl
914
915 void wxListCtrl::UpdateStyle ()
916 {
917 if (GetHWND())
918 {
919 long lDummy;
920 DWORD dwStyleNew = ConvertToOS2Style( lDummy, GetWindowStyleFlag() );
921
922 dwStyleNew |= m_lBaseStyle;
923
924 //
925 // Get the current window style.
926 //
927 ULONG dwStyleOld = ::WinQueryWindowULong(GetHWND(), QWL_STYLE);
928
929 //
930 // Only set the window style if the view bits have changed.
931 //
932 if (dwStyleOld != dwStyleNew)
933 {
934 ::WinSetWindowULong(GetHWND(), QWL_STYLE, dwStyleNew);
935 }
936 }
937 } // end of wxListCtrl::UpdateStyle
938
939 void wxListCtrl::FreeAllInternalData ()
940 {
941 if (m_bAnyInternalData)
942 {
943 int n = GetItemCount();
944 int i = 0;
945
946 for (i = 0; i < n; i++)
947 DeleteInternalData(this, (long)i);
948 m_bAnyInternalData = false;
949 }
950 } // end of wxListCtrl::FreeAllInternalData
951
952 wxListCtrl::~wxListCtrl ()
953 {
954 FreeAllInternalData();
955 if (m_pTextCtrl )
956 {
957 m_pTextCtrl->SetHWND(0);
958 m_pTextCtrl->UnsubclassWin();
959 wxDELETE(m_pTextCtrl);
960 }
961
962 if (m_bOwnsImageListNormal)
963 delete m_pImageListNormal;
964 if (m_bOwnsImageListSmall)
965 delete m_pImageListSmall;
966 if (m_bOwnsImageListState)
967 delete m_pImageListState;
968 } // end of wxListCtrl::~wxListCtrl
969
970 // ----------------------------------------------------------------------------
971 // set/get/change style
972 // ----------------------------------------------------------------------------
973
974 // Add or remove a single window style
975 void wxListCtrl::SetSingleStyle (
976 long lStyle
977 , bool bAdd
978 )
979 {
980 long lFlag = GetWindowStyleFlag();
981
982 //
983 // Get rid of conflicting styles
984 //
985 if (bAdd)
986 {
987 if (lStyle & wxLC_MASK_TYPE)
988 lFlag = lFlag & ~wxLC_MASK_TYPE;
989 if (lStyle & wxLC_MASK_ALIGN )
990 lFlag = lFlag & ~wxLC_MASK_ALIGN;
991 if (lStyle & wxLC_MASK_SORT )
992 lFlag = lFlag & ~wxLC_MASK_SORT;
993 }
994 if (lFlag & lStyle)
995 {
996 if (!bAdd)
997 lFlag -= lStyle;
998 }
999 else
1000 {
1001 if (bAdd)
1002 {
1003 lFlag |= lStyle;
1004 }
1005 }
1006 m_windowStyle = lFlag;
1007 UpdateStyle();
1008 } // end of wxListCtrl::SetSingleStyle
1009
1010 // Set the whole window style
1011 void wxListCtrl::SetWindowStyleFlag (
1012 long lFlag
1013 )
1014 {
1015 m_windowStyle = lFlag;
1016 UpdateStyle();
1017 } // end of wxListCtrl::SetWindowStyleFlag
1018
1019 long wxListCtrl::ConvertToOS2Style (
1020 long& rOldStyle
1021 , long lStyle
1022 ) const
1023 {
1024 long lWstyle = 0L;
1025
1026 //
1027 // The only styles OS2 uses on creation are auto arrange, read only, and
1028 // and selection styles. This lib does not support OS/2 MINIRECORDCORE
1029 // or VERIFYPOINTER styles
1030 //
1031 if (lStyle & wxLC_AUTOARRANGE)
1032 lWstyle |= CCS_AUTOPOSITION;
1033 if (lStyle & wxLC_SINGLE_SEL)
1034 lWstyle |= CCS_SINGLESEL;
1035 else
1036 lWstyle |= CCS_EXTENDSEL;
1037 if (!(lStyle & wxLC_EDIT_LABELS))
1038 lWstyle |= CCS_READONLY;
1039 return lWstyle;
1040 } // end of wxListCtrl::ConvertToOS2Style
1041
1042 long wxListCtrl::ConvertArrangeToOS2Style (
1043 long lStyle
1044 )
1045 {
1046 long lWstyle = 0;
1047
1048 if (lStyle & wxLC_ALIGN_LEFT)
1049 {
1050 lWstyle |= CMA_LEFT;
1051 }
1052
1053 if (lStyle & wxLC_ALIGN_TOP)
1054 {
1055 lWstyle |= CMA_TOP;
1056 }
1057 return lWstyle;
1058 } // end of wxListCtrl::ConvertArrangeToOS2Style
1059
1060 long wxListCtrl::ConvertViewToOS2Style (
1061 long lStyle
1062 )
1063 {
1064 long lWstyle = CA_DRAWICON; // we will only use icons
1065
1066 if (lStyle & wxLC_ICON)
1067 {
1068 lWstyle |= CV_ICON;
1069 }
1070 if (lStyle & wxLC_SMALL_ICON)
1071 {
1072 lWstyle |= (CV_ICON | CV_MINI);
1073 }
1074 if (lStyle & wxLC_LIST)
1075 {
1076 lWstyle |= CV_TEXT;
1077 }
1078 if (lStyle & wxLC_REPORT)
1079 {
1080 lWstyle |= CV_DETAIL;
1081 }
1082 if (lStyle & wxLC_VIRTUAL)
1083 {
1084 lWstyle |= CA_OWNERDRAW;
1085 }
1086 if (lStyle & wxLC_AUTOARRANGE)
1087 {
1088 lWstyle |= CV_FLOW;
1089 }
1090 if (!(lStyle & wxLC_NO_HEADER))
1091 {
1092 lWstyle |= CA_DETAILSVIEWTITLES;
1093 }
1094 return lWstyle;
1095 } // end of wxListCtrl::ConvertViewToOS2Style
1096
1097 // ----------------------------------------------------------------------------
1098 // accessors
1099 // ----------------------------------------------------------------------------
1100
1101 // Sets the foreground, i.e. text, colour
1102 bool wxListCtrl::SetForegroundColour (const wxColour& rCol)
1103 {
1104 ULONG ulColor = wxColourToRGB(rCol);
1105
1106 if (!wxWindow::SetForegroundColour(rCol))
1107 return false;
1108
1109 ::WinSetPresParam( GetHWND()
1110 ,PP_FOREGROUNDCOLOR
1111 ,sizeof(ULONG)
1112 ,&ulColor
1113 );
1114 return true;
1115 } // end of wxListCtrl::SetForegroundColour
1116
1117 // Sets the background colour
1118 bool wxListCtrl::SetBackgroundColour ( const wxColour& rCol )
1119 {
1120 if (!wxWindow::SetBackgroundColour(rCol))
1121 return false;
1122
1123 //
1124 // We set the same colour for both the "empty" background and the items
1125 // background
1126 //
1127 ULONG ulColor = wxColourToRGB(rCol);
1128
1129 ::WinSetPresParam( GetHWND()
1130 ,PP_BACKGROUNDCOLOR
1131 ,sizeof(ULONG)
1132 ,&ulColor
1133 );
1134 return true;
1135 } // end of wxListCtrl::SetBackgroundColour
1136
1137 // Gets information about this column
1138 bool wxListCtrl::GetColumn ( int nCol, wxListItem& rItem ) const
1139 {
1140 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), nCol );
1141
1142 if (!pFieldInfo)
1143 return false;
1144 rItem.SetWidth(pFieldInfo->cxWidth);
1145 if ((rItem.GetMask() & wxLIST_MASK_TEXT) &&
1146 (pFieldInfo->flData & CFA_STRING) &&
1147 (pFieldInfo->pUserData != NULL))
1148 {
1149 rItem.SetText((char*)pFieldInfo->pUserData);
1150 }
1151 if (rItem.GetMask() & wxLIST_MASK_FORMAT )
1152 {
1153 if (pFieldInfo->flData & CFA_LEFT)
1154 rItem.m_format = wxLIST_FORMAT_LEFT;
1155 else if (pFieldInfo->flData & CFA_RIGHT)
1156 rItem.m_format = wxLIST_FORMAT_RIGHT;
1157 else if (pFieldInfo->flData & CFA_CENTER)
1158 rItem.m_format = wxLIST_FORMAT_CENTRE;
1159 }
1160 return true;
1161 } // end of wxListCtrl::GetColumn
1162
1163 // Sets information about this column
1164 bool wxListCtrl::SetColumn ( int nCol, wxListItem& rItem )
1165 {
1166 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum( GetHWND(), nCol );
1167 ConvertToOS2ListCol( nCol, rItem, pFieldInfo );
1168 //
1169 // Since we changed the field pointed to, we invalidate to see the result
1170 //
1171 ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO, NULL, NULL);
1172 return true;
1173 } // end of wxListCtrl::SetColumn
1174
1175 // Gets the column width
1176 int wxListCtrl::GetColumnWidth ( int nCol ) const
1177 {
1178 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), nCol );
1179
1180 if (!pFieldInfo)
1181 return 0;
1182 return((int)pFieldInfo->cxWidth);
1183 } // end of wxListCtrl::GetColumnWidth
1184
1185 // Sets the column width
1186 bool wxListCtrl::SetColumnWidth ( int nCol, int nWidth )
1187 {
1188 int nCol2 = nCol;
1189 int nWidth2 = nWidth;
1190
1191 if (GetWindowStyleFlag() & wxLC_LIST)
1192 nCol2 = -1;
1193
1194 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum( GetHWND(), nCol );
1195 pFieldInfo->cxWidth = nWidth;
1196 ::WinSendMsg(GetHWND(), CM_INVALIDATEDETAILFIELDINFO, NULL, NULL);
1197 return true;
1198 } // end of wxListCtrl::SetColumnWidth
1199
1200 // Gets the number of items that can fit vertically in the
1201 // visible area of the list control (list or report view)
1202 // or the total number of items in the list control (icon
1203 // or small icon view)
1204 int wxListCtrl::GetCountPerPage () const
1205 {
1206 QUERYRECORDRECT vQueryRect;
1207 CNRINFO vCnrInfo;
1208 RECTL vRectRecord;
1209 RECTL vRectControl;
1210 int nCount;
1211
1212 if (!::WinSendMsg( GetHWND()
1213 ,CM_QUERYCNRINFO
1214 ,MPFROMP(&vCnrInfo)
1215 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1216 ))
1217 return 0;
1218 memset(&vQueryRect, '\0', sizeof(QUERYRECORDRECT));
1219 vQueryRect.cb = sizeof(QUERYRECORDRECT);
1220 if (vCnrInfo.flWindowAttr & CV_ICON)
1221 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1222 else if (vCnrInfo.flWindowAttr & CV_NAME)
1223 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1224 else if (vCnrInfo.flWindowAttr & CV_TEXT)
1225 vQueryRect.fsExtent = CMA_TEXT;
1226 else if (vCnrInfo.flWindowAttr & CV_DETAIL)
1227 vQueryRect.fsExtent = CMA_TEXT;
1228 if (!::WinSendMsg( GetHWND()
1229 ,CM_QUERYRECORDRECT
1230 ,MPFROMP(&vRectRecord)
1231 ,MPFROMP(&vQueryRect)
1232 ))
1233 return 0;
1234 if (!::WinSendMsg( GetHWND()
1235 ,CM_QUERYVIEWPORTRECT
1236 ,MPFROMP(&vRectControl)
1237 ,MPFROM2SHORT(CMA_WINDOW, (USHORT)FALSE)
1238 ))
1239 return 0;
1240 nCount = (int)((int)((vRectControl.xRight - vRectControl.xLeft) / (vRectRecord.xRight - vRectRecord.xLeft)) *
1241 (int)((vRectControl.yTop - vRectControl.yBottom) / (vRectRecord.yTop - vRectRecord.yBottom))
1242 );
1243 if (nCount > (int)vCnrInfo.cFields)
1244 nCount = (int)vCnrInfo.cFields;
1245 return nCount;
1246 } // end of wxListCtrl::GetCountPerPage
1247
1248 // Gets the edit control for editing labels.
1249 wxTextCtrl* wxListCtrl::GetEditControl() const
1250 {
1251 return m_pTextCtrl;
1252 }
1253
1254 // Gets information about the item
1255 bool wxListCtrl::GetItem ( wxListItem& rInfo ) const
1256 {
1257 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), rInfo.GetId() );
1258
1259 //
1260 // Give NULL as hwnd as we already have everything we need
1261 //
1262 ConvertFromOS2ListItem( NULL, rInfo, pRecord );
1263 return true;
1264 } // end of wxListCtrl::GetItem
1265
1266 // Sets information about the item
1267 bool wxListCtrl::SetItem ( wxListItem& rInfo )
1268 {
1269 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND(), rInfo.GetColumn() );
1270 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), rInfo.GetId() );
1271
1272 ConvertToOS2ListItem( this
1273 ,rInfo
1274 ,pRecord
1275 ,pFieldInfo
1276 );
1277
1278 //
1279 // Check if setting attributes or lParam
1280 //
1281 if (rInfo.HasAttributes() || (rInfo.GetMask() & wxLIST_MASK_DATA))
1282 {
1283 //
1284 // Get internal item data
1285 // perhaps a cache here ?
1286 //
1287 CListItemInternalData* pData = GetInternalData( this
1288 ,rInfo.GetId()
1289 );
1290
1291 if (!pData)
1292 {
1293 //
1294 // Need to set it
1295 //
1296 m_bAnyInternalData = true;
1297 pData = new CListItemInternalData();
1298 pRecord->m_ulUserData = (unsigned long)pData;
1299 };
1300
1301 //
1302 // User data
1303 //
1304 if (rInfo.GetMask() & wxLIST_MASK_DATA)
1305 pData->m_lParam = (WXLPARAM)rInfo.GetData();
1306
1307 // attributes
1308 if (rInfo.HasAttributes())
1309 {
1310 if (pData->m_pAttr)
1311 *pData->m_pAttr = *rInfo.GetAttributes();
1312 else
1313 pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
1314 }
1315 pData->m_pMyRecord = pRecord; // they point to each other
1316 }
1317
1318 //
1319 // We need to update the item immediately to show the new image
1320 //
1321 bool bUpdateNow = (rInfo.GetMask() & wxLIST_MASK_IMAGE) != 0;
1322
1323 //
1324 // Check whether it has any custom attributes
1325 //
1326 if (rInfo.HasAttributes())
1327 {
1328 m_bHasAnyAttr = true;
1329
1330 //
1331 // If the colour has changed, we must redraw the item
1332 //
1333 bUpdateNow = true;
1334 }
1335 if (::WinIsWindowVisible(GetHWND()))
1336 {
1337 ::WinSendMsg( GetHWND()
1338 ,CM_INVALIDATERECORD
1339 ,MPFROMP(pRecord)
1340 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
1341 );
1342 RefreshItem(pRecord->m_ulItemId);
1343 }
1344 ::WinSendMsg( GetHWND()
1345 ,CM_INVALIDATEDETAILFIELDINFO
1346 ,NULL
1347 ,NULL
1348 );
1349 return true;
1350 } // end of wxListCtrl::SetItem
1351
1352 long wxListCtrl::SetItem (
1353 long lIndex
1354 , int nCol
1355 , const wxString& rsLabel
1356 , int nImageId
1357 )
1358 {
1359 wxListItem vInfo;
1360
1361 vInfo.m_text = rsLabel;
1362 vInfo.m_mask = wxLIST_MASK_TEXT;
1363 vInfo.m_itemId = lIndex;
1364 vInfo.m_col = nCol;
1365 if (nImageId > -1)
1366 {
1367 vInfo.m_image = nImageId;
1368 vInfo.m_mask |= wxLIST_MASK_IMAGE;
1369 }
1370 return SetItem(vInfo);
1371 } // end of wxListCtrl::SetItem
1372
1373 // Gets the item state
1374 int wxListCtrl::GetItemState (
1375 long lItem
1376 , long lStateMask
1377 ) const
1378 {
1379 wxListItem vInfo;
1380
1381 vInfo.m_mask = wxLIST_MASK_STATE;
1382 vInfo.m_stateMask = lStateMask;
1383 vInfo.m_itemId = lItem;
1384
1385 if (!GetItem(vInfo))
1386 return 0;
1387 return vInfo.m_state;
1388 } // end of wxListCtrl::GetItemState
1389
1390 // Sets the item state
1391 bool wxListCtrl::SetItemState ( long lItem, long lState, long lStateMask )
1392 {
1393 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
1394
1395 //
1396 // Don't use SetItem() here as it doesn't work with the virtual list
1397 // controls
1398 //
1399 ConvertToOS2Flags( lState, pRecord );
1400
1401 //
1402 // for the virtual list controls we need to refresh the previously focused
1403 // item manually when changing focus without changing selection
1404 // programmatically because otherwise it keeps its focus rectangle until
1405 // next repaint (yet another comctl32 bug)
1406 //
1407 long lFocusOld;
1408
1409 if (IsVirtual() &&
1410 (lStateMask & wxLIST_STATE_FOCUSED) &&
1411 (lState & wxLIST_STATE_FOCUSED) )
1412 {
1413 lFocusOld = GetNextItem( -1
1414 ,wxLIST_NEXT_ALL
1415 ,wxLIST_STATE_FOCUSED
1416 );
1417 }
1418 else
1419 {
1420 lFocusOld = -1;
1421 }
1422 ::WinSendMsg( GetHWND()
1423 ,CM_INVALIDATERECORD
1424 ,MPFROMP(pRecord)
1425 ,MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION | CMA_TEXTCHANGED)
1426 );
1427
1428 if (lFocusOld != -1)
1429 {
1430 //
1431 // No need to refresh the item if it was previously selected, it would
1432 // only result in annoying flicker
1433 //
1434 if (!(GetItemState( lFocusOld
1435 ,wxLIST_STATE_SELECTED
1436 ) & wxLIST_STATE_SELECTED))
1437 {
1438 RefreshItem(lFocusOld);
1439 }
1440 }
1441 return true;
1442 } // end of wxListCtrl::SetItemState
1443
1444 // Sets the item image
1445 bool wxListCtrl::SetItemImage (
1446 long lItem
1447 , int nImage
1448 , int WXUNUSED(nSelImage))
1449 {
1450 return SetItemColumnInfo(lItem, 0, nImage);
1451 } // end of wxListCtrl::SetItemImage
1452
1453 // Sets the item image
1454 bool wxListCtrl::SetItemColumnImage (
1455 long lItem
1456 , long lColumn
1457 , int nImage)
1458 {
1459 wxListItem vInfo;
1460
1461 vInfo.m_mask = wxLIST_MASK_IMAGE;
1462 vInfo.m_image = nImage;
1463 vInfo.m_itemId = lItem;
1464 vInfo.m_col = lColumn;
1465 return SetItem(vInfo);
1466 } // end of wxListCtrl::SetItemColumnImage
1467
1468 // Gets the item text
1469 wxString wxListCtrl::GetItemText (
1470 long lItem
1471 ) const
1472 {
1473 wxListItem vInfo;
1474
1475 vInfo.m_mask = wxLIST_MASK_TEXT;
1476 vInfo.m_itemId = lItem;
1477
1478 if (!GetItem(vInfo))
1479 return wxEmptyString;
1480 return vInfo.m_text;
1481 } // end of wxListCtrl::GetItemText
1482
1483 // Sets the item text
1484 void wxListCtrl::SetItemText (
1485 long lItem
1486 , const wxString& rsStr
1487 )
1488 {
1489 wxListItem vInfo;
1490
1491 vInfo.m_mask = wxLIST_MASK_TEXT;
1492 vInfo.m_itemId = lItem;
1493 vInfo.m_text = rsStr;
1494 SetItem(vInfo);
1495 } // end of wxListCtrl::SetItemText
1496
1497 // Gets the item data
1498 long wxListCtrl::GetItemData (
1499 long lItem
1500 ) const
1501 {
1502 wxListItem vInfo;
1503
1504 vInfo.m_mask = wxLIST_MASK_DATA;
1505 vInfo.m_itemId = lItem;
1506 if (!GetItem(vInfo))
1507 return 0;
1508 return vInfo.m_data;
1509 } // end of wxListCtrl::GetItemData
1510
1511 // Sets the item data
1512 bool wxListCtrl::SetItemPtrData (
1513 long lItem
1514 , wxUIntPtr lData
1515 )
1516 {
1517 wxListItem vInfo;
1518
1519 vInfo.m_mask = wxLIST_MASK_DATA;
1520 vInfo.m_itemId = lItem;
1521 vInfo.m_data = lData;
1522 return SetItem(vInfo);
1523 } // end of wxListCtrl::SetItemPtrData
1524
1525 // Gets the item rectangle
1526 bool wxListCtrl::GetItemRect ( long lItem,
1527 wxRect& rRect,
1528 int nCode ) const
1529 {
1530 bool bSuccess;
1531 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
1532 QUERYRECORDRECT vQueryRect;
1533 RECTL vRect;
1534 int nHeight;
1535
1536 if (!pRecord)
1537 return false;
1538 vQueryRect.cb = sizeof(QUERYRECORDRECT);
1539 vQueryRect.pRecord = &pRecord->m_vRecord;
1540 vQueryRect.fRightSplitWindow = TRUE;
1541 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1542 ::WinSendMsg( GetHWND()
1543 ,CM_QUERYRECORDRECT
1544 ,MPFROMP(&vRect)
1545 ,MPFROMP(&vQueryRect)
1546 );
1547 //
1548 // remember OS/2 is backwards
1549 //
1550 GetClientSize( NULL, &nHeight );
1551 rRect.x = vRect.xLeft;
1552 rRect.y = nHeight - vRect.yTop;
1553 rRect.width = vRect.xRight;
1554 rRect.height = nHeight - vRect.yBottom;
1555 bSuccess = true;
1556 return bSuccess;
1557 } // end of wxListCtrl::GetItemRect
1558
1559 // Gets the item position
1560 bool wxListCtrl::GetItemPosition ( long lItem, wxPoint& rPos ) const
1561 {
1562 bool bSuccess;
1563 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND() , lItem );
1564 QUERYRECORDRECT vQueryRect;
1565 RECTL vRect;
1566 int nHeight;
1567
1568 if (!pRecord)
1569 return false;
1570 vQueryRect.cb = sizeof(QUERYRECORDRECT);
1571 vQueryRect.pRecord = &pRecord->m_vRecord;
1572 vQueryRect.fRightSplitWindow = TRUE;
1573 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
1574 ::WinSendMsg( GetHWND()
1575 ,CM_QUERYRECORDRECT
1576 ,MPFROMP(&vRect)
1577 ,MPFROMP(&vQueryRect)
1578 );
1579 //
1580 // remember OS/2 is backwards
1581 //
1582 GetClientSize( NULL, &nHeight );
1583 rPos.x = vRect.xLeft;
1584 rPos.y = nHeight - vRect.yTop;
1585 bSuccess = true;
1586 return bSuccess;
1587 } // end of wxListCtrl::GetItemPosition
1588
1589 // Sets the item position.
1590 bool wxListCtrl::SetItemPosition ( long lItem, const wxPoint& rPos )
1591 {
1592 //
1593 // Items cannot be positioned in X/Y coord in OS/2
1594 //
1595 return false;
1596 } // end of wxListCtrl::SetItemPosition
1597
1598 // Gets the number of items in the list control
1599 int wxListCtrl::GetItemCount () const
1600 {
1601 CNRINFO vCnrInfo;
1602
1603 if (!::WinSendMsg( GetHWND()
1604 ,CM_QUERYCNRINFO
1605 ,MPFROMP(&vCnrInfo)
1606 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1607 ))
1608 return -1;
1609 return vCnrInfo.cRecords;
1610 } // end of wxListCtrl::GetItemCount
1611
1612 // Retrieves the spacing between icons in pixels.
1613 // If bIsSmall is true, gets the spacing for the small icon
1614 // view, otherwise the large icon view.
1615 int wxListCtrl::GetItemSpacing ( bool bIsSmall ) const
1616 {
1617 CNRINFO vCnrInfo;
1618
1619 if (!::WinSendMsg( GetHWND()
1620 ,CM_QUERYCNRINFO
1621 ,MPFROMP(&vCnrInfo)
1622 ,(MPARAM)(USHORT)sizeof(CNRINFO)
1623 ))
1624 return -1;
1625 return vCnrInfo.cyLineSpacing;
1626 } // end of wxListCtrl::GetItemSpacing
1627
1628 void wxListCtrl::SetItemTextColour (
1629 long lItem
1630 , const wxColour& rCol
1631 )
1632 {
1633 wxListItem vInfo;
1634
1635 vInfo.m_itemId = lItem;
1636 vInfo.SetTextColour(rCol);
1637 SetItem(vInfo);
1638 } // end of wxListCtrl::SetItemTextColour
1639
1640 wxColour wxListCtrl::GetItemTextColour (
1641 long lItem
1642 ) const
1643 {
1644 wxListItem vInfo;
1645
1646 vInfo.m_itemId = lItem;
1647 GetItem(vInfo);
1648 return vInfo.GetTextColour();
1649 } // end of wxListCtrl::GetItemTextColour
1650
1651 void wxListCtrl::SetItemBackgroundColour (
1652 long lItem
1653 , const wxColour& rCol
1654 )
1655 {
1656 wxListItem vInfo;
1657
1658 vInfo.m_itemId = lItem;
1659 vInfo.SetBackgroundColour(rCol);
1660 SetItem(vInfo);
1661 } // end of wxListCtrl::SetItemBackgroundColour
1662
1663 wxColour wxListCtrl::GetItemBackgroundColour (
1664 long lItem
1665 ) const
1666 {
1667 wxListItem vInfo;
1668
1669 vInfo.m_itemId = lItem;
1670 GetItem(vInfo);
1671 return vInfo.GetBackgroundColour();
1672 } // end of wxListCtrl::GetItemBackgroundColour
1673
1674 // Gets the number of selected items in the list control
1675 int wxListCtrl::GetSelectedItemCount () const
1676 {
1677 PMYRECORD pRecord = NULL;
1678 int nCount = 0;
1679 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1680 ,CM_QUERYRECORDEMPHASIS
1681 ,(MPARAM)CMA_FIRST
1682 ,(MPARAM)CRA_SELECTED
1683 ));
1684 if (pRecord)
1685 nCount++;
1686 else
1687 return 0;
1688 while (pRecord)
1689 {
1690 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
1691 ,CM_QUERYRECORDEMPHASIS
1692 ,MPFROMP(pRecord)
1693 ,(MPARAM)CRA_SELECTED
1694 ));
1695 if (pRecord)
1696 nCount++;
1697 }
1698 return nCount;
1699 } // end of wxListCtrl::GetSelectedItemCount
1700
1701 // Gets the text colour of the listview
1702 wxColour wxListCtrl::GetTextColour () const
1703 {
1704 wxColour vCol;
1705 ULONG ulColor;
1706
1707 ::WinQueryPresParam( GetHWND()
1708 ,PP_FOREGROUNDCOLOR
1709 ,0
1710 ,NULL
1711 ,sizeof(ULONG)
1712 ,&ulColor
1713 ,QPF_PURERGBCOLOR
1714 );
1715 vCol.Set(ulColor);
1716 return vCol;
1717 } // end of wxListCtrl::GetTextColour
1718
1719 // Sets the text colour of the listview
1720 void wxListCtrl::SetTextColour (
1721 const wxColour& rCol
1722 )
1723 {
1724 ULONG ulColor = wxColourToRGB(rCol);
1725
1726 ::WinSetPresParam( GetHWND()
1727 ,PP_FOREGROUNDCOLOR
1728 ,sizeof(ULONG)
1729 ,&ulColor
1730 );
1731 } // end of wxListCtrl::SetTextColour
1732
1733 // Gets the index of the topmost visible item when in
1734 // list or report view
1735 long wxListCtrl::GetTopItem () const
1736 {
1737 PMYRECORD pRecord = NULL;
1738 QUERYRECFROMRECT vQueryRect;
1739 RECTL vRect;
1740
1741 ::WinSendMsg( GetHWND()
1742 ,CM_QUERYVIEWPORTRECT
1743 ,MPFROMP(&vRect)
1744 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
1745 );
1746 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
1747 vQueryRect.rect = vRect;
1748 vQueryRect.fsSearch = CMA_PARTIAL;
1749
1750 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
1751 ,CM_QUERYRECORDFROMRECT
1752 ,(MPARAM)CMA_FIRST
1753 ,MPFROMP(&vQueryRect)
1754 );
1755
1756 if (!pRecord)
1757 return -1L;
1758 return (long)pRecord->m_ulItemId;
1759 } // end of wxListCtrl::GetTopItem
1760
1761 // Searches for an item, starting from 'item'.
1762 // 'geometry' is one of
1763 // wxLIST_NEXT_ABOVE/ALL/BELOW/LEFT/RIGHT.
1764 // 'state' is a state bit flag, one or more of
1765 // wxLIST_STATE_DROPHILITED/FOCUSED/SELECTED/CUT.
1766 // item can be -1 to find the first item that matches the
1767 // specified flags.
1768 // Returns the item or -1 if unsuccessful.
1769 long wxListCtrl::GetNextItem (
1770 long lItem
1771 , int WXUNUSED(nGeom)
1772 , int WXUNUSED(nState)
1773 ) const
1774 {
1775 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1776 ,lItem
1777 );
1778
1779 pRecord = (PMYRECORD)pRecord->m_vRecord.preccNextRecord;
1780 if (pRecord)
1781 return((long)pRecord->m_ulItemId);
1782 return -1L;
1783 } // end of wxListCtrl::GetNextItem
1784
1785 wxImageList* wxListCtrl::GetImageList (
1786 int nWhich
1787 ) const
1788 {
1789 if (nWhich == wxIMAGE_LIST_NORMAL )
1790 {
1791 return m_pImageListNormal;
1792 }
1793 else if (nWhich == wxIMAGE_LIST_SMALL )
1794 {
1795 return m_pImageListSmall;
1796 }
1797 else if (nWhich == wxIMAGE_LIST_STATE )
1798 {
1799 return m_pImageListState;
1800 }
1801 return NULL;
1802 } // end of wxListCtrl::GetImageList
1803
1804 void wxListCtrl::SetImageList ( wxImageList* pImageList,
1805 int nWhich )
1806 {
1807 if (nWhich == wxIMAGE_LIST_NORMAL)
1808 {
1809 if (m_bOwnsImageListNormal)
1810 delete m_pImageListNormal;
1811 m_pImageListNormal = pImageList;
1812 m_bOwnsImageListNormal = false;
1813 }
1814 else if (nWhich == wxIMAGE_LIST_SMALL)
1815 {
1816 if (m_bOwnsImageListSmall)
1817 delete m_pImageListSmall;
1818 m_pImageListSmall = pImageList;
1819 m_bOwnsImageListSmall = false;
1820 }
1821 else if (nWhich == wxIMAGE_LIST_STATE)
1822 {
1823 if (m_bOwnsImageListState)
1824 delete m_pImageListState;
1825 m_pImageListState = pImageList;
1826 m_bOwnsImageListState = false;
1827 }
1828 } // end of wxListCtrl::SetImageList
1829
1830 void wxListCtrl::AssignImageList ( wxImageList* pImageList, int nWhich )
1831 {
1832 SetImageList( pImageList, nWhich );
1833
1834 if (nWhich == wxIMAGE_LIST_NORMAL )
1835 m_bOwnsImageListNormal = true;
1836 else if (nWhich == wxIMAGE_LIST_SMALL )
1837 m_bOwnsImageListSmall = true;
1838 else if (nWhich == wxIMAGE_LIST_STATE )
1839 m_bOwnsImageListState = true;
1840 } // end of wxListCtrl::AssignImageList
1841
1842 // ----------------------------------------------------------------------------
1843 // Operations
1844 // ----------------------------------------------------------------------------
1845
1846 // Arranges the items
1847 bool wxListCtrl::Arrange ( int nFlag )
1848 {
1849 ULONG ulType = 0L;
1850 ULONG ulFlags = 0L;
1851
1852 if (nFlag == wxLIST_ALIGN_SNAP_TO_GRID)
1853 {
1854 ulType = CMA_ARRANGEGRID;
1855 if (nFlag == wxLIST_ALIGN_LEFT)
1856 ulFlags |= CMA_LEFT;
1857 else if (nFlag == wxLIST_ALIGN_TOP)
1858 ulFlags |= CMA_TOP;
1859 else if (nFlag == wxLIST_ALIGN_DEFAULT)
1860 ulFlags |= CMA_LEFT;
1861 }
1862 else
1863 ulType = CMA_ARRANGESTANDARD;
1864 ::WinSendMsg( GetHWND()
1865 ,CM_ARRANGE
1866 ,(MPARAM)ulType
1867 ,(MPARAM)ulFlags
1868 );
1869 //
1870 // We do not support CMA_ARRANGESELECTED
1871 //
1872 return true;
1873 } // end of wxListCtrl::Arrange
1874
1875 // Deletes an item
1876 bool wxListCtrl::DeleteItem ( long lItem )
1877 {
1878 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
1879 if (LONGFROMMR(::WinSendMsg( GetHWND()
1880 ,CM_REMOVERECORD
1881 ,(MPARAM)pRecord
1882 ,MPFROM2SHORT(1, CMA_FREE)
1883 )) == -1L)
1884 {
1885 return false;
1886 }
1887
1888 //
1889 // The virtual list control doesn't refresh itself correctly, help it
1890 //
1891 if (IsVirtual())
1892 {
1893 //
1894 // We need to refresh all the lines below the one which was deleted
1895 //
1896 wxRect vRectItem;
1897
1898 if (lItem > 0 && GetItemCount())
1899 {
1900 GetItemRect( lItem - 1
1901 ,vRectItem
1902 );
1903 }
1904 else
1905 {
1906 vRectItem.y = vRectItem.height = 0;
1907 }
1908 wxRect vRectWin = GetRect();
1909
1910 vRectWin.height = vRectWin.GetBottom() - vRectItem.GetBottom();
1911 vRectWin.y = vRectItem.GetBottom();
1912 RefreshRect(vRectWin);
1913 }
1914 return true;
1915 } // end of wxListCtrl::DeleteItem
1916
1917 // Deletes all items
1918 bool wxListCtrl::DeleteAllItems ()
1919 {
1920 return((LONG)::WinSendMsg( GetHWND()
1921 ,CM_REMOVERECORD
1922 ,NULL
1923 ,MPFROM2SHORT(0, CMA_FREE)
1924 ) != -1L);
1925 } // end of wxListCtrl::DeleteAllItems
1926
1927 // Deletes all items
1928 bool wxListCtrl::DeleteAllColumns ()
1929 {
1930 while (m_nColCount > 0)
1931 {
1932 DeleteColumn(m_nColCount - 1);
1933 m_nColCount--;
1934 }
1935
1936 wxASSERT_MSG(m_nColCount == 0, wxT("no columns should be left"));
1937 return true;
1938 } // end of wxListCtrl::DeleteAllColumns
1939
1940 // Deletes a column
1941 bool wxListCtrl::DeleteColumn ( int nCol )
1942 {
1943 bool bSuccess = false;
1944 PFIELDINFO pField = FindOS2ListFieldByColNum( GetHWND(), nCol );
1945 bSuccess = ((LONG)::WinSendMsg( GetHWND()
1946 ,CM_REMOVEDETAILFIELDINFO
1947 ,MPFROMP(pField)
1948 ,MPFROM2SHORT((SHORT)1, CMA_FREE)
1949 ) == -1L);
1950 if (bSuccess && (m_nColCount > 0))
1951 m_nColCount--;
1952 return bSuccess;
1953 } // end of wxListCtrl::DeleteColumn
1954
1955 // Clears items, and columns if there are any.
1956 void wxListCtrl::ClearAll ()
1957 {
1958 DeleteAllItems();
1959 if (m_nColCount > 0)
1960 DeleteAllColumns();
1961 } // end of wxListCtrl::ClearAll
1962
1963 //
1964 // OS/2 does not use a text control for its container labels. You merely
1965 // "open" a record for editting.
1966 //
1967 wxTextCtrl* wxListCtrl::EditLabel (
1968 long lItem
1969 , wxClassInfo* WXUNUSED(pTextControlClass)
1970 )
1971 {
1972 CNREDITDATA vEdit;
1973 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
1974 ,lItem
1975 );
1976
1977 vEdit.cb = sizeof(CNREDITDATA);
1978 vEdit.hwndCnr = GetHWND();
1979 vEdit.pRecord = &pRecord->m_vRecord;
1980 vEdit.pFieldInfo = NULL;
1981 vEdit.ppszText = NULL;
1982 vEdit.cbText = 0;
1983 vEdit.id = 0;
1984
1985 ::WinSendMsg( GetHWND()
1986 ,CM_OPENEDIT
1987 ,MPFROMP(&vEdit)
1988 ,(MPARAM)0
1989 );
1990 return m_pTextCtrl;
1991 } // end of wxListCtrl::EditLabel
1992
1993 // End label editing, optionally cancelling the edit. Under OS/2 you close
1994 // the record for editting
1995 bool wxListCtrl::EndEditLabel ( bool WXUNUSED(bCancel) )
1996 {
1997 ::WinSendMsg( GetHWND()
1998 ,CM_CLOSEEDIT
1999 ,(MPARAM)0
2000 ,(MPARAM)0
2001 );
2002 return true;
2003 } // end of wxListCtrl::EndEditLabel
2004
2005 // Ensures this item is visible
2006 bool wxListCtrl::EnsureVisible ( long lItem )
2007 {
2008 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND(), lItem );
2009 ::WinSendMsg( GetHWND()
2010 ,CM_INVALIDATERECORD
2011 ,MPFROMP(pRecord)
2012 ,MPFROM2SHORT((SHORT)1, CMA_NOREPOSITION)
2013 );
2014 return true;
2015 } // end of wxListCtrl::EnsureVisible
2016
2017 // Find an item whose label matches this string, starting from the item after 'start'
2018 // or the beginning if 'start' is -1.
2019 long wxListCtrl::FindItem (
2020 long lStart
2021 , const wxString& rsStr
2022 , bool bPartial
2023 )
2024 {
2025 CNRINFO vCnrInfo;
2026 SEARCHSTRING vSearch;
2027 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2028 ,lStart
2029 );
2030 ULONG ulFlag;
2031
2032
2033 if (!::WinSendMsg( GetHWND()
2034 ,CM_QUERYCNRINFO
2035 ,MPFROMP(&vCnrInfo)
2036 ,(MPARAM)(USHORT)sizeof(CNRINFO)
2037 ))
2038 return -1L;
2039
2040 if (vCnrInfo.flWindowAttr & CV_ICON)
2041 ulFlag = CV_ICON;
2042 if (vCnrInfo.flWindowAttr & CV_NAME)
2043 ulFlag = CV_NAME;
2044 if (vCnrInfo.flWindowAttr & CV_TEXT)
2045 ulFlag = CV_TEXT;
2046 if (vCnrInfo.flWindowAttr & CV_DETAIL)
2047 ulFlag = CV_DETAIL;
2048 if (!bPartial)
2049 ulFlag |= CV_EXACTLENGTH;
2050
2051 vSearch.cb = sizeof(SEARCHSTRING);
2052 vSearch.pszSearch = (char*)rsStr.c_str();
2053 vSearch.fsPrefix = TRUE;
2054 vSearch.fsCaseSensitive = TRUE;
2055 vSearch.usView = ulFlag;
2056
2057 if (lStart == -1)
2058 {
2059 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2060 ,CM_SEARCHSTRING
2061 ,MPFROMP(&vSearch)
2062 ,(MPARAM)CMA_FIRST
2063 );
2064 }
2065 else
2066 {
2067 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2068 ,CM_SEARCHSTRING
2069 ,MPFROMP(&vSearch)
2070 ,MPFROMP(pRecord)
2071 );
2072 }
2073 if (!pRecord)
2074 return -1L;
2075 return pRecord->m_ulItemId;
2076 } // end of wxListCtrl::FindItem
2077
2078 // Find an item whose data matches this data, starting from the item after 'start'
2079 // or the beginning if 'start' is -1.
2080 long wxListCtrl::FindItem (
2081 long lStart
2082 , long lData
2083 )
2084 {
2085 long lIdx = lStart + 1;
2086 long lCount = GetItemCount();
2087
2088 while (lIdx < lCount)
2089 {
2090 if (GetItemData(lIdx) == lData)
2091 return lIdx;
2092 lIdx++;
2093 };
2094 return -1;
2095 } // end of wxListCtrl::FindItem
2096
2097 // Find an item nearest this position in the specified direction, starting from
2098 // the item after 'start' or the beginning if 'start' is -1.
2099 long wxListCtrl::FindItem (
2100 long lStart
2101 , const wxPoint& rPoint
2102 , int nDirection
2103 )
2104 {
2105 RECTL vRect;
2106 QUERYRECORDRECT vQueryRect;
2107 PMYRECORD pRecord = FindOS2ListRecordByID( GetHWND()
2108 ,lStart
2109 );
2110 CNRINFO vCnrInfo;
2111 ULONG i;
2112 wxRect vLibRect;
2113
2114 if (!::WinSendMsg( GetHWND()
2115 ,CM_QUERYCNRINFO
2116 ,MPFROMP(&vCnrInfo)
2117 ,(MPARAM)(USHORT)sizeof(CNRINFO)
2118 ))
2119 return -1L;
2120
2121 vQueryRect.cb = sizeof(QUERYRECORDRECT);
2122 vQueryRect.pRecord = &pRecord->m_vRecord;
2123 vQueryRect.fRightSplitWindow = TRUE;
2124 vQueryRect.fsExtent = CMA_ICON | CMA_TEXT;
2125
2126 ::WinSendMsg( GetHWND()
2127 ,CM_QUERYRECORDRECT
2128 ,MPFROMP(&vRect)
2129 ,MPFROMP(&vQueryRect)
2130 );
2131 vLibRect.SetLeft(vRect.xLeft);
2132 vLibRect.SetTop(vRect.yTop);
2133 vLibRect.SetRight(vRect.xRight);
2134 vLibRect.SetBottom(vRect.yBottom);
2135 if (vLibRect.Contains(rPoint))
2136 return pRecord->m_ulItemId;
2137
2138 for (i = lStart + 1; i < vCnrInfo.cRecords; i++)
2139 {
2140 pRecord = (PMYRECORD)PVOIDFROMMR(::WinSendMsg( GetHWND()
2141 ,CM_QUERYRECORD
2142 ,MPFROMP(pRecord)
2143 ,MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER)
2144 ));
2145 vQueryRect.pRecord = (PRECORDCORE)pRecord;
2146 ::WinSendMsg( GetHWND()
2147 ,CM_QUERYRECORDRECT
2148 ,MPFROMP(&vRect)
2149 ,MPFROMP(&vQueryRect)
2150 );
2151 vLibRect.SetLeft(vRect.xLeft);
2152 vLibRect.SetTop(vRect.yTop);
2153 vLibRect.SetRight(vRect.xRight);
2154 vLibRect.SetBottom(vRect.yBottom);
2155 if (vLibRect.Contains(rPoint))
2156 return pRecord->m_ulItemId;
2157 }
2158 return -1L;
2159 } // end of wxListCtrl::FindItem
2160
2161 // Determines which item (if any) is at the specified point,
2162 // giving details in 'flags' (see wxLIST_HITTEST_... flags above)
2163 long wxListCtrl::HitTest (
2164 const wxPoint& rPoint
2165 , int& WXUNUSED(rFlags)
2166 )
2167 {
2168 PMYRECORD pRecord = NULL;
2169 QUERYRECFROMRECT vQueryRect;
2170 RECTL vRect;
2171 long lHeight;
2172
2173 //
2174 // Get height for OS/2 point conversion
2175 //
2176 ::WinSendMsg( GetHWND()
2177 ,CM_QUERYVIEWPORTRECT
2178 ,MPFROMP(&vRect)
2179 ,MPFROM2SHORT(CMA_WINDOW, TRUE)
2180 );
2181 lHeight = vRect.yTop - vRect.yBottom;
2182
2183 //
2184 // For now just try and get a record in the general vicinity and forget
2185 // the flag
2186 //
2187 vRect.xLeft = rPoint.x - 2;
2188 vRect.xRight = rPoint.x + 2;
2189 vRect.yTop = (lHeight - rPoint.y) + 2;
2190 vRect.yBottom = (lHeight - rPoint.y) - 2;
2191
2192 vQueryRect.cb = sizeof(QUERYRECFROMRECT);
2193 vQueryRect.rect = vRect;
2194 vQueryRect.fsSearch = CMA_PARTIAL;
2195
2196 pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2197 ,CM_QUERYRECORDFROMRECT
2198 ,(MPARAM)CMA_FIRST
2199 ,MPFROMP(&vQueryRect)
2200 );
2201
2202 if (!pRecord)
2203 return -1L;
2204 return pRecord->m_ulItemId;
2205 } // end of wxListCtrl::HitTest
2206
2207 // Inserts an item, returning the index of the new item if successful,
2208 // -1 otherwise.
2209 long wxListCtrl::InsertItem (
2210 wxListItem& rInfo
2211 )
2212 {
2213 wxASSERT_MSG( !IsVirtual(), wxT("can't be used with virtual controls") );
2214
2215 PFIELDINFO pFieldInfo = FindOS2ListFieldByColNum ( GetHWND()
2216 ,rInfo.GetColumn()
2217 );
2218 PMYRECORD pRecordAfter = NULL;
2219 PMYRECORD pRecord = (PMYRECORD)::WinSendMsg( GetHWND()
2220 ,CM_ALLOCRECORD
2221 ,MPFROMLONG(sizeof(MYRECORD) - sizeof(RECORDCORE))
2222 ,MPFROMSHORT(1)
2223 );
2224
2225 ConvertToOS2ListItem( this
2226 ,rInfo
2227 ,pRecord
2228 ,pFieldInfo
2229 );
2230
2231 if (rInfo.GetId() > 0)
2232 pRecordAfter = FindOS2ListRecordByID( GetHWND()
2233 ,rInfo.GetId() - 1
2234 );
2235
2236 RECORDINSERT vInsert;
2237
2238 vInsert.cb = sizeof(RECORDINSERT);
2239 vInsert.pRecordParent = NULL;
2240 if (!pRecordAfter)
2241 vInsert.pRecordOrder = (PRECORDCORE)CMA_FIRST;
2242 else
2243 vInsert.pRecordOrder = (PRECORDCORE)pRecordAfter;
2244 vInsert.zOrder = CMA_TOP;
2245 vInsert.cRecordsInsert = 1;
2246 vInsert.fInvalidateRecord = TRUE;
2247
2248 //
2249 // Check whether we need to allocate our internal data
2250 //
2251 bool bNeedInternalData = ((rInfo.GetMask() & wxLIST_MASK_DATA) ||
2252 rInfo.HasAttributes()
2253 );
2254 if (bNeedInternalData)
2255 {
2256 m_bAnyInternalData = true;
2257
2258 //
2259 // Internal stucture that manages data
2260 //
2261 CListItemInternalData* pData = new CListItemInternalData();
2262
2263 pRecord->m_ulUserData = (unsigned long)pData;
2264 if (rInfo.GetMask() & wxLIST_MASK_DATA)
2265 pData->m_lParam = (WXLPARAM)rInfo.GetData();
2266
2267 //
2268 // Check whether it has any custom attributes
2269 //
2270 if (rInfo.HasAttributes())
2271 {
2272 //
2273 // Take copy of attributes
2274 //
2275 pData->m_pAttr = new wxListItemAttr(*rInfo.GetAttributes());
2276 }
2277 }
2278 if (!::WinSendMsg( GetHWND()
2279 ,CM_INSERTRECORD
2280 ,MPFROMP(pRecord)
2281 ,MPFROMP(&vInsert)
2282 ))
2283 return -1;
2284 //
2285 // OS/2 must mannually bump the index's of following records
2286 //
2287 BumpRecordIds( GetHWND()
2288 ,pRecord
2289 );
2290 ::WinSendMsg( GetHWND()
2291 ,CM_INVALIDATEDETAILFIELDINFO
2292 ,NULL
2293 ,NULL
2294 );
2295 return pRecord->m_ulItemId;
2296 } // end of wxListCtrl::InsertItem
2297
2298 long wxListCtrl::InsertItem (
2299 long lIndex
2300 , const wxString& rsLabel
2301 )
2302 {
2303 wxListItem vInfo;
2304
2305 memset(&vInfo, '\0', sizeof(wxListItem));
2306 vInfo.m_text = rsLabel;
2307 vInfo.m_mask = wxLIST_MASK_TEXT;
2308 vInfo.m_itemId = lIndex;
2309 return InsertItem(vInfo);
2310 } // end of wxListCtrl::InsertItem
2311
2312 // Inserts an image item
2313 long wxListCtrl::InsertItem (
2314 long lIndex
2315 , int nImageIndex
2316 )
2317 {
2318 wxListItem vInfo;
2319
2320 vInfo.m_image = nImageIndex;
2321 vInfo.m_mask = wxLIST_MASK_IMAGE;
2322 vInfo.m_itemId = lIndex;
2323 return InsertItem(vInfo);
2324 } // end of wxListCtrl::InsertItem
2325
2326 // Inserts an image/string item
2327 long wxListCtrl::InsertItem (
2328 long lIndex
2329 , const wxString& rsLabel
2330 , int nImageIndex
2331 )
2332 {
2333 wxListItem vInfo;
2334
2335 vInfo.m_image = nImageIndex;
2336 vInfo.m_text = rsLabel;
2337 vInfo.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
2338 vInfo.m_itemId = lIndex;
2339 return InsertItem(vInfo);
2340 } // end of wxListCtrl::InsertItem
2341
2342 // For details view mode (only), inserts a column.
2343 long wxListCtrl::InsertColumn (
2344 long lCol
2345 , wxListItem& rItem
2346 )
2347 {
2348 bool bSuccess;
2349 PFIELDINFO pField = (PFIELDINFO)::WinSendMsg( GetHWND()
2350 ,CM_ALLOCDETAILFIELDINFO
2351 ,MPFROMLONG(1)
2352 ,NULL
2353 );
2354 PFIELDINFO pFieldAfter = FindOS2ListFieldByColNum ( GetHWND()
2355 ,lCol - 1
2356 );
2357 FIELDINFOINSERT vInsert;
2358
2359 ConvertToOS2ListCol ( lCol
2360 ,rItem
2361 ,pField
2362 );
2363
2364 vInsert.cb = sizeof(FIELDINFOINSERT);
2365 vInsert.pFieldInfoOrder = pFieldAfter;
2366 vInsert.fInvalidateFieldInfo = TRUE;
2367 vInsert.cFieldInfoInsert = 1;
2368
2369 bSuccess = ::WinSendMsg( GetHWND()
2370 ,CM_INSERTDETAILFIELDINFO
2371 ,MPFROMP(pField)
2372 ,MPFROMP(&vInsert)
2373 ) != (MRESULT)0;
2374 return bSuccess;
2375 } // end of wxListCtrl::InsertColumn
2376
2377 long wxListCtrl::InsertColumn (
2378 long lCol
2379 , const wxString& rsHeading
2380 , int nFormat
2381 , int nWidth
2382 )
2383 {
2384 wxListItem vItem;
2385
2386 vItem.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
2387 vItem.m_text = rsHeading;
2388 if (nWidth > -1)
2389 {
2390 vItem.m_mask |= wxLIST_MASK_WIDTH;
2391 vItem.m_width = nWidth;
2392 }
2393 vItem.m_format = nFormat;
2394
2395 return InsertColumn( lCol
2396 ,vItem
2397 );
2398 } // end of wxListCtrl::InsertColumn
2399
2400 // scroll the control by the given number of pixels (exception: in list view,
2401 // dx is interpreted as number of columns)
2402 bool wxListCtrl::ScrollList ( int nDx, int nDy )
2403 {
2404 if (nDx > 0)
2405 ::WinSendMsg( GetHWND()
2406 ,CM_SCROLLWINDOW
2407 ,(MPARAM)CMA_HORIZONTAL
2408 ,(MPARAM)nDx
2409 );
2410 if (nDy > 0)
2411 ::WinSendMsg( GetHWND()
2412 ,CM_SCROLLWINDOW
2413 ,(MPARAM)CMA_VERTICAL
2414 ,(MPARAM)nDy
2415 );
2416 return true;
2417 } // end of wxListCtrl::ScrollList
2418
2419 bool wxListCtrl::SortItems ( wxListCtrlCompare fn, long lData )
2420 {
2421 SInternalDataSort vInternalData;
2422
2423 vInternalData.m_fnUser = fn;
2424 vInternalData.m_lData = lData;
2425
2426 // WPARAM cast is needed for mingw/cygwin
2427 if (!::WinSendMsg( GetHWND()
2428 ,CM_SORTRECORD
2429 ,(PFN)InternalDataCompareFunc
2430 ,(PVOID)&vInternalData
2431 ))
2432 {
2433 wxLogDebug(wxT("CM_SORTRECORD failed"));
2434 return false;
2435 }
2436 return true;
2437 } // end of wxListCtrl::SortItems
2438
2439 // ----------------------------------------------------------------------------
2440 // message processing
2441 // ----------------------------------------------------------------------------
2442
2443 bool wxListCtrl::OS2Command ( WXUINT uCmd, WXWORD wId )
2444 {
2445 if (uCmd == CN_ENDEDIT)
2446 {
2447 wxCommandEvent vEvent( wxEVT_TEXT, wId );
2448
2449 vEvent.SetEventObject( this );
2450 ProcessCommand(vEvent);
2451 return true;
2452 }
2453 else if (uCmd == CN_KILLFOCUS)
2454 {
2455 wxCommandEvent vEvent( wxEVT_KILL_FOCUS, wId );
2456 vEvent.SetEventObject( this );
2457 ProcessCommand(vEvent);
2458 return true;
2459 }
2460 else
2461 return false;
2462 } // end of wxListCtrl::OS2Command
2463
2464 // Necessary for drawing hrules and vrules, if specified
2465 void wxListCtrl::OnPaint ( wxPaintEvent& rEvent )
2466 {
2467 wxPaintDC vDc(this);
2468 wxPen vPen(wxSystemSettings::GetColour( wxSYS_COLOUR_3DLIGHT)
2469 ,1
2470 ,wxSOLID
2471 );
2472 wxSize vClientSize = GetClientSize();
2473 wxRect vItemRect;
2474 int nItemCount = GetItemCount();
2475 int nCy = 0;
2476 int i;
2477 bool bDrawHRules = ((GetWindowStyle() & wxLC_HRULES) != 0);
2478 bool bDrawVRules = ((GetWindowStyle() & wxLC_VRULES) != 0);
2479
2480 wxControl::OnPaint(rEvent);
2481
2482 //
2483 // Reset the device origin since it may have been set
2484 //
2485 vDc.SetDeviceOrigin(0, 0);
2486 if (!bDrawHRules && !bDrawVRules)
2487 return;
2488 if ((GetWindowStyle() & wxLC_REPORT) == 0)
2489 return;
2490 vDc.SetPen(vPen);
2491 vDc.SetBrush(*wxTRANSPARENT_BRUSH);
2492
2493 if (bDrawHRules)
2494 {
2495 long lTop = GetTopItem();
2496
2497 for (i = lTop; i < lTop + GetCountPerPage() + 1; i++)
2498 {
2499 if (GetItemRect( i
2500 ,vItemRect
2501 ))
2502 {
2503 nCy = vItemRect.GetTop();
2504 if (i != 0) // Don't draw the first one
2505 {
2506 vDc.DrawLine( 0
2507 ,nCy
2508 ,vClientSize.x
2509 ,nCy
2510 );
2511 }
2512 // Draw last line
2513 if (i == nItemCount - 1)
2514 {
2515 nCy = vItemRect.GetBottom();
2516 vDc.DrawLine( 0
2517 ,nCy
2518 ,vClientSize.x
2519 ,nCy
2520 );
2521 }
2522 }
2523 }
2524 }
2525 i = nItemCount - 1;
2526 if (bDrawVRules && (i > -1))
2527 {
2528 wxRect vFirstItemRect;
2529
2530 GetItemRect( 0
2531 ,vFirstItemRect
2532 );
2533 if (GetItemRect( i
2534 ,vItemRect
2535 ))
2536 {
2537 int nCol;
2538 int nX = vItemRect.GetX();
2539
2540 for (nCol = 0; nCol < GetColumnCount(); nCol++)
2541 {
2542 int nColWidth = GetColumnWidth(nCol);
2543
2544 nX += nColWidth ;
2545 vDc.DrawLine( nX - 1
2546 ,vFirstItemRect.GetY() - 2
2547 ,nX - 1
2548 ,vItemRect.GetBottom()
2549 );
2550 }
2551 }
2552 }
2553 } // end of wxListCtrl::OnPaint
2554
2555 // ----------------------------------------------------------------------------
2556 // virtual list controls
2557 // ----------------------------------------------------------------------------
2558
2559 wxString wxListCtrl::OnGetItemText (
2560 long WXUNUSED(lItem)
2561 , long WXUNUSED(lCol)
2562 ) const
2563 {
2564 // this is a pure virtual function, in fact - which is not really pure
2565 // because the controls which are not virtual don't need to implement it
2566 wxFAIL_MSG( wxT("not supposed to be called") );
2567 return wxEmptyString;
2568 } // end of wxListCtrl::OnGetItemText
2569
2570 int wxListCtrl::OnGetItemImage (
2571 long WXUNUSED(lItem)
2572 ) const
2573 {
2574 // same as above
2575 wxFAIL_MSG( wxT("not supposed to be called") );
2576 return -1;
2577 } // end of wxListCtrl::OnGetItemImage
2578
2579 int wxListCtrl::OnGetItemColumnImage (
2580 long lItem,
2581 long lColumn
2582 ) const
2583 {
2584 if (!lColumn)
2585 return OnGetItemImage(lItem);
2586
2587 return -1;
2588 } // end of wxListCtrl::OnGetItemColumnImage
2589
2590 void wxListCtrl::SetItemCount (
2591 long lCount
2592 )
2593 {
2594 wxASSERT_MSG( IsVirtual(), wxT("this is for virtual controls only") );
2595
2596 //
2597 // Cannot explicitly set the record count in OS/2
2598 //
2599 } // end of wxListCtrl::SetItemCount
2600
2601 void wxListCtrl::RefreshItem (
2602 long lItem
2603 )
2604 {
2605 wxRect vRect;
2606
2607 GetItemRect( lItem
2608 ,vRect
2609 );
2610 RefreshRect(vRect);
2611 } // end of wxListCtrl::RefreshItem
2612
2613 void wxListCtrl::RefreshItems ( long lItemFrom, long lItemTo )
2614 {
2615 wxRect vRect1;
2616 wxRect vRect2;
2617
2618 GetItemRect( lItemFrom , vRect1 );
2619 GetItemRect( lItemTo , vRect2 );
2620
2621 wxRect vRect = vRect1;
2622
2623 vRect.height = vRect2.GetBottom() - vRect1.GetTop();
2624 RefreshRect(vRect);
2625 } // end of wxListCtrl::RefreshItems
2626
2627 MRESULT wxListCtrl::OS2WindowProc( WXUINT uMsg,
2628 WXWPARAM wParam,
2629 WXLPARAM lParam )
2630 {
2631 bool bProcessed = false;
2632 MRESULT lRc;
2633 wxListEvent vEvent( wxEVT_NULL
2634 ,m_windowId
2635 );
2636 wxEventType vEventType = wxEVT_NULL;
2637 PCNRDRAGINIT pDragInit = NULL;
2638 PCNREDITDATA pEditData = NULL;
2639 PNOTIFYRECORDENTER pNotifyEnter = NULL;
2640
2641 vEvent.SetEventObject(this);
2642 switch (uMsg)
2643 {
2644 case WM_CONTROL:
2645 //
2646 // First off let's set some internal data
2647 //
2648 switch(SHORT2FROMMP(wParam))
2649 {
2650 case CN_INITDRAG:
2651 case CN_DRAGOVER:
2652 case CN_DRAGAFTER:
2653 {
2654 CListItemInternalData* pInternaldata = (CListItemInternalData *)lParam;
2655
2656 if (pInternaldata)
2657 {
2658 wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
2659
2660 pItem->SetData((long)pInternaldata->m_lParam);
2661 }
2662 }
2663 break;
2664 }
2665 //
2666 // Now let's go through the codes we're interested in
2667 //
2668 switch(SHORT2FROMMP(wParam))
2669 {
2670 case CN_INITDRAG:
2671 pDragInit = (PCNRDRAGINIT)lParam;
2672 if (pDragInit)
2673 {
2674 PMYRECORD pRecord = (PMYRECORD)pDragInit->pRecord;
2675
2676 vEventType = wxEVT_LIST_BEGIN_RDRAG;
2677 vEvent.m_itemIndex = pRecord->m_ulItemId;
2678 vEvent.m_pointDrag.x = pDragInit->x;
2679 vEvent.m_pointDrag.y = pDragInit->y;
2680 }
2681 break;
2682
2683 case CN_BEGINEDIT:
2684 pEditData = (PCNREDITDATA)lParam;
2685 if (pEditData)
2686 {
2687 vEventType = wxEVT_LIST_BEGIN_LABEL_EDIT;
2688 ConvertFromOS2ListItem( GetHWND()
2689 ,(wxListItem &)vEvent.GetItem()
2690 ,(PMYRECORD)pEditData->pRecord
2691 );
2692 vEvent.m_itemIndex = vEvent.GetItem().GetId();
2693 }
2694 break;
2695
2696 case CN_ENDEDIT:
2697 pEditData = (PCNREDITDATA)lParam;
2698 if (pEditData)
2699 {
2700 vEventType = wxEVT_LIST_END_LABEL_EDIT;
2701 ConvertFromOS2ListItem( GetHWND()
2702 ,(wxListItem &)vEvent.GetItem()
2703 ,(PMYRECORD)pEditData->pRecord
2704 );
2705 if (pEditData->cbText == 0)
2706 return (MRESULT)FALSE;
2707 vEvent.m_itemIndex = vEvent.GetItem().GetId();
2708 }
2709 break;
2710
2711 case CN_ENTER:
2712 pNotifyEnter = (PNOTIFYRECORDENTER)lParam;
2713 if (pNotifyEnter)
2714 {
2715 wxListItem* pItem = (wxListItem*)&vEvent.GetItem();
2716 PMYRECORD pMyRecord = (PMYRECORD)pNotifyEnter->pRecord;
2717
2718 vEventType = wxEVT_LIST_ITEM_ACTIVATED;
2719 vEvent.m_itemIndex = pMyRecord->m_ulItemId;
2720 pItem->SetText(GetItemText(pMyRecord->m_ulItemId));
2721 pItem->SetData(GetItemData(pMyRecord->m_ulItemId));
2722 }
2723 break;
2724
2725 //
2726 // Add the CN_DROP messages for Direct Manipulation
2727 //
2728 }
2729 vEvent.SetEventType(vEventType);
2730 bProcessed = HandleWindowEvent(vEvent);
2731 break;
2732 }
2733 if (!bProcessed)
2734 lRc = wxControl::OS2WindowProc( uMsg
2735 ,wParam
2736 ,lParam
2737 );
2738 return lRc;
2739 } // end of wxListCtrl::WindowProc
2740
2741 #endif // wxUSE_LISTCTRL