ReactOS 0.4.16-dev-1946-g52006dd
listbox.c
Go to the documentation of this file.
1/*
2 * Listbox controls
3 *
4 * Copyright 1996 Alexandre Julliard
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 * NOTES
21 *
22 * This code was audited for completeness against the documented features
23 * of Comctl32.dll version 6.0 on Oct. 9, 2004, by Dimitrie O. Paun.
24 *
25 * Unless otherwise noted, we believe this code to be complete, as per
26 * the specification mentioned above.
27 * If you discover missing features, or bugs, please note them below.
28 *
29 * TODO:
30 * - LBS_NODATA ReactOS
31 */
32
33#include <user32.h>
34
36
37/* Items array granularity */
38#define LB_ARRAY_GRANULARITY 16
39
40/* Scrolling timeout in ms */
41#define LB_SCROLL_TIMEOUT 50
42
43/* Listbox system timer id */
44#define LB_TIMER_ID 2
45
46/* flag listbox changed while setredraw false - internal style */
47#define LBS_DISPLAYCHANGED 0x80000000
48
49/* Item structure */
50typedef struct
51{
52 LPWSTR str; /* Item text */
53 BOOL selected; /* Is item selected? */
54 UINT height; /* Item height (only for OWNERDRAWVARIABLE) */
55 ULONG_PTR data; /* User data */
57
58/* Listbox structure */
59typedef struct
60{
61 HWND self; /* Our own window handle */
62 HWND owner; /* Owner window to send notifications to */
63 UINT style; /* Window style */
64 INT width; /* Window width */
65 INT height; /* Window height */
66 LB_ITEMDATA *items; /* Array of items */
67 INT nb_items; /* Number of items */
68 INT top_item; /* Top visible item */
69 INT selected_item; /* Selected item */
70 INT focus_item; /* Item that has the focus */
71 INT anchor_item; /* Anchor item for extended selection */
72 INT item_height; /* Default item height */
73 INT page_size; /* Items per listbox page */
74 INT column_width; /* Column width for multi-column listboxes */
75 INT horz_extent; /* Horizontal extent */
76 INT horz_pos; /* Horizontal position */
77 INT nb_tabs; /* Number of tabs in array */
78 INT *tabs; /* Array of tabs */
79 INT avg_char_width; /* Average width of characters */
80 INT wheel_remain; /* Left over scroll amount */
81 BOOL caret_on; /* Is caret on? */
82 BOOL captured; /* Is mouse captured? */
83 BOOL in_focus;
84 HFONT font; /* Current font */
85 LCID locale; /* Current locale for string comparisons */
86 LPHEADCOMBO lphc; /* ComboLBox */
87 LONG UIState; // REACTOS
88} LB_DESCR;
89
90
91#define IS_OWNERDRAW(descr) \
92 ((descr)->style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE))
93
94#define HAS_STRINGS(descr) \
95 (!IS_OWNERDRAW(descr) || ((descr)->style & LBS_HASSTRINGS))
96
97
98#define IS_MULTISELECT(descr) \
99 ((descr)->style & (LBS_MULTIPLESEL|LBS_EXTENDEDSEL) && \
100 !((descr)->style & LBS_NOSEL))
101
102#define SEND_NOTIFICATION(descr,code) \
103 (SendMessageW( (descr)->owner, WM_COMMAND, \
104 MAKEWPARAM( GetWindowLongPtrW((descr->self),GWLP_ID), (code)), (LPARAM)(descr->self) ))
105
106#define ISWIN31 (LOWORD(GetVersion()) == 0x0a03)
107
108/* Current timer status */
109typedef enum
110{
117
119
121
122/*********************************************************************
123 * listbox class descriptor
124 */
125static const WCHAR listboxW[] = {'L','i','s','t','B','o','x',0};
127{
128 listboxW, /* name */
129 CS_DBLCLKS /*| CS_PARENTDC*/, /* style */
130 ListBoxWndProcA, /* procA */
131 ListBoxWndProcW, /* procW */
132 sizeof(LB_DESCR *), /* extra */
133 IDC_ARROW, /* cursor */
134 0 /* brush */
135};
136
137
138/*********************************************************************
139 * combolbox class descriptor
140 */
141static const WCHAR combolboxW[] = {'C','o','m','b','o','L','B','o','x',0};
143{
144 combolboxW, /* name */
145 CS_DBLCLKS | CS_SAVEBITS, /* style */
146 ListBoxWndProcA, /* procA */
147 ListBoxWndProcW, /* procW */
148 sizeof(LB_DESCR *), /* extra */
149 IDC_ARROW, /* cursor */
150 0 /* brush */
151};
152
153
154/***********************************************************************
155 * LISTBOX_GetCurrentPageSize
156 *
157 * Return the current page size
158 */
160{
161 INT i, height;
162 if (!(descr->style & LBS_OWNERDRAWVARIABLE)) return descr->page_size;
163 for (i = descr->top_item, height = 0; i < descr->nb_items; i++)
164 {
165 if ((height += descr->items[i].height) > descr->height) break;
166 }
167 if (i == descr->top_item) return 1;
168 else return i - descr->top_item;
169}
170
171
172/***********************************************************************
173 * LISTBOX_GetMaxTopIndex
174 *
175 * Return the maximum possible index for the top of the listbox.
176 */
178{
179 INT max, page;
180
181 if (descr->style & LBS_OWNERDRAWVARIABLE)
182 {
183 page = descr->height;
184 for (max = descr->nb_items - 1; max >= 0; max--)
185 if ((page -= descr->items[max].height) < 0) break;
186 if (max < descr->nb_items - 1) max++;
187 }
188 else if (descr->style & LBS_MULTICOLUMN)
189 {
190 if ((page = descr->width / descr->column_width) < 1) page = 1;
191 max = (descr->nb_items + descr->page_size - 1) / descr->page_size;
192 max = (max - page) * descr->page_size;
193 }
194 else
195 {
196 max = descr->nb_items - descr->page_size;
197 }
198 if (max < 0) max = 0;
199 return max;
200}
201
202
203/***********************************************************************
204 * LISTBOX_UpdateScroll
205 *
206 * Update the scrollbars. Should be called whenever the content
207 * of the listbox changes.
208 */
210{
212
213 /* Check the listbox scroll bar flags individually before we call
214 SetScrollInfo otherwise when the listbox style is WS_HSCROLL and
215 no WS_VSCROLL, we end up with an uninitialized, visible horizontal
216 scroll bar when we do not need one.
217 if (!(descr->style & WS_VSCROLL)) return;
218 */
219
220 /* It is important that we check descr->style, and not wnd->dwStyle,
221 for WS_VSCROLL, as the former is exactly the one passed in
222 argument to CreateWindow.
223 In Windows (and from now on in Wine :) a listbox created
224 with such a style (no WS_SCROLL) does not update
225 the scrollbar with listbox-related data, thus letting
226 the programmer use it for his/her own purposes. */
227
228 if (descr->style & LBS_NOREDRAW) return;
229 info.cbSize = sizeof(info);
230
231 if (descr->style & LBS_MULTICOLUMN)
232 {
233 info.nMin = 0;
234 info.nMax = (descr->nb_items - 1) / descr->page_size;
235 info.nPos = descr->top_item / descr->page_size;
236 info.nPage = descr->width / descr->column_width;
237 if (info.nPage < 1) info.nPage = 1;
238 info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
239 if (descr->style & LBS_DISABLENOSCROLL)
240 info.fMask |= SIF_DISABLENOSCROLL;
241 if (descr->style & WS_HSCROLL)
242 SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
243 info.nMax = 0;
244 info.fMask = SIF_RANGE;
245 if (descr->style & WS_VSCROLL)
246 SetScrollInfo( descr->self, SB_VERT, &info, TRUE );
247 }
248 else
249 {
250 info.nMin = 0;
251 info.nMax = descr->nb_items - 1;
252 info.nPos = descr->top_item;
254 info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
255 if (descr->style & LBS_DISABLENOSCROLL)
256 info.fMask |= SIF_DISABLENOSCROLL;
257 if (descr->style & WS_VSCROLL)
258 SetScrollInfo( descr->self, SB_VERT, &info, TRUE );
259
260 if ((descr->style & WS_HSCROLL) && descr->horz_extent)
261 {
262 info.nPos = descr->horz_pos;
263 info.nPage = descr->width;
264 info.fMask = SIF_POS | SIF_PAGE;
265 if (descr->style & LBS_DISABLENOSCROLL)
266 info.fMask |= SIF_DISABLENOSCROLL;
267 SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
268 }
269 else
270 {
271 if (descr->style & LBS_DISABLENOSCROLL)
272 {
273 info.nMin = 0;
274 info.nMax = 0;
276 SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
277 }
278 else
279 {
280 ShowScrollBar( descr->self, SB_HORZ, FALSE );
281 }
282 }
283 }
284}
285
286
287/***********************************************************************
288 * LISTBOX_SetTopItem
289 *
290 * Set the top item of the listbox, scrolling up or down if necessary.
291 */
293{
295
296 TRACE("setting top item %d, scroll %d\n", index, scroll);
297
298 if (index > max) index = max;
299 if (index < 0) index = 0;
300 if (descr->style & LBS_MULTICOLUMN) index -= index % descr->page_size;
301 if (descr->top_item == index) return LB_OKAY;
302 if (scroll)
303 {
304 INT diff;
305 if (descr->style & LBS_MULTICOLUMN)
306 diff = (descr->top_item - index) / descr->page_size * descr->column_width;
307 else if (descr->style & LBS_OWNERDRAWVARIABLE)
308 {
309 INT i;
310 diff = 0;
311 if (index > descr->top_item)
312 {
313 for (i = index - 1; i >= descr->top_item; i--)
314 diff -= descr->items[i].height;
315 }
316 else
317 {
318 for (i = index; i < descr->top_item; i++)
319 diff += descr->items[i].height;
320 }
321 }
322 else
323 diff = (descr->top_item - index) * descr->item_height;
324
325#ifdef __REACTOS__
326 if (descr->style & LBS_MULTICOLUMN)
327 ScrollWindowEx(descr->self, diff, 0, NULL, NULL, 0, NULL,
329 else
330#endif
331 ScrollWindowEx( descr->self, 0, diff, NULL, NULL, 0, NULL,
333 }
334 else
335 InvalidateRect( descr->self, NULL, TRUE );
336 descr->top_item = index;
338 return LB_OKAY;
339}
340
341
342/***********************************************************************
343 * LISTBOX_UpdatePage
344 *
345 * Update the page size. Should be called when the size of
346 * the client area or the item height changes.
347 */
349{
351
352 if ((descr->item_height == 0) || (page_size = descr->height / descr->item_height) < 1)
353 page_size = 1;
354 if (page_size == descr->page_size) return;
355 descr->page_size = page_size;
356 if (descr->style & LBS_MULTICOLUMN)
357 InvalidateRect( descr->self, NULL, TRUE );
358 LISTBOX_SetTopItem( descr, descr->top_item, FALSE );
359}
360
361
362/***********************************************************************
363 * LISTBOX_UpdateSize
364 *
365 * Update the size of the listbox. Should be called when the size of
366 * the client area changes.
367 */
369{
370 RECT rect;
372
373 GetClientRect( descr->self, &rect );
374 if (style & WS_HSCROLL)
376 descr->width = rect.right - rect.left;
377 descr->height = rect.bottom - rect.top;
378 if (!(descr->style & LBS_NOINTEGRALHEIGHT) && !(descr->style & LBS_OWNERDRAWVARIABLE))
379 {
380 INT remaining;
381 RECT rect;
382
383 GetWindowRect( descr->self, &rect );
384 if(descr->item_height != 0)
385 remaining = descr->height % descr->item_height;
386 else
387 remaining = 0;
388 if ((descr->height > descr->item_height) && remaining)
389 {
390 TRACE("[%p]: changing height %d -> %d\n",
391 descr->self, descr->height, descr->height - remaining );
392 SetWindowPos( descr->self, 0, 0, 0, rect.right - rect.left,
393 rect.bottom - rect.top - remaining,
395 return;
396 }
397 }
398 TRACE("[%p]: new size = %d,%d\n", descr->self, descr->width, descr->height );
401
402 /* Invalidate the focused item so it will be repainted correctly */
403 if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1)
404 {
405 InvalidateRect( descr->self, &rect, FALSE );
406 }
407}
408
409
410/***********************************************************************
411 * LISTBOX_GetItemRect
412 *
413 * Get the rectangle enclosing an item, in listbox client coordinates.
414 * Return 1 if the rectangle is (partially) visible, 0 if hidden, -1 on error.
415 */
417{
418 /* Index <= 0 is legal even on empty listboxes */
419 if (index && (index >= descr->nb_items))
420 {
421 memset(rect, 0, sizeof(*rect));
423 return LB_ERR;
424 }
425 SetRect( rect, 0, 0, descr->width, descr->height );
426 if (descr->style & LBS_MULTICOLUMN)
427 {
428 INT col = (index / descr->page_size) -
429 (descr->top_item / descr->page_size);
430 rect->left += col * descr->column_width;
431 rect->right = rect->left + descr->column_width;
432 rect->top += (index % descr->page_size) * descr->item_height;
433 rect->bottom = rect->top + descr->item_height;
434 }
435 else if (descr->style & LBS_OWNERDRAWVARIABLE)
436 {
437 INT i;
438 rect->right += descr->horz_pos;
439 if ((index >= 0) && (index < descr->nb_items))
440 {
441 if (index < descr->top_item)
442 {
443 for (i = descr->top_item-1; i >= index; i--)
444 rect->top -= descr->items[i].height;
445 }
446 else
447 {
448 for (i = descr->top_item; i < index; i++)
449 rect->top += descr->items[i].height;
450 }
451 rect->bottom = rect->top + descr->items[index].height;
452
453 }
454 }
455 else
456 {
457 rect->top += (index - descr->top_item) * descr->item_height;
458 rect->bottom = rect->top + descr->item_height;
459 rect->right += descr->horz_pos;
460 }
461
462 TRACE("item %d, rect %s\n", index, wine_dbgstr_rect(rect));
463
464 return ((rect->left < descr->width) && (rect->right > 0) &&
465 (rect->top < descr->height) && (rect->bottom > 0));
466}
467
468
469/***********************************************************************
470 * LISTBOX_GetItemFromPoint
471 *
472 * Return the item nearest from point (x,y) (in client coordinates).
473 */
475{
476 INT index = descr->top_item;
477
478 if (!descr->nb_items) return -1; /* No items */
479 if (descr->style & LBS_OWNERDRAWVARIABLE)
480 {
481 INT pos = 0;
482 if (y >= 0)
483 {
484 while (index < descr->nb_items)
485 {
486 if ((pos += descr->items[index].height) > y) break;
487 index++;
488 }
489 }
490 else
491 {
492 while (index > 0)
493 {
494 index--;
495 if ((pos -= descr->items[index].height) <= y) break;
496 }
497 }
498 }
499 else if (descr->style & LBS_MULTICOLUMN)
500 {
501 if (y >= descr->item_height * descr->page_size) return -1;
502 if (y >= 0) index += y / descr->item_height;
503 if (x >= 0) index += (x / descr->column_width) * descr->page_size;
504 else index -= (((x + 1) / descr->column_width) - 1) * descr->page_size;
505 }
506 else
507 {
508 index += (y / descr->item_height);
509 }
510 if (index < 0) return 0;
511 if (index >= descr->nb_items) return -1;
512 return index;
513}
514
515
516/***********************************************************************
517 * LISTBOX_PaintItem
518 *
519 * Paint an item.
520 */
522 INT index, UINT action, BOOL ignoreFocus )
523{
525 if (index < descr->nb_items) item = &descr->items[index];
526
527 if (IS_OWNERDRAW(descr))
528 {
529 DRAWITEMSTRUCT dis;
530 RECT r;
531 HRGN hrgn;
532
533 if (!item)
534 {
535 if (action == ODA_FOCUS)
536 { // REACTOS
537 if (!(descr->UIState & UISF_HIDEFOCUS))
539 } //
540 else
541 ERR("called with an out of bounds index %d(%d) in owner draw, Not good.\n",index,descr->nb_items);
542 return;
543 }
544
545 /* some programs mess with the clipping region when
546 drawing the item, *and* restore the previous region
547 after they are done, so a region has better to exist
548 else everything ends clipped */
549 GetClientRect(descr->self, &r);
551
552 dis.CtlType = ODT_LISTBOX;
553 dis.CtlID = GetWindowLongPtrW( descr->self, GWLP_ID );
554 dis.hwndItem = descr->self;
555 dis.itemAction = action;
556 dis.hDC = hdc;
557 dis.itemID = index;
558 dis.itemState = 0;
559 if (item->selected) dis.itemState |= ODS_SELECTED;
560 if (!ignoreFocus && (descr->focus_item == index) &&
561 (descr->caret_on) &&
562 (descr->in_focus)) dis.itemState |= ODS_FOCUS;
563 if (!IsWindowEnabled(descr->self)) dis.itemState |= ODS_DISABLED;
564 dis.itemData = item->data;
565 dis.rcItem = *rect;
566 TRACE("[%p]: drawitem %d (%s) action=%02x state=%02x rect=%s\n",
567 descr->self, index, debugstr_w(item->str), action,
569 SendMessageW(descr->owner, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis);
571 if (hrgn) DeleteObject( hrgn );
572 }
573 else
574 {
575 COLORREF oldText = 0, oldBk = 0;
576
577 if (action == ODA_FOCUS)
578 {
579 if (!(descr->UIState & UISF_HIDEFOCUS)) // REACTOS
581 return;
582 }
583 if (item && item->selected)
584 {
587 }
588
589 TRACE("[%p]: painting %d (%s) action=%02x rect=%s\n",
590 descr->self, index, item ? debugstr_w(item->str) : "", action,
592 if (!item)
593 ExtTextOutW( hdc, rect->left + 1, rect->top,
595 else if (!(descr->style & LBS_USETABSTOPS))
596 ExtTextOutW( hdc, rect->left + 1, rect->top,
598 strlenW(item->str), NULL );
599 else
600 {
601 /* Output empty string to paint background in the full width. */
602 ExtTextOutW( hdc, rect->left + 1, rect->top,
604 TabbedTextOutW( hdc, rect->left + 1 , rect->top,
605 item->str, strlenW(item->str),
606 descr->nb_tabs, descr->tabs, 0);
607 }
608 if (item && item->selected)
609 {
610 SetBkColor( hdc, oldBk );
611 SetTextColor( hdc, oldText );
612 }
613 if (!ignoreFocus && (descr->focus_item == index) &&
614 (descr->caret_on) &&
615 (descr->in_focus) &&
616 !(descr->UIState & UISF_HIDEFOCUS)) DrawFocusRect( hdc, rect );
617 }
618}
619
620
621/***********************************************************************
622 * LISTBOX_SetRedraw
623 *
624 * Change the redraw flag.
625 */
627{
628 if (on)
629 {
630 if (!(descr->style & LBS_NOREDRAW)) return;
631 descr->style &= ~LBS_NOREDRAW;
632 if (descr->style & LBS_DISPLAYCHANGED)
633 { /* page was changed while setredraw false, refresh automatically */
634 InvalidateRect(descr->self, NULL, TRUE);
635 if ((descr->top_item + descr->page_size) > descr->nb_items)
636 { /* reset top of page if less than number of items/page */
637 descr->top_item = descr->nb_items - descr->page_size;
638 if (descr->top_item < 0) descr->top_item = 0;
639 }
640 descr->style &= ~LBS_DISPLAYCHANGED;
641 }
643 }
644 else descr->style |= LBS_NOREDRAW;
645}
646
647
648/***********************************************************************
649 * LISTBOX_RepaintItem
650 *
651 * Repaint a single item synchronously.
652 */
654{
655 HDC hdc;
656 RECT rect;
657 HFONT oldFont = 0;
658 HBRUSH hbrush, oldBrush = 0;
659
660 /* Do not repaint the item if the item is not visible */
661 if (!IsWindowVisible(descr->self)) return;
662 if (descr->style & LBS_NOREDRAW)
663 {
664 descr->style |= LBS_DISPLAYCHANGED;
665 return;
666 }
667 if (LISTBOX_GetItemRect( descr, index, &rect ) != 1) return;
668 if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE ))) return;
669 if (descr->font) oldFont = SelectObject( hdc, descr->font );
670#ifdef __REACTOS__
672#else
673 hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
674 (WPARAM)hdc, (LPARAM)descr->self );
675#endif
676 if (hbrush) oldBrush = SelectObject( hdc, hbrush );
677 if (!IsWindowEnabled(descr->self))
679 SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
681 if (oldFont) SelectObject( hdc, oldFont );
682 if (oldBrush) SelectObject( hdc, oldBrush );
683 ReleaseDC( descr->self, hdc );
684}
685
686
687/***********************************************************************
688 * LISTBOX_DrawFocusRect
689 */
691{
692 HDC hdc;
693 RECT rect;
694 HFONT oldFont = 0;
695
696 /* Do not repaint the item if the item is not visible */
697 if (!IsWindowVisible(descr->self)) return;
698
699 if (descr->focus_item == -1) return;
700 if (!descr->caret_on || !descr->in_focus) return;
701
702 if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) != 1) return;
703 if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE ))) return;
704 if (descr->font) oldFont = SelectObject( hdc, descr->font );
705 if (!IsWindowEnabled(descr->self))
707 SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
708 LISTBOX_PaintItem( descr, hdc, &rect, descr->focus_item, ODA_FOCUS, !on );
709 if (oldFont) SelectObject( hdc, oldFont );
710 ReleaseDC( descr->self, hdc );
711}
712
713
714/***********************************************************************
715 * LISTBOX_InitStorage
716 */
718{
720
721 nb_items += LB_ARRAY_GRANULARITY - 1;
722 nb_items -= (nb_items % LB_ARRAY_GRANULARITY);
723 if (descr->items) {
724 nb_items += HeapSize( GetProcessHeap(), 0, descr->items ) / sizeof(*item);
725 item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
726 nb_items * sizeof(LB_ITEMDATA));
727 }
728 else {
730 nb_items * sizeof(LB_ITEMDATA));
731 }
732
733 if (!item)
734 {
736 return LB_ERRSPACE;
737 }
738 descr->items = item;
739 return LB_OKAY;
740}
741
742
743/***********************************************************************
744 * LISTBOX_SetTabStops
745 */
747{
748 INT i;
749
750 if (!(descr->style & LBS_USETABSTOPS))
751 {
753 return FALSE;
754 }
755
756 HeapFree( GetProcessHeap(), 0, descr->tabs );
757 if (!(descr->nb_tabs = count))
758 {
759 descr->tabs = NULL;
760 return TRUE;
761 }
762 if (!(descr->tabs = HeapAlloc( GetProcessHeap(), 0,
763 descr->nb_tabs * sizeof(INT) )))
764 return FALSE;
765 memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT) );
766
767 /* convert into "dialog units"*/
768 for (i = 0; i < descr->nb_tabs; i++)
769 descr->tabs[i] = MulDiv(descr->tabs[i], descr->avg_char_width, 4);
770
771 return TRUE;
772}
773
774
775/***********************************************************************
776 * LISTBOX_GetText
777 */
779{
780 DWORD len;
781
782 if ((index < 0) || (index >= descr->nb_items))
783 {
785 return LB_ERR;
786 }
787 if (HAS_STRINGS(descr))
788 {
789 if (!buffer)
790 {
791 len = strlenW(descr->items[index].str);
792 if( unicode )
793 return len;
794 return WideCharToMultiByte( CP_ACP, 0, descr->items[index].str, len,
795 NULL, 0, NULL, NULL );
796 }
797
798 TRACE("index %d (0x%04x) %s\n", index, index, debugstr_w(descr->items[index].str));
799
800 _SEH2_TRY /* hide a Delphi bug that passes a read-only buffer */
801 {
802 if(unicode)
803 {
804 strcpyW( buffer, descr->items[index].str );
805 len = strlenW(buffer);
806 }
807 else
808 {
809 len = WideCharToMultiByte(CP_ACP, 0, descr->items[index].str, -1,
810 (LPSTR)buffer, 0x7FFFFFFF, NULL, NULL) - 1;
811 }
812 }
814 {
815 ERR( "got an invalid buffer (Delphi bug?)\n" );
817 len = LB_ERR;
818 }
820 } else {
821 if (buffer)
822 *((LPDWORD)buffer)=*(LPDWORD)(&descr->items[index].data);
823 len = sizeof(DWORD);
824 }
825 return len;
826}
827
828static inline INT LISTBOX_lstrcmpiW( LCID lcid, LPCWSTR str1, LPCWSTR str2 )
829{
830 INT ret = CompareStringW( lcid, NORM_IGNORECASE, str1, -1, str2, -1 );
831 if (ret == CSTR_LESS_THAN)
832 return -1;
833 if (ret == CSTR_EQUAL)
834 return 0;
835 if (ret == CSTR_GREATER_THAN)
836 return 1;
837 return -1;
838}
839
840/***********************************************************************
841 * LISTBOX_FindStringPos
842 *
843 * Find the nearest string located before a given string in sort order.
844 * If 'exact' is TRUE, return an error if we don't get an exact match.
845 */
847{
848 INT index, min, max, res;
849
850 if (!(descr->style & LBS_SORT)) return -1; /* Add it at the end */
851 min = 0;
852 max = descr->nb_items;
853 while (min != max)
854 {
855 index = (min + max) / 2;
856 if (HAS_STRINGS(descr))
857 res = LISTBOX_lstrcmpiW( descr->locale, str, descr->items[index].str);
858 else
859 {
861 UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
862
863 cis.CtlType = ODT_LISTBOX;
864 cis.CtlID = id;
865 cis.hwndItem = descr->self;
866 /* note that some application (MetaStock) expects the second item
867 * to be in the listbox */
868 cis.itemID1 = -1;
869 cis.itemData1 = (ULONG_PTR)str;
870 cis.itemID2 = index;
871 cis.itemData2 = descr->items[index].data;
872 cis.dwLocaleId = descr->locale;
873 res = SendMessageW( descr->owner, WM_COMPAREITEM, id, (LPARAM)&cis );
874 }
875 if (!res) return index;
876 if (res < 0) max = index;
877 else min = index + 1;
878 }
879 return exact ? -1 : max;
880}
881
882
883/***********************************************************************
884 * LISTBOX_FindFileStrPos
885 *
886 * Find the nearest string located before a given string in directory
887 * sort order (i.e. first files, then directories, then drives).
888 */
890{
891 INT min, max, res;
892
893 if (!HAS_STRINGS(descr))
895 min = 0;
896 max = descr->nb_items;
897 while (min != max)
898 {
899 INT index = (min + max) / 2;
900 LPCWSTR p = descr->items[index].str;
901 if (*p == '[') /* drive or directory */
902 {
903 if (*str != '[') res = -1;
904 else if (p[1] == '-') /* drive */
905 {
906 if (str[1] == '-') res = str[2] - p[2];
907 else res = -1;
908 }
909 else /* directory */
910 {
911 if (str[1] == '-') res = 1;
912 else res = LISTBOX_lstrcmpiW( descr->locale, str, p );
913 }
914 }
915 else /* filename */
916 {
917 if (*str == '[') res = 1;
918 else res = LISTBOX_lstrcmpiW( descr->locale, str, p );
919 }
920 if (!res) return index;
921 if (res < 0) max = index;
922 else min = index + 1;
923 }
924 return max;
925}
926
927
928/***********************************************************************
929 * LISTBOX_FindString
930 *
931 * Find the item beginning with a given string.
932 */
934{
935 INT i;
937
938 if (start >= descr->nb_items) start = -1;
939 item = descr->items + start + 1;
940 if (HAS_STRINGS(descr))
941 {
942 if (!str || ! str[0] ) return LB_ERR;
943 if (exact)
944 {
945 for (i = start + 1; i < descr->nb_items; i++, item++)
946 if (!LISTBOX_lstrcmpiW( descr->locale, str, item->str )) return i;
947 for (i = 0, item = descr->items; i <= start; i++, item++)
948 if (!LISTBOX_lstrcmpiW( descr->locale, str, item->str )) return i;
949 }
950 else
951 {
952 /* Special case for drives and directories: ignore prefix */
953#define CHECK_DRIVE(item) \
954 if ((item)->str[0] == '[') \
955 { \
956 if (!strncmpiW( str, (item)->str+1, len )) return i; \
957 if (((item)->str[1] == '-') && !strncmpiW(str, (item)->str+2, len)) \
958 return i; \
959 }
960
961 INT len = strlenW(str);
962 for (i = start + 1; i < descr->nb_items; i++, item++)
963 {
964 if (!strncmpiW( str, item->str, len )) return i;
966 }
967 for (i = 0, item = descr->items; i <= start; i++, item++)
968 {
969 if (!strncmpiW( str, item->str, len )) return i;
971 }
972#undef CHECK_DRIVE
973 }
974 }
975 else
976 {
977 if (exact && (descr->style & LBS_SORT))
978 /* If sorted, use a WM_COMPAREITEM binary search */
980
981 /* Otherwise use a linear search */
982 for (i = start + 1; i < descr->nb_items; i++, item++)
983 if (item->data == (ULONG_PTR)str) return i;
984 for (i = 0, item = descr->items; i <= start; i++, item++)
985 if (item->data == (ULONG_PTR)str) return i;
986 }
987 return LB_ERR;
988}
989
990
991/***********************************************************************
992 * LISTBOX_GetSelCount
993 */
995{
996 INT i, count;
997 const LB_ITEMDATA *item = descr->items;
998
999 if (!(descr->style & LBS_MULTIPLESEL) ||
1000 (descr->style & LBS_NOSEL))
1001 return LB_ERR;
1002 for (i = count = 0; i < descr->nb_items; i++, item++)
1003 if (item->selected) count++;
1004 return count;
1005}
1006
1007
1008/***********************************************************************
1009 * LISTBOX_GetSelItems
1010 */
1012{
1013 INT i, count;
1014 const LB_ITEMDATA *item = descr->items;
1015
1016 if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
1017 for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
1018 if (item->selected) array[count++] = i;
1019 return count;
1020}
1021
1022
1023/***********************************************************************
1024 * LISTBOX_Paint
1025 */
1027{
1028 INT i, col_pos = descr->page_size - 1;
1029 RECT rect;
1030 RECT focusRect = {-1, -1, -1, -1};
1031 HFONT oldFont = 0;
1032 HBRUSH hbrush, oldBrush = 0;
1033
1034 if (descr->style & LBS_NOREDRAW) return 0;
1035
1036 SetRect( &rect, 0, 0, descr->width, descr->height );
1037 if (descr->style & LBS_MULTICOLUMN)
1038 rect.right = rect.left + descr->column_width;
1039 else if (descr->horz_pos)
1040 {
1041 SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
1042 rect.right += descr->horz_pos;
1043 }
1044
1045 if (descr->font) oldFont = SelectObject( hdc, descr->font );
1046#ifdef __REACTOS__
1048#else
1049 hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
1050 (WPARAM)hdc, (LPARAM)descr->self );
1051#endif
1052 if (hbrush) oldBrush = SelectObject( hdc, hbrush );
1054
1055 if (!descr->nb_items && (descr->focus_item != -1) && descr->caret_on &&
1056 (descr->in_focus))
1057 {
1058 /* Special case for empty listbox: paint focus rect */
1059 rect.bottom = rect.top + descr->item_height;
1061 &rect, NULL, 0, NULL );
1062 LISTBOX_PaintItem( descr, hdc, &rect, descr->focus_item, ODA_FOCUS, FALSE );
1063 rect.top = rect.bottom;
1064 }
1065
1066 /* Paint all the item, regarding the selection
1067 Focus state will be painted after */
1068
1069 for (i = descr->top_item; i < descr->nb_items; i++)
1070 {
1071 if (!(descr->style & LBS_OWNERDRAWVARIABLE))
1072 rect.bottom = rect.top + descr->item_height;
1073 else
1074 rect.bottom = rect.top + descr->items[i].height;
1075
1076 /* keep the focus rect, to paint the focus item after */
1077 if (i == descr->focus_item)
1078 focusRect = rect;
1079#ifdef __REACTOS__
1080 rect.bottom = min(rect.bottom, descr->height);
1081#endif
1083 rect.top = rect.bottom;
1084
1085 if ((descr->style & LBS_MULTICOLUMN) && !col_pos)
1086 {
1087 if (!IS_OWNERDRAW(descr))
1088 {
1089 /* Clear the bottom of the column */
1090 if (rect.top < descr->height)
1091 {
1092 rect.bottom = descr->height;
1094 &rect, NULL, 0, NULL );
1095 }
1096 }
1097
1098 /* Go to the next column */
1099 rect.left += descr->column_width;
1100 rect.right += descr->column_width;
1101 rect.top = 0;
1102 col_pos = descr->page_size - 1;
1103 }
1104 else
1105 {
1106 col_pos--;
1107 if (rect.top >= descr->height) break;
1108 }
1109 }
1110
1111 /* Paint the focus item now */
1112 if (focusRect.top != focusRect.bottom &&
1113 descr->caret_on && descr->in_focus)
1114 LISTBOX_PaintItem( descr, hdc, &focusRect, descr->focus_item, ODA_FOCUS, FALSE );
1115
1116 if (!IS_OWNERDRAW(descr))
1117 {
1118 /* Clear the remainder of the client area */
1119 if (rect.top < descr->height)
1120 {
1121 rect.bottom = descr->height;
1123 &rect, NULL, 0, NULL );
1124 }
1125 if (rect.right < descr->width)
1126 {
1127 rect.left = rect.right;
1128 rect.right = descr->width;
1129 rect.top = 0;
1130 rect.bottom = descr->height;
1132 &rect, NULL, 0, NULL );
1133 }
1134 }
1135 if (oldFont) SelectObject( hdc, oldFont );
1136 if (oldBrush) SelectObject( hdc, oldBrush );
1137 return 0;
1138}
1139
1140
1141/***********************************************************************
1142 * LISTBOX_InvalidateItems
1143 *
1144 * Invalidate all items from a given item. If the specified item is not
1145 * visible, nothing happens.
1146 */
1148{
1149 RECT rect;
1150
1151 if (LISTBOX_GetItemRect( descr, index, &rect ) == 1)
1152 {
1153 if (descr->style & LBS_NOREDRAW)
1154 {
1155 descr->style |= LBS_DISPLAYCHANGED;
1156 return;
1157 }
1158 rect.bottom = descr->height;
1159 InvalidateRect( descr->self, &rect, TRUE );
1160 if (descr->style & LBS_MULTICOLUMN)
1161 {
1162 /* Repaint the other columns */
1163 rect.left = rect.right;
1164 rect.right = descr->width;
1165 rect.top = 0;
1166 InvalidateRect( descr->self, &rect, TRUE );
1167 }
1168 }
1169}
1170
1172{
1173 RECT rect;
1174
1175 if (LISTBOX_GetItemRect( descr, index, &rect ) == 1)
1176 InvalidateRect( descr->self, &rect, TRUE );
1177}
1178
1179/***********************************************************************
1180 * LISTBOX_GetItemHeight
1181 */
1183{
1184 if (descr->style & LBS_OWNERDRAWVARIABLE && descr->nb_items > 0)
1185 {
1186 if ((index < 0) || (index >= descr->nb_items))
1187 {
1189 return LB_ERR;
1190 }
1191 return descr->items[index].height;
1192 }
1193 else return descr->item_height;
1194}
1195
1196
1197/***********************************************************************
1198 * LISTBOX_SetItemHeight
1199 */
1201{
1202 if (height > MAXBYTE)
1203 return -1;
1204
1205 if (!height) height = 1;
1206
1207 if (descr->style & LBS_OWNERDRAWVARIABLE)
1208 {
1209 if ((index < 0) || (index >= descr->nb_items))
1210 {
1212 return LB_ERR;
1213 }
1214 TRACE("[%p]: item %d height = %d\n", descr->self, index, height );
1215 descr->items[index].height = height;
1217 if (repaint)
1219 }
1220 else if (height != descr->item_height)
1221 {
1222 TRACE("[%p]: new height = %d\n", descr->self, height );
1223 descr->item_height = height;
1226 if (repaint)
1227 InvalidateRect( descr->self, 0, TRUE );
1228 }
1229 return LB_OKAY;
1230}
1231
1232
1233/***********************************************************************
1234 * LISTBOX_SetHorizontalPos
1235 */
1237{
1238 INT diff;
1239
1240 if (pos > descr->horz_extent - descr->width)
1241 pos = descr->horz_extent - descr->width;
1242 if (pos < 0) pos = 0;
1243 if (!(diff = descr->horz_pos - pos)) return;
1244 TRACE("[%p]: new horz pos = %d\n", descr->self, pos );
1245 descr->horz_pos = pos;
1247 if (abs(diff) < descr->width)
1248 {
1249 RECT rect;
1250 /* Invalidate the focused item so it will be repainted correctly */
1251 if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1)
1252 InvalidateRect( descr->self, &rect, TRUE );
1253 ScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL,
1255 }
1256 else
1257 InvalidateRect( descr->self, NULL, TRUE );
1258}
1259
1260
1261/***********************************************************************
1262 * LISTBOX_SetHorizontalExtent
1263 */
1265{
1266 if (descr->style & LBS_MULTICOLUMN)
1267 return LB_OKAY;
1268 if (extent == descr->horz_extent) return LB_OKAY;
1269 TRACE("[%p]: new horz extent = %d\n", descr->self, extent );
1270 descr->horz_extent = extent;
1271 if (descr->style & WS_HSCROLL) {
1273 info.cbSize = sizeof(info);
1274 info.nMin = 0;
1275 info.nMax = descr->horz_extent ? descr->horz_extent - 1 : 0;
1276 info.fMask = SIF_RANGE;
1277 if (descr->style & LBS_DISABLENOSCROLL)
1278 info.fMask |= SIF_DISABLENOSCROLL;
1279 SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
1280 }
1281 if (descr->horz_pos > extent - descr->width)
1283 return LB_OKAY;
1284}
1285
1286
1287/***********************************************************************
1288 * LISTBOX_SetColumnWidth
1289 */
1291{
1292 if (width == descr->column_width) return LB_OKAY;
1293 TRACE("[%p]: new column width = %d\n", descr->self, width );
1294 descr->column_width = width;
1296 return LB_OKAY;
1297}
1298
1299
1300/***********************************************************************
1301 * LISTBOX_SetFont
1302 *
1303 * Returns the item height.
1304 */
1306{
1307 HDC hdc;
1308 HFONT oldFont = 0;
1309 const char *alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
1310 SIZE sz;
1311
1312 descr->font = font;
1313
1314 if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE )))
1315 {
1316 ERR("unable to get DC.\n" );
1317 return 16;
1318 }
1319 if (font) oldFont = SelectObject( hdc, font );
1320 GetTextExtentPointA( hdc, alphabet, 52, &sz);
1321 if (oldFont) SelectObject( hdc, oldFont );
1322 ReleaseDC( descr->self, hdc );
1323
1324 descr->avg_char_width = (sz.cx / 26 + 1) / 2;
1325 if (!IS_OWNERDRAW(descr))
1327 return sz.cy;
1328}
1329
1330
1331/***********************************************************************
1332 * LISTBOX_MakeItemVisible
1333 *
1334 * Make sure that a given item is partially or fully visible.
1335 */
1337{
1338 INT top;
1339
1340 TRACE("current top item %d, index %d, fully %d\n", descr->top_item, index, fully);
1341
1342 if (index <= descr->top_item) top = index;
1343 else if (descr->style & LBS_MULTICOLUMN)
1344 {
1345 INT cols = descr->width;
1346 if (!fully) cols += descr->column_width - 1;
1347 if (cols >= descr->column_width) cols /= descr->column_width;
1348 else cols = 1;
1349 if (index < descr->top_item + (descr->page_size * cols)) return;
1350 top = index - descr->page_size * (cols - 1);
1351 }
1352 else if (descr->style & LBS_OWNERDRAWVARIABLE)
1353 {
1354 INT height = fully ? descr->items[index].height : 1;
1355 for (top = index; top > descr->top_item; top--)
1356 if ((height += descr->items[top-1].height) > descr->height) break;
1357 }
1358 else
1359 {
1360 if (index < descr->top_item + descr->page_size) return;
1361 if (!fully && (index == descr->top_item + descr->page_size) &&
1362 (descr->height > (descr->page_size * descr->item_height))) return;
1363 top = index - descr->page_size + 1;
1364 }
1366}
1367
1368/***********************************************************************
1369 * LISTBOX_SetCaretIndex
1370 *
1371 * NOTES
1372 * index must be between 0 and descr->nb_items-1, or LB_ERR is returned.
1373 *
1374 */
1376{
1377 INT oldfocus = descr->focus_item;
1378
1379 TRACE("old focus %d, index %d\n", oldfocus, index);
1380
1381 if (descr->style & LBS_NOSEL) return LB_ERR;
1382 if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
1383 if (index == oldfocus) return LB_OKAY;
1384
1386 descr->focus_item = index;
1387
1388 LISTBOX_MakeItemVisible( descr, index, fully_visible );
1390
1391 return LB_OKAY;
1392}
1393
1394
1395/***********************************************************************
1396 * LISTBOX_SelectItemRange
1397 *
1398 * Select a range of items. Should only be used on a MULTIPLESEL listbox.
1399 */
1401 INT last, BOOL on )
1402{
1403 INT i;
1404
1405 /* A few sanity checks */
1406
1407 if (descr->style & LBS_NOSEL) return LB_ERR;
1408 if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
1409
1410 if (!descr->nb_items) return LB_OKAY;
1411
1412 if (last == -1 || last >= descr->nb_items) last = descr->nb_items - 1;
1413 if (first < 0) first = 0;
1414 if (last < first) return LB_OKAY;
1415
1416 if (on) /* Turn selection on */
1417 {
1418 for (i = first; i <= last; i++)
1419 {
1420 if (descr->items[i].selected) continue;
1421 descr->items[i].selected = TRUE;
1423 }
1424 }
1425 else /* Turn selection off */
1426 {
1427 for (i = first; i <= last; i++)
1428 {
1429 if (!descr->items[i].selected) continue;
1430 descr->items[i].selected = FALSE;
1432 }
1433 }
1434 return LB_OKAY;
1435}
1436
1437/***********************************************************************
1438 * LISTBOX_SetSelection
1439 */
1441 BOOL on, BOOL send_notify )
1442{
1443 TRACE( "cur_sel=%d index=%d notify=%s\n",
1444 descr->selected_item, index, send_notify ? "YES" : "NO" );
1445
1446 if (descr->style & LBS_NOSEL)
1447 {
1448 descr->selected_item = index;
1449 return LB_ERR;
1450 }
1451 if ((index < -1) || (index >= descr->nb_items)) return LB_ERR;
1452 if (descr->style & LBS_MULTIPLESEL)
1453 {
1454 if (index == -1) /* Select all items */
1455 return LISTBOX_SelectItemRange( descr, 0, descr->nb_items, on );
1456 else /* Only one item */
1457 return LISTBOX_SelectItemRange( descr, index, index, on );
1458 }
1459 else
1460 {
1461 INT oldsel = descr->selected_item;
1462 if (index == oldsel) return LB_OKAY;
1463 if (oldsel != -1) descr->items[oldsel].selected = FALSE;
1464 if (index != -1) descr->items[index].selected = TRUE;
1465 if (oldsel != -1) LISTBOX_RepaintItem( descr, oldsel, ODA_SELECT );
1466 descr->selected_item = index;
1468 if (send_notify && descr->nb_items) SEND_NOTIFICATION( descr,
1469 (index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL );
1470 else
1471 if( descr->lphc ) /* set selection change flag for parent combo */
1472 descr->lphc->wState |= CBF_SELCHANGE;
1473 }
1474 return LB_OKAY;
1475}
1476
1477
1478/***********************************************************************
1479 * LISTBOX_MoveCaret
1480 *
1481 * Change the caret position and extend the selection to the new caret.
1482 */
1483static void LISTBOX_MoveCaret( LB_DESCR *descr, INT index, BOOL fully_visible )
1484{
1485 TRACE("old focus %d, index %d\n", descr->focus_item, index);
1486
1487 if ((index < 0) || (index >= descr->nb_items))
1488 return;
1489
1490 /* Important, repaint needs to be done in this order if
1491 you want to mimic Windows behavior:
1492 1. Remove the focus and paint the item
1493 2. Remove the selection and paint the item(s)
1494 3. Set the selection and repaint the item(s)
1495 4. Set the focus to 'index' and repaint the item */
1496
1497 /* 1. remove the focus and repaint the item */
1499
1500 /* 2. then turn off the previous selection */
1501 /* 3. repaint the new selected item */
1502 if (descr->style & LBS_EXTENDEDSEL)
1503 {
1504 if (descr->anchor_item != -1)
1505 {
1506 INT first = min( index, descr->anchor_item );
1507 INT last = max( index, descr->anchor_item );
1508 if (first > 0)
1512 }
1513 }
1514 else if (!(descr->style & LBS_MULTIPLESEL))
1515 {
1516 /* Set selection to new caret item */
1518 }
1519
1520 /* 4. repaint the new item with the focus */
1521 descr->focus_item = index;
1522 LISTBOX_MakeItemVisible( descr, index, fully_visible );
1524}
1525
1526
1527/***********************************************************************
1528 * LISTBOX_InsertItem
1529 */
1532{
1534 INT max_items;
1535 INT oldfocus = descr->focus_item;
1536
1537 if (index == -1) index = descr->nb_items;
1538 else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
1539 if (!descr->items) max_items = 0;
1540 else max_items = HeapSize( GetProcessHeap(), 0, descr->items ) / sizeof(*item);
1541 if (descr->nb_items == max_items)
1542 {
1543 /* We need to grow the array */
1544 max_items += LB_ARRAY_GRANULARITY;
1545 if (descr->items)
1546 item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
1547 max_items * sizeof(LB_ITEMDATA) );
1548 else
1550 max_items * sizeof(LB_ITEMDATA) );
1551 if (!item)
1552 {
1554 return LB_ERRSPACE;
1555 }
1556 descr->items = item;
1557 }
1558
1559 /* Insert the item structure */
1560
1561 item = &descr->items[index];
1562 if (index < descr->nb_items)
1563 RtlMoveMemory( item + 1, item,
1564 (descr->nb_items - index) * sizeof(LB_ITEMDATA) );
1565 item->str = str;
1566 item->data = data;
1567 item->height = 0;
1568 item->selected = FALSE;
1569 descr->nb_items++;
1570
1571 /* Get item height */
1572
1573 if (descr->style & LBS_OWNERDRAWVARIABLE)
1574 {
1576 UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
1577
1578 mis.CtlType = ODT_LISTBOX;
1579 mis.CtlID = id;
1580 mis.itemID = index;
1581 mis.itemData = descr->items[index].data;
1582 mis.itemHeight = descr->item_height;
1583 SendMessageW( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
1584 item->height = mis.itemHeight ? mis.itemHeight : 1;
1585 TRACE("[%p]: measure item %d (%s) = %d\n",
1586 descr->self, index, str ? debugstr_w(str) : "", item->height );
1587 }
1588
1589 /* Repaint the items */
1590
1593
1594 /* Move selection and focused item */
1595 /* If listbox was empty, set focus to the first item */
1596 if (descr->nb_items == 1)
1598 /* single select don't change selection index in win31 */
1599 else if ((ISWIN31) && !(IS_MULTISELECT(descr)))
1600 {
1601 descr->selected_item++;
1602 LISTBOX_SetSelection( descr, descr->selected_item-1, TRUE, FALSE );
1603 }
1604 else
1605 {
1606 if (index <= descr->selected_item)
1607 {
1608 descr->selected_item++;
1609 descr->focus_item = oldfocus; /* focus not changed */
1610 }
1611 }
1612 return LB_OKAY;
1613}
1614
1615
1616/***********************************************************************
1617 * LISTBOX_InsertString
1618 */
1620{
1621 LPWSTR new_str = NULL;
1622 ULONG_PTR data = 0;
1623 LRESULT ret;
1624
1625 if (HAS_STRINGS(descr))
1626 {
1627 static const WCHAR empty_stringW[] = { 0 };
1628 if (!str) str = empty_stringW;
1629 if (!(new_str = HeapAlloc( GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR) )))
1630 {
1632 return LB_ERRSPACE;
1633 }
1634 strcpyW(new_str, str);
1635 }
1636 else data = (ULONG_PTR)str;
1637
1638 if (index == -1) index = descr->nb_items;
1639 if ((ret = LISTBOX_InsertItem( descr, index, new_str, data )) != 0)
1640 {
1641 HeapFree( GetProcessHeap(), 0, new_str );
1642 return ret;
1643 }
1644
1645 TRACE("[%p]: added item %d %s\n",
1646 descr->self, index, HAS_STRINGS(descr) ? debugstr_w(new_str) : "" );
1647 return index;
1648}
1649
1650
1651/***********************************************************************
1652 * LISTBOX_DeleteItem
1653 *
1654 * Delete the content of an item. 'index' must be a valid index.
1655 */
1657{
1658 /* save the item data before it gets freed by LB_RESETCONTENT */
1659 ULONG_PTR item_data = descr->items[index].data;
1660 LPWSTR item_str = descr->items[index].str;
1661
1662 if (!descr->nb_items)
1663 SendMessageW( descr->self, LB_RESETCONTENT, 0, 0 );
1664
1665 /* Note: Win 3.1 only sends DELETEITEM on owner-draw items,
1666 * while Win95 sends it for all items with user data.
1667 * It's probably better to send it too often than not
1668 * often enough, so this is what we do here.
1669 */
1670 if (IS_OWNERDRAW(descr) || item_data)
1671 {
1672 DELETEITEMSTRUCT dis;
1673 UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
1674
1675 dis.CtlType = ODT_LISTBOX;
1676 dis.CtlID = id;
1677 dis.itemID = index;
1678 dis.hwndItem = descr->self;
1679 dis.itemData = item_data;
1680 SendMessageW( descr->owner, WM_DELETEITEM, id, (LPARAM)&dis );
1681 }
1682 if (HAS_STRINGS(descr))
1683 HeapFree( GetProcessHeap(), 0, item_str );
1684}
1685
1686
1687/***********************************************************************
1688 * LISTBOX_RemoveItem
1689 *
1690 * Remove an item from the listbox and delete its content.
1691 */
1693{
1695 INT max_items;
1696
1697 if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
1698
1699 /* We need to invalidate the original rect instead of the updated one. */
1701
1702 descr->nb_items--;
1704
1705 if (!descr->nb_items) return LB_OKAY;
1706
1707 /* Remove the item */
1708
1709 item = &descr->items[index];
1710 if (index < descr->nb_items)
1711 RtlMoveMemory( item, item + 1,
1712 (descr->nb_items - index) * sizeof(LB_ITEMDATA) );
1713 if (descr->anchor_item == descr->nb_items) descr->anchor_item--;
1714
1715 /* Shrink the item array if possible */
1716
1717 max_items = HeapSize( GetProcessHeap(), 0, descr->items ) / sizeof(LB_ITEMDATA);
1718 if (descr->nb_items < max_items - 2*LB_ARRAY_GRANULARITY)
1719 {
1720 max_items -= LB_ARRAY_GRANULARITY;
1721 item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
1722 max_items * sizeof(LB_ITEMDATA) );
1723 if (item) descr->items = item;
1724 }
1725 /* Repaint the items */
1726
1728 /* if we removed the scrollbar, reset the top of the list
1729 (correct for owner-drawn ???) */
1730 if (descr->nb_items == descr->page_size)
1732
1733 /* Move selection and focused item */
1734 if (!IS_MULTISELECT(descr))
1735 {
1736 if (index == descr->selected_item)
1737 descr->selected_item = -1;
1738 else if (index < descr->selected_item)
1739 {
1740 descr->selected_item--;
1741 if (ISWIN31) /* win 31 do not change the selected item number */
1742 LISTBOX_SetSelection( descr, descr->selected_item + 1, TRUE, FALSE);
1743 }
1744 }
1745
1746 if (descr->focus_item >= descr->nb_items)
1747 {
1748 descr->focus_item = descr->nb_items - 1;
1749 if (descr->focus_item < 0) descr->focus_item = 0;
1750 }
1751 return LB_OKAY;
1752}
1753
1754
1755/***********************************************************************
1756 * LISTBOX_ResetContent
1757 */
1759{
1760 INT i;
1761
1762 for(i = descr->nb_items - 1; i>=0; i--) LISTBOX_DeleteItem( descr, i);
1763 HeapFree( GetProcessHeap(), 0, descr->items );
1764 descr->nb_items = 0;
1765 descr->top_item = 0;
1766 descr->selected_item = -1;
1767 descr->focus_item = 0;
1768 descr->anchor_item = -1;
1769 descr->items = NULL;
1770}
1771
1772
1773/***********************************************************************
1774 * LISTBOX_SetCount
1775 */
1777{
1778 LRESULT ret;
1779
1780 if (HAS_STRINGS(descr))
1781 {
1783 return LB_ERR;
1784 }
1785
1786 /* FIXME: this is far from optimal... */
1787 if (count > descr->nb_items)
1788 {
1789 while (count > descr->nb_items)
1790 if ((ret = LISTBOX_InsertString( descr, -1, 0 )) < 0)
1791 return ret;
1792 }
1793 else if (count < descr->nb_items)
1794 {
1795 while (count < descr->nb_items)
1796 if ((ret = LISTBOX_RemoveItem( descr, (descr->nb_items - 1) )) < 0)
1797 return ret;
1798 }
1799
1800 InvalidateRect( descr->self, NULL, TRUE );
1801 return LB_OKAY;
1802}
1803
1804
1805/***********************************************************************
1806 * LISTBOX_Directory
1807 */
1809 LPCWSTR filespec, BOOL long_names )
1810{
1811 HANDLE handle;
1814 int pos;
1815 LRESULT maxinsert = LB_ERR;
1816
1817 /* don't scan directory if we just want drives exclusively */
1818 if (attrib != (DDL_DRIVES | DDL_EXCLUSIVE)) {
1819 /* scan directory */
1820 if ((handle = FindFirstFileW(filespec, &entry)) == INVALID_HANDLE_VALUE)
1821 {
1822 int le = GetLastError();
1823 if ((le != ERROR_NO_MORE_FILES) && (le != ERROR_FILE_NOT_FOUND)) return LB_ERR;
1824 }
1825 else
1826 {
1827 do
1828 {
1829 WCHAR buffer[270];
1830 if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1831 {
1832 static const WCHAR bracketW[] = { ']',0 };
1833 static const WCHAR dotW[] = { '.',0 };
1834 if (!(attrib & DDL_DIRECTORY) ||
1835 !strcmpW( entry.cFileName, dotW )) continue;
1836 buffer[0] = '[';
1837 if (!long_names && entry.cAlternateFileName[0])
1838 strcpyW( buffer + 1, entry.cAlternateFileName );
1839 else
1840 strcpyW( buffer + 1, entry.cFileName );
1841 strcatW(buffer, bracketW);
1842 }
1843 else /* not a directory */
1844 {
1845#define ATTRIBS (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \
1846 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE)
1847
1848 if ((attrib & DDL_EXCLUSIVE) &&
1849 ((attrib & ATTRIBS) != (entry.dwFileAttributes & ATTRIBS)))
1850 continue;
1851#undef ATTRIBS
1852 if (!long_names && entry.cAlternateFileName[0])
1853 strcpyW( buffer, entry.cAlternateFileName );
1854 else
1855 strcpyW( buffer, entry.cFileName );
1856 }
1857 if (!long_names) CharLowerW( buffer );
1859 if ((ret = LISTBOX_InsertString( descr, pos, buffer )) < 0)
1860 break;
1861 if (ret <= maxinsert) maxinsert++; else maxinsert = ret;
1862 } while (FindNextFileW( handle, &entry ));
1863 FindClose( handle );
1864 }
1865 }
1866 if (ret >= 0)
1867 {
1868 ret = maxinsert;
1869
1870 /* scan drives */
1871 if (attrib & DDL_DRIVES)
1872 {
1873 WCHAR buffer[] = {'[','-','a','-',']',0};
1874 WCHAR root[] = {'A',':','\\',0};
1875 int drive;
1876 for (drive = 0; drive < 26; drive++, buffer[2]++, root[0]++)
1877 {
1878 if (GetDriveTypeW(root) <= DRIVE_NO_ROOT_DIR) continue;
1879 if ((ret = LISTBOX_InsertString( descr, -1, buffer )) < 0)
1880 break;
1881 }
1882 }
1883 }
1884 return ret;
1885}
1886
1887
1888/***********************************************************************
1889 * LISTBOX_HandleVScroll
1890 */
1892{
1894
1895 if (descr->style & LBS_MULTICOLUMN) return 0;
1896 switch(scrollReq)
1897 {
1898 case SB_LINEUP:
1899 LISTBOX_SetTopItem( descr, descr->top_item - 1, TRUE );
1900 break;
1901 case SB_LINEDOWN:
1902 LISTBOX_SetTopItem( descr, descr->top_item + 1, TRUE );
1903 break;
1904 case SB_PAGEUP:
1905 LISTBOX_SetTopItem( descr, descr->top_item -
1907 break;
1908 case SB_PAGEDOWN:
1909 LISTBOX_SetTopItem( descr, descr->top_item +
1911 break;
1912 case SB_THUMBPOSITION:
1914 break;
1915 case SB_THUMBTRACK:
1916 info.cbSize = sizeof(info);
1917 info.fMask = SIF_TRACKPOS;
1918 GetScrollInfo( descr->self, SB_VERT, &info );
1919 LISTBOX_SetTopItem( descr, info.nTrackPos, TRUE );
1920 break;
1921 case SB_TOP:
1923 break;
1924 case SB_BOTTOM:
1925 LISTBOX_SetTopItem( descr, descr->nb_items, TRUE );
1926 break;
1927 }
1928 return 0;
1929}
1930
1931
1932/***********************************************************************
1933 * LISTBOX_HandleHScroll
1934 */
1936{
1938 INT page;
1939
1940 if (descr->style & LBS_MULTICOLUMN)
1941 {
1942 switch(scrollReq)
1943 {
1944 case SB_LINELEFT:
1945 LISTBOX_SetTopItem( descr, descr->top_item-descr->page_size,
1946 TRUE );
1947 break;
1948 case SB_LINERIGHT:
1949 LISTBOX_SetTopItem( descr, descr->top_item+descr->page_size,
1950 TRUE );
1951 break;
1952 case SB_PAGELEFT:
1953 page = descr->width / descr->column_width;
1954 if (page < 1) page = 1;
1956 descr->top_item - page * descr->page_size, TRUE );
1957 break;
1958 case SB_PAGERIGHT:
1959 page = descr->width / descr->column_width;
1960 if (page < 1) page = 1;
1962 descr->top_item + page * descr->page_size, TRUE );
1963 break;
1964 case SB_THUMBPOSITION:
1965 LISTBOX_SetTopItem( descr, pos*descr->page_size, TRUE );
1966 break;
1967 case SB_THUMBTRACK:
1968 info.cbSize = sizeof(info);
1969 info.fMask = SIF_TRACKPOS;
1970#ifdef __REACTOS__
1971 GetScrollInfo( descr->self, SB_HORZ, &info );
1972#else
1973 GetScrollInfo( descr->self, SB_VERT, &info );
1974#endif
1975 LISTBOX_SetTopItem( descr, info.nTrackPos*descr->page_size,
1976 TRUE );
1977 break;
1978 case SB_LEFT:
1980 break;
1981 case SB_RIGHT:
1982 LISTBOX_SetTopItem( descr, descr->nb_items, TRUE );
1983 break;
1984 }
1985 }
1986 else if (descr->horz_extent)
1987 {
1988 switch(scrollReq)
1989 {
1990 case SB_LINELEFT:
1991 LISTBOX_SetHorizontalPos( descr, descr->horz_pos - 1 );
1992 break;
1993 case SB_LINERIGHT:
1994 LISTBOX_SetHorizontalPos( descr, descr->horz_pos + 1 );
1995 break;
1996 case SB_PAGELEFT:
1998 descr->horz_pos - descr->width );
1999 break;
2000 case SB_PAGERIGHT:
2002 descr->horz_pos + descr->width );
2003 break;
2004 case SB_THUMBPOSITION:
2006 break;
2007 case SB_THUMBTRACK:
2008 info.cbSize = sizeof(info);
2009 info.fMask = SIF_TRACKPOS;
2010 GetScrollInfo( descr->self, SB_HORZ, &info );
2011 LISTBOX_SetHorizontalPos( descr, info.nTrackPos );
2012 break;
2013 case SB_LEFT:
2015 break;
2016 case SB_RIGHT:
2018 descr->horz_extent - descr->width );
2019 break;
2020 }
2021 }
2022 return 0;
2023}
2024
2026{
2027 UINT pulScrollLines = 3;
2028
2029 SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
2030
2031 /* if scrolling changes direction, ignore left overs */
2032 if ((delta < 0 && descr->wheel_remain < 0) ||
2033 (delta > 0 && descr->wheel_remain > 0))
2034 descr->wheel_remain += delta;
2035 else
2036 descr->wheel_remain = delta;
2037
2038 if (descr->wheel_remain && pulScrollLines)
2039 {
2040 int cLineScroll;
2041 pulScrollLines = min((UINT) descr->page_size, pulScrollLines);
2042 cLineScroll = pulScrollLines * (float)descr->wheel_remain / WHEEL_DELTA;
2043 descr->wheel_remain -= WHEEL_DELTA * cLineScroll / (int)pulScrollLines;
2044#ifdef __REACTOS__
2045 if (cLineScroll < 0)
2046 cLineScroll -= descr->page_size;
2047#endif
2048 LISTBOX_SetTopItem( descr, descr->top_item - cLineScroll, TRUE );
2049 }
2050 return 0;
2051}
2052
2053/***********************************************************************
2054 * LISTBOX_HandleLButtonDown
2055 */
2057{
2059
2060 TRACE("[%p]: lbuttondown %d,%d item %d, focus item %d\n",
2061 descr->self, x, y, index, descr->focus_item);
2062
2063 if (!descr->caret_on && (descr->in_focus)) return 0;
2064
2065 if (!descr->in_focus)
2066 {
2067 if( !descr->lphc ) SetFocus( descr->self );
2068 else SetFocus( (descr->lphc->hWndEdit) ? descr->lphc->hWndEdit : descr->lphc->self );
2069 }
2070
2071 if (index == -1) return 0;
2072
2073 if (!descr->lphc)
2074 {
2075 if (descr->style & LBS_NOTIFY )
2077 MAKELPARAM( x, y ) );
2078 }
2079
2080 descr->captured = TRUE;
2081 SetCapture( descr->self );
2082
2083 if (descr->style & (LBS_EXTENDEDSEL | LBS_MULTIPLESEL))
2084 {
2085 /* we should perhaps make sure that all items are deselected
2086 FIXME: needed for !LBS_EXTENDEDSEL, too ?
2087 if (!(keys & (MK_SHIFT|MK_CONTROL)))
2088 LISTBOX_SetSelection( descr, -1, FALSE, FALSE);
2089 */
2090
2091 if (!(keys & MK_SHIFT)) descr->anchor_item = index;
2092 if (keys & MK_CONTROL)
2093 {
2096 !descr->items[index].selected,
2097 (descr->style & LBS_NOTIFY) != 0);
2098 }
2099 else
2100 {
2102
2103 if (descr->style & LBS_EXTENDEDSEL)
2104 {
2106 descr->items[index].selected,
2107 (descr->style & LBS_NOTIFY) != 0 );
2108 }
2109 else
2110 {
2112 !descr->items[index].selected,
2113 (descr->style & LBS_NOTIFY) != 0 );
2114 }
2115 }
2116 }
2117 else
2118 {
2119 descr->anchor_item = index;
2122 TRUE, (descr->style & LBS_NOTIFY) != 0 );
2123 }
2124
2125 if (!descr->lphc)
2126 { // See rev 40864 use Ptr for 64 bit.
2128 {
2129 POINT pt;
2130
2131 pt.x = x;
2132 pt.y = y;
2133
2134 if (DragDetect( descr->self, pt ))
2135 SendMessageW( descr->owner, WM_BEGINDRAG, 0, 0 );
2136 }
2137 }
2138 return 0;
2139}
2140
2141
2142/*************************************************************************
2143 * LISTBOX_HandleLButtonDownCombo [Internal]
2144 *
2145 * Process LButtonDown message for the ComboListBox
2146 *
2147 * PARAMS
2148 * pWnd [I] The windows internal structure
2149 * pDescr [I] The ListBox internal structure
2150 * keys [I] Key Flag (WM_LBUTTONDOWN doc for more info)
2151 * x [I] X Mouse Coordinate
2152 * y [I] Y Mouse Coordinate
2153 *
2154 * RETURNS
2155 * 0 since we are processing the WM_LBUTTONDOWN Message
2156 *
2157 * NOTES
2158 * This function is only to be used when a ListBox is a ComboListBox
2159 */
2160
2162{
2163 RECT clientRect, screenRect;
2164 POINT mousePos;
2165
2166 mousePos.x = x;
2167 mousePos.y = y;
2168
2169 GetClientRect(descr->self, &clientRect);
2170
2171 if(PtInRect(&clientRect, mousePos))
2172 {
2173 /* MousePos is in client, resume normal processing */
2174 if (msg == WM_LBUTTONDOWN)
2175 {
2176 descr->lphc->droppedIndex = descr->nb_items ? descr->selected_item : -1;
2178 }
2179 else if (descr->style & LBS_NOTIFY)
2181 }
2182 else
2183 {
2184 POINT screenMousePos;
2185 HWND hWndOldCapture;
2186
2187 /* Check the Non-Client Area */
2188 screenMousePos = mousePos;
2189 hWndOldCapture = GetCapture();
2191 GetWindowRect(descr->self, &screenRect);
2192 ClientToScreen(descr->self, &screenMousePos);
2193
2194 if(!PtInRect(&screenRect, screenMousePos))
2195 {
2196 LISTBOX_SetCaretIndex( descr, descr->lphc->droppedIndex, FALSE );
2197 LISTBOX_SetSelection( descr, descr->lphc->droppedIndex, FALSE, FALSE );
2199 }
2200 else
2201 {
2202 /* Check to see the NC is a scrollbar */
2203 INT nHitTestType=0;
2205 /* Check Vertical scroll bar */
2206 if (style & WS_VSCROLL)
2207 {
2208 clientRect.right += GetSystemMetrics(SM_CXVSCROLL);
2209 if (PtInRect( &clientRect, mousePos ))
2210 nHitTestType = HTVSCROLL;
2211 }
2212 /* Check horizontal scroll bar */
2213 if (style & WS_HSCROLL)
2214 {
2215 clientRect.bottom += GetSystemMetrics(SM_CYHSCROLL);
2216 if (PtInRect( &clientRect, mousePos ))
2217 nHitTestType = HTHSCROLL;
2218 }
2219 /* Windows sends this message when a scrollbar is clicked
2220 */
2221
2222 if(nHitTestType != 0)
2223 {
2224 SendMessageW(descr->self, WM_NCLBUTTONDOWN, nHitTestType,
2225 MAKELONG(screenMousePos.x, screenMousePos.y));
2226 }
2227 /* Resume the Capture after scrolling is complete
2228 */
2229 if(hWndOldCapture != 0)
2230 SetCapture(hWndOldCapture);
2231 }
2232 }
2233 return 0;
2234}
2235
2236/***********************************************************************
2237 * LISTBOX_HandleLButtonUp
2238 */
2240{
2244 if (descr->captured)
2245 {
2246 descr->captured = FALSE;
2247 if (GetCapture() == descr->self) ReleaseCapture();
2248 if ((descr->style & LBS_NOTIFY) && descr->nb_items)
2250 }
2251 return 0;
2252}
2253
2254
2255/***********************************************************************
2256 * LISTBOX_HandleTimer
2257 *
2258 * Handle scrolling upon a timer event.
2259 * Return TRUE if scrolling should continue.
2260 */
2262{
2263 switch(dir)
2264 {
2265 case LB_TIMER_UP:
2266 if (descr->top_item) index = descr->top_item - 1;
2267 else index = 0;
2268 break;
2269 case LB_TIMER_LEFT:
2270 if (descr->top_item) index -= descr->page_size;
2271 break;
2272 case LB_TIMER_DOWN:
2274 if (index == descr->focus_item) index++;
2275 if (index >= descr->nb_items) index = descr->nb_items - 1;
2276 break;
2277 case LB_TIMER_RIGHT:
2278 if (index + descr->page_size < descr->nb_items)
2279 index += descr->page_size;
2280 break;
2281 case LB_TIMER_NONE:
2282 break;
2283 }
2284 if (index == descr->focus_item) return FALSE;
2286 return TRUE;
2287}
2288
2289
2290/***********************************************************************
2291 * LISTBOX_HandleSystemTimer
2292 *
2293 * WM_SYSTIMER handler.
2294 */
2296{
2297 if (!LISTBOX_HandleTimer( descr, descr->focus_item, LISTBOX_Timer ))
2298 {
2301 }
2302 return 0;
2303}
2304
2305
2306/***********************************************************************
2307 * LISTBOX_HandleMouseMove
2308 *
2309 * WM_MOUSEMOVE handler.
2310 */
2312 INT x, INT y )
2313{
2314 INT index;
2316
2317 if (!descr->captured) return;
2318
2319 if (descr->style & LBS_MULTICOLUMN)
2320 {
2321 if (y < 0) y = 0;
2322 else if (y >= descr->item_height * descr->page_size)
2323 y = descr->item_height * descr->page_size - 1;
2324
2325 if (x < 0)
2326 {
2328 x = 0;
2329 }
2330 else if (x >= descr->width)
2331 {
2333 x = descr->width - 1;
2334 }
2335 }
2336 else
2337 {
2338 if (y < 0) dir = LB_TIMER_UP; /* above */
2339 else if (y >= descr->height) dir = LB_TIMER_DOWN; /* below */
2340 }
2341
2343 if (index == -1) index = descr->focus_item;
2345
2346 /* Start/stop the system timer */
2347
2348 if (dir != LB_TIMER_NONE)
2350 else if (LISTBOX_Timer != LB_TIMER_NONE)
2353}
2354
2355
2356/***********************************************************************
2357 * LISTBOX_HandleKeyDown
2358 */
2360{
2361 INT caret = -1;
2362 BOOL bForceSelection = TRUE; /* select item pointed to by focus_item */
2363 if ((IS_MULTISELECT(descr)) || (descr->selected_item == descr->focus_item))
2364 bForceSelection = FALSE; /* only for single select list */
2365
2366 if (descr->style & LBS_WANTKEYBOARDINPUT)
2367 {
2368 caret = SendMessageW( descr->owner, WM_VKEYTOITEM,
2369 MAKEWPARAM(LOWORD(key), descr->focus_item),
2370 (LPARAM)descr->self );
2371 if (caret == -2) return 0;
2372 }
2373 if (caret == -1) switch(key)
2374 {
2375 case VK_LEFT:
2376 if (descr->style & LBS_MULTICOLUMN)
2377 {
2378 bForceSelection = FALSE;
2379 if (descr->focus_item >= descr->page_size)
2380 caret = descr->focus_item - descr->page_size;
2381 break;
2382 }
2383 /* fall through */
2384 case VK_UP:
2385 caret = descr->focus_item - 1;
2386 if (caret < 0) caret = 0;
2387 break;
2388 case VK_RIGHT:
2389 if (descr->style & LBS_MULTICOLUMN)
2390 {
2391 bForceSelection = FALSE;
2392 if (descr->focus_item + descr->page_size < descr->nb_items)
2393 caret = descr->focus_item + descr->page_size;
2394 break;
2395 }
2396 /* fall through */
2397 case VK_DOWN:
2398 caret = descr->focus_item + 1;
2399 if (caret >= descr->nb_items) caret = descr->nb_items - 1;
2400 break;
2401
2402 case VK_PRIOR:
2403 if (descr->style & LBS_MULTICOLUMN)
2404 {
2405 INT page = descr->width / descr->column_width;
2406 if (page < 1) page = 1;
2407 caret = descr->focus_item - (page * descr->page_size) + 1;
2408 }
2409 else caret = descr->focus_item-LISTBOX_GetCurrentPageSize(descr) + 1;
2410 if (caret < 0) caret = 0;
2411 break;
2412 case VK_NEXT:
2413 if (descr->style & LBS_MULTICOLUMN)
2414 {
2415 INT page = descr->width / descr->column_width;
2416 if (page < 1) page = 1;
2417 caret = descr->focus_item + (page * descr->page_size) - 1;
2418 }
2419 else caret = descr->focus_item + LISTBOX_GetCurrentPageSize(descr) - 1;
2420 if (caret >= descr->nb_items) caret = descr->nb_items - 1;
2421 break;
2422 case VK_HOME:
2423 caret = 0;
2424 break;
2425 case VK_END:
2426 caret = descr->nb_items - 1;
2427 break;
2428 case VK_SPACE:
2429 if (descr->style & LBS_EXTENDEDSEL) caret = descr->focus_item;
2430 else if (descr->style & LBS_MULTIPLESEL)
2431 {
2432 LISTBOX_SetSelection( descr, descr->focus_item,
2433 !descr->items[descr->focus_item].selected,
2434 (descr->style & LBS_NOTIFY) != 0 );
2435 }
2436 break;
2437 default:
2438 bForceSelection = FALSE;
2439 }
2440 if (bForceSelection) /* focused item is used instead of key */
2441 caret = descr->focus_item;
2442 if (caret >= 0)
2443 {
2444 if (((descr->style & LBS_EXTENDEDSEL) &&
2445 !(GetKeyState( VK_SHIFT ) & 0x8000)) ||
2447 descr->anchor_item = caret;
2448 LISTBOX_MoveCaret( descr, caret, TRUE );
2449
2450 if (descr->style & LBS_MULTIPLESEL)
2451 descr->selected_item = caret;
2452 else
2454 if (descr->style & LBS_NOTIFY)
2455 {
2456 if (descr->lphc && IsWindowVisible( descr->self ))
2457 {
2458 /* make sure that combo parent doesn't hide us */
2459 descr->lphc->wState |= CBF_NOROLLUP;
2460 }
2461 if (descr->nb_items) SEND_NOTIFICATION( descr, LBN_SELCHANGE );
2462 }
2463 }
2464 return 0;
2465}
2466
2467
2468/***********************************************************************
2469 * LISTBOX_HandleChar
2470 */
2472{
2473 INT caret = -1;
2474 WCHAR str[2];
2475
2476 str[0] = charW;
2477 str[1] = '\0';
2478
2479 if (descr->style & LBS_WANTKEYBOARDINPUT)
2480 {
2481 caret = SendMessageW( descr->owner, WM_CHARTOITEM,
2482 MAKEWPARAM(charW, descr->focus_item),
2483 (LPARAM)descr->self );
2484 if (caret == -2) return 0;
2485 }
2486 if (caret == -1)
2487 caret = LISTBOX_FindString( descr, descr->focus_item, str, FALSE);
2488 if (caret != -1)
2489 {
2490 if ((!IS_MULTISELECT(descr)) && descr->selected_item == -1)
2492 LISTBOX_MoveCaret( descr, caret, TRUE );
2493 if ((descr->style & LBS_NOTIFY) && descr->nb_items)
2495 }
2496 return 0;
2497}
2498
2499/* ReactOS Retrieve the UI state for the control */
2501{
2502 LONG prev_flags;
2503
2504 prev_flags = descr->UIState;
2505 descr->UIState = DefWindowProcW(descr->self, WM_QUERYUISTATE, 0, 0);
2506 return prev_flags != descr->UIState;
2507}
2508
2509
2510/***********************************************************************
2511 * LISTBOX_Create
2512 */
2514{
2515 LB_DESCR *descr;
2517 RECT rect;
2518
2519 if (!(descr = HeapAlloc( GetProcessHeap(), 0, sizeof(*descr) )))
2520 return FALSE;
2521
2522 GetClientRect( hwnd, &rect );
2523 descr->self = hwnd;
2524 descr->owner = GetParent( descr->self );
2525 descr->style = GetWindowLongPtrW( descr->self, GWL_STYLE );
2526 descr->width = rect.right - rect.left;
2527 descr->height = rect.bottom - rect.top;
2528 descr->items = NULL;
2529 descr->nb_items = 0;
2530 descr->top_item = 0;
2531 descr->selected_item = -1;
2532 descr->focus_item = 0;
2533 descr->anchor_item = -1;
2534 descr->item_height = 1;
2535 descr->page_size = 1;
2536 descr->column_width = 150;
2537 descr->horz_extent = 0;
2538 descr->horz_pos = 0;
2539 descr->nb_tabs = 0;
2540 descr->tabs = NULL;
2541 descr->wheel_remain = 0;
2542 descr->caret_on = !lphc;
2543 if (descr->style & LBS_NOSEL) descr->caret_on = FALSE;
2544 descr->in_focus = FALSE;
2545 descr->captured = FALSE;
2546 descr->font = 0;
2547 descr->locale = GetUserDefaultLCID();
2548 descr->lphc = lphc;
2549
2550 if( lphc )
2551 {
2552 TRACE("[%p]: resetting owner %p -> %p\n", descr->self, descr->owner, lphc->self );
2553 descr->owner = lphc->self;
2554 }
2555
2556 SetWindowLongPtrW( descr->self, 0, (LONG_PTR)descr );
2557
2558 LISTBOX_update_uistate(descr); // ReactOS
2559
2560/* if (wnd->dwExStyle & WS_EX_NOPARENTNOTIFY) descr->style &= ~LBS_NOTIFY;
2561 */
2562 if (descr->style & LBS_EXTENDEDSEL) descr->style |= LBS_MULTIPLESEL;
2563 if (descr->style & LBS_MULTICOLUMN) descr->style &= ~LBS_OWNERDRAWVARIABLE;
2564 if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT;
2565
2567 /* A no-data list box must also have the LBS_OWNERDRAWFIXED style, but must
2568 not have the LBS_SORT or LBS_HASSTRINGS style. */
2569 if ( descr->style & LBS_NODATA &&
2570 (!(descr->style & LBS_OWNERDRAWFIXED) || descr->style & (LBS_HASSTRINGS|LBS_SORT) ) )
2571 descr->style &= ~LBS_NODATA;
2573 descr->item_height = LISTBOX_SetFont( descr, 0 );
2574
2575 if (descr->style & LBS_OWNERDRAWFIXED)
2576 {
2577 if( descr->lphc && (descr->lphc->dwStyle & CBS_DROPDOWN))
2578 {
2579 /* WinWord gets VERY unhappy if we send WM_MEASUREITEM from here */
2580 descr->item_height = lphc->fixedOwnerDrawHeight;
2581 }
2582 else
2583 {
2584 UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
2585 mis.CtlType = ODT_LISTBOX;
2586 mis.CtlID = id;
2587 mis.itemID = -1;
2588 mis.itemWidth = 0;
2589 mis.itemData = 0;
2590 mis.itemHeight = descr->item_height;
2591 SendMessageW( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
2592 descr->item_height = mis.itemHeight ? mis.itemHeight : 1;
2593 }
2594 }
2595
2596 TRACE("owner: %p, style: %08x, width: %d, height: %d\n", descr->owner, descr->style, descr->width, descr->height);
2597 return TRUE;
2598}
2599
2600
2601/***********************************************************************
2602 * LISTBOX_Destroy
2603 */
2605{
2607 SetWindowLongPtrW( descr->self, 0, 0 );
2608 HeapFree( GetProcessHeap(), 0, descr );
2609 return TRUE;
2610}
2611
2612
2613/***********************************************************************
2614 * ListBoxWndProc_common
2615 */
2617 WPARAM wParam, LPARAM lParam, BOOL unicode )
2618{
2620 LPHEADCOMBO lphc = 0;
2621 LRESULT ret;
2622#ifdef __REACTOS__
2623 PWND pWnd;
2624
2625 pWnd = ValidateHwnd(hwnd);
2626 if (pWnd)
2627 {
2628 if (!pWnd->fnid)
2629 {
2630 NtUserSetWindowFNID(hwnd, FNID_LISTBOX); // Could be FNID_COMBOLBOX by class.
2631 }
2632 else
2633 {
2634 if (pWnd->fnid != FNID_LISTBOX)
2635 {
2636 ERR("Wrong window class for listbox! fnId 0x%x\n",pWnd->fnid);
2637 return 0;
2638 }
2639 }
2640 }
2641#endif
2642
2643 if (!descr)
2644 {
2645 if (!IsWindow(hwnd)) return 0;
2646
2647 if (msg == WM_CREATE)
2648 {
2650 if (lpcs->style & LBS_COMBOBOX) lphc = lpcs->lpCreateParams;
2651 if (!LISTBOX_Create( hwnd, lphc )) return -1;
2652 TRACE("creating hwnd %p descr %p\n", hwnd, (void *)GetWindowLongPtrW( hwnd, 0 ) );
2653 return 0;
2654 }
2655 /* Ignore all other messages before we get a WM_CREATE */
2656 return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
2658 }
2659 if (descr->style & LBS_COMBOBOX) lphc = descr->lphc;
2660
2661 TRACE("[%p]: msg %s wp %08lx lp %08lx\n",
2662 descr->self, SPY_GetMsgName(msg, descr->self), wParam, lParam );
2663
2664 switch(msg)
2665 {
2666 case LB_RESETCONTENT:
2669 InvalidateRect( descr->self, NULL, TRUE );
2670 return 0;
2671
2672 case LB_ADDSTRING:
2673#ifdef __REACTOS__
2674 case LB_ADDSTRING_LOWER:
2675 case LB_ADDSTRING_UPPER:
2676#endif
2677 {
2678 INT ret;
2679 LPWSTR textW;
2680 if(unicode || !HAS_STRINGS(descr))
2681 textW = (LPWSTR)lParam;
2682 else
2683 {
2685 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
2686 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
2687 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
2688 else
2689 return LB_ERRSPACE;
2690 }
2691#ifdef __REACTOS__
2692 /* in the unicode the version, the string is really overwritten
2693 during the converting case */
2694 if (msg == LB_ADDSTRING_LOWER)
2695 strlwrW(textW);
2696 else if (msg == LB_ADDSTRING_UPPER)
2697 struprW(textW);
2698#endif
2701 if (!unicode && HAS_STRINGS(descr))
2703 return ret;
2704 }
2705
2706 case LB_INSERTSTRING:
2707#ifdef __REACTOS__
2710#endif
2711 {
2712 INT ret;
2713 LPWSTR textW;
2714 if(unicode || !HAS_STRINGS(descr))
2715 textW = (LPWSTR)lParam;
2716 else
2717 {
2719 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
2720 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
2721 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
2722 else
2723 return LB_ERRSPACE;
2724 }
2725#ifdef __REACTOS__
2726 /* in the unicode the version, the string is really overwritten
2727 during the converting case */
2729 strlwrW(textW);
2730 else if (msg == LB_INSERTSTRING_UPPER)
2731 struprW(textW);
2732#endif
2734 if(!unicode && HAS_STRINGS(descr))
2736 return ret;
2737 }
2738
2739 case LB_ADDFILE:
2740 {
2741 INT ret;
2742 LPWSTR textW;
2743 if(unicode || !HAS_STRINGS(descr))
2744 textW = (LPWSTR)lParam;
2745 else
2746 {
2748 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
2749 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
2750 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
2751 else
2752 return LB_ERRSPACE;
2753 }
2756 if(!unicode && HAS_STRINGS(descr))
2758 return ret;
2759 }
2760
2761 case LB_DELETESTRING:
2763 return descr->nb_items;
2764 else
2765 {
2767 return LB_ERR;
2768 }
2769
2770 case LB_GETITEMDATA:
2771 if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
2772 {
2774 return LB_ERR;
2775 }
2776 return descr->items[wParam].data;
2777
2778 case LB_SETITEMDATA:
2779 if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
2780 {
2782 return LB_ERR;
2783 }
2784 descr->items[wParam].data = lParam;
2785 /* undocumented: returns TRUE, not LB_OKAY (0) */
2786 return TRUE;
2787
2788 case LB_GETCOUNT:
2789 return descr->nb_items;
2790
2791 case LB_GETTEXT:
2792 return LISTBOX_GetText( descr, wParam, (LPWSTR)lParam, unicode );
2793
2794 case LB_GETTEXTLEN:
2795 if ((INT)wParam >= descr->nb_items || (INT)wParam < 0)
2796 {
2798 return LB_ERR;
2799 }
2800 if (!HAS_STRINGS(descr)) return sizeof(DWORD);
2801 if (unicode) return strlenW( descr->items[wParam].str );
2802 return WideCharToMultiByte( CP_ACP, 0, descr->items[wParam].str,
2803 strlenW(descr->items[wParam].str), NULL, 0, NULL, NULL );
2804
2805 case LB_GETCURSEL:
2806 if (descr->nb_items == 0)
2807 return LB_ERR;
2808 if (!IS_MULTISELECT(descr))
2809 return descr->selected_item;
2810 if (descr->selected_item != -1)
2811 return descr->selected_item;
2812 return descr->focus_item;
2813 /* otherwise, if the user tries to move the selection with the */
2814 /* arrow keys, we will give the application something to choke on */
2815 case LB_GETTOPINDEX:
2816 return descr->top_item;
2817
2818 case LB_GETITEMHEIGHT:
2820
2821 case LB_SETITEMHEIGHT:
2823
2824 case LB_ITEMFROMPOINT:
2825 {
2826 POINT pt;
2827 RECT rect;
2828 int index;
2829 BOOL hit = TRUE;
2830
2831 /* The hiword of the return value is not a client area
2832 hittest as suggested by MSDN, but rather a hittest on
2833 the returned listbox item. */
2834
2835 if(descr->nb_items == 0)
2836 return 0x1ffff; /* win9x returns 0x10000, we copy winnt */
2837
2838 pt.x = (short)LOWORD(lParam);
2839 pt.y = (short)HIWORD(lParam);
2840
2841 SetRect(&rect, 0, 0, descr->width, descr->height);
2842
2843 if(!PtInRect(&rect, pt))
2844 {
2845 pt.x = min(pt.x, rect.right - 1);
2846 pt.x = max(pt.x, 0);
2847 pt.y = min(pt.y, rect.bottom - 1);
2848 pt.y = max(pt.y, 0);
2849 hit = FALSE;
2850 }
2851
2853
2854 if(index == -1)
2855 {
2856 index = descr->nb_items - 1;
2857 hit = FALSE;
2858 }
2859 return MAKELONG(index, hit ? 0 : 1);
2860 }
2861
2862 case LB_SETCARETINDEX:
2863 if ((!IS_MULTISELECT(descr)) && (descr->selected_item != -1)) return LB_ERR;
2865 return LB_ERR;
2866 else if (ISWIN31)
2867 return wParam;
2868 else
2869 return LB_OKAY;
2870
2871 case LB_GETCARETINDEX:
2872 return descr->focus_item;
2873
2874 case LB_SETTOPINDEX:
2875 return LISTBOX_SetTopItem( descr, wParam, TRUE );
2876
2877 case LB_SETCOLUMNWIDTH:
2879
2880 case LB_GETITEMRECT:
2882
2883 case LB_FINDSTRING:
2884 {
2885 INT ret;
2886 LPWSTR textW;
2887 if(unicode || !HAS_STRINGS(descr))
2888 textW = (LPWSTR)lParam;
2889 else
2890 {
2892 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
2893 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
2894 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
2895 }
2897 if(!unicode && HAS_STRINGS(descr))
2899 return ret;
2900 }
2901
2902 case LB_FINDSTRINGEXACT:
2903 {
2904 INT ret;
2905 LPWSTR textW;
2906 if(unicode || !HAS_STRINGS(descr))
2907 textW = (LPWSTR)lParam;
2908 else
2909 {
2911 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
2912 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
2913 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
2914 }
2916 if(!unicode && HAS_STRINGS(descr))
2918 return ret;
2919 }
2920
2921 case LB_SELECTSTRING:
2922 {
2923 INT index;
2924 LPWSTR textW;
2925
2926 if(HAS_STRINGS(descr))
2927 TRACE("LB_SELECTSTRING: %s\n", unicode ? debugstr_w((LPWSTR)lParam) :
2929 if(unicode || !HAS_STRINGS(descr))
2930 textW = (LPWSTR)lParam;
2931 else
2932 {
2934 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
2935 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
2936 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
2937 }
2939 if(!unicode && HAS_STRINGS(descr))
2941 if (index != LB_ERR)
2942 {
2945 }
2946 return index;
2947 }
2948
2949 case LB_GETSEL:
2950 if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
2951 return LB_ERR;
2952 return descr->items[wParam].selected;
2953
2954 case LB_SETSEL:
2956
2957 case LB_SETCURSEL:
2958 if (IS_MULTISELECT(descr)) return LB_ERR;
2961 if (ret != LB_ERR) ret = descr->selected_item;
2962 return ret;
2963
2964 case LB_GETSELCOUNT:
2965 return LISTBOX_GetSelCount( descr );
2966
2967 case LB_GETSELITEMS:
2969
2970 case LB_SELITEMRANGE:
2971 if (LOWORD(lParam) <= HIWORD(lParam))
2973 HIWORD(lParam), wParam );
2974 else
2976 LOWORD(lParam), wParam );
2977
2978 case LB_SELITEMRANGEEX:
2979 if ((INT)lParam >= (INT)wParam)
2981 else
2983
2985 return descr->horz_extent;
2986
2989
2990 case LB_GETANCHORINDEX:
2991 return descr->anchor_item;
2992
2993 case LB_SETANCHORINDEX:
2994 if (((INT)wParam < -1) || ((INT)wParam >= descr->nb_items))
2995 {
2997 return LB_ERR;
2998 }
2999 descr->anchor_item = (INT)wParam;
3000 return LB_OKAY;
3001
3002 case LB_DIR:
3003 {
3004 INT ret;
3005 LPWSTR textW;
3006 if(unicode)
3007 textW = (LPWSTR)lParam;
3008 else
3009 {
3011 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
3012 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
3013 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
3014 }
3016 if(!unicode)
3018 return ret;
3019 }
3020
3021 case LB_GETLOCALE:
3022 return descr->locale;
3023
3024 case LB_SETLOCALE:
3025 {
3026 LCID ret;
3028 return LB_ERR;
3029 ret = descr->locale;
3030 descr->locale = (LCID)wParam;
3031 return ret;
3032 }
3033
3034 case LB_INITSTORAGE:
3035 return LISTBOX_InitStorage( descr, wParam );
3036
3037 case LB_SETCOUNT:
3038 return LISTBOX_SetCount( descr, (INT)wParam );
3039
3040 case LB_SETTABSTOPS:
3042
3043 case LB_CARETON:
3044 if (descr->caret_on)
3045 return LB_OKAY;
3046 descr->caret_on = TRUE;
3047 if ((descr->focus_item != -1) && (descr->in_focus))
3048 LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
3049 return LB_OKAY;
3050
3051 case LB_CARETOFF:
3052 if (!descr->caret_on)
3053 return LB_OKAY;
3054 descr->caret_on = FALSE;
3055 if ((descr->focus_item != -1) && (descr->in_focus))
3056 LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
3057 return LB_OKAY;
3058
3059 case LB_GETLISTBOXINFO:
3060 return descr->page_size;
3061
3062 case WM_DESTROY:
3063 return LISTBOX_Destroy( descr );
3064
3065 case WM_ENABLE:
3066 InvalidateRect( descr->self, NULL, TRUE );
3067 return 0;
3068
3069 case WM_SETREDRAW:
3071 return 0;
3072
3073 case WM_GETDLGCODE:
3075
3076 case WM_PRINTCLIENT:
3077 case WM_PAINT:
3078 {
3079 PAINTSTRUCT ps;
3080 HDC hdc = ( wParam ) ? ((HDC)wParam) : BeginPaint( descr->self, &ps );
3081 ret = LISTBOX_Paint( descr, hdc );
3082 if( !wParam ) EndPaint( descr->self, &ps );
3083 }
3084 return ret;
3085 case WM_SIZE:
3087 return 0;
3088 case WM_GETFONT:
3089 return (LRESULT)descr->font;
3090 case WM_SETFONT:
3092 if (lParam) InvalidateRect( descr->self, 0, TRUE );
3093 return 0;
3094 case WM_SETFOCUS:
3095 descr->in_focus = TRUE;
3096 descr->caret_on = TRUE;
3097 if (descr->focus_item != -1)
3100 return 0;
3101 case WM_KILLFOCUS:
3102 LISTBOX_HandleLButtonUp( descr ); /* Release capture if we have it */
3103 descr->in_focus = FALSE;
3104 descr->wheel_remain = 0;
3105 if ((descr->focus_item != -1) && descr->caret_on)
3106 LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
3108 return 0;
3109 case WM_HSCROLL:
3111 case WM_VSCROLL:
3113 case WM_MOUSEWHEEL:
3114 if (wParam & (MK_SHIFT | MK_CONTROL))
3115 return DefWindowProcW( descr->self, msg, wParam, lParam );
3117 case WM_LBUTTONDOWN:
3118 if (lphc)
3121 (INT16)HIWORD(lParam) );
3124 (INT16)HIWORD(lParam) );
3125 case WM_LBUTTONDBLCLK:
3126 if (lphc)
3129 (INT16)HIWORD(lParam) );
3130 if (descr->style & LBS_NOTIFY)
3132 return 0;
3133 case WM_MOUSEMOVE:
3134 if ( lphc && ((lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE) )
3135 {
3136 BOOL captured = descr->captured;
3137 POINT mousePos;
3138 RECT clientRect;
3139
3140 mousePos.x = (INT16)LOWORD(lParam);
3141 mousePos.y = (INT16)HIWORD(lParam);
3142
3143 /*
3144 * If we are in a dropdown combobox, we simulate that
3145 * the mouse is captured to show the tracking of the item.
3146 */
3147 if (GetClientRect(descr->self, &clientRect) && PtInRect( &clientRect, mousePos ))
3148 descr->captured = TRUE;
3149
3150 LISTBOX_HandleMouseMove( descr, mousePos.x, mousePos.y);
3151
3152 descr->captured = captured;
3153 }
3154 else if (GetCapture() == descr->self)
3155 {
3157 (INT16)HIWORD(lParam) );
3158 }
3159 return 0;
3160 case WM_LBUTTONUP:
3161 if (lphc)
3162 {
3163 POINT mousePos;
3164 RECT clientRect;
3165
3166 /*
3167 * If the mouse button "up" is not in the listbox,
3168 * we make sure there is no selection by re-selecting the
3169 * item that was selected when the listbox was made visible.
3170 */
3171 mousePos.x = (INT16)LOWORD(lParam);
3172 mousePos.y = (INT16)HIWORD(lParam);
3173
3174 GetClientRect(descr->self, &clientRect);
3175
3176 /*
3177 * When the user clicks outside the combobox and the focus
3178 * is lost, the owning combobox will send a fake buttonup with
3179 * 0xFFFFFFF as the mouse location, we must also revert the
3180 * selection to the original selection.
3181 */
3182 if ( (lParam == (LPARAM)-1) || (!PtInRect( &clientRect, mousePos )) )
3184 }
3186 case WM_KEYDOWN:
3187 if( lphc && (lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE )
3188 {
3189 /* for some reason Windows makes it possible to
3190 * show/hide ComboLBox by sending it WM_KEYDOWNs */
3191
3192 if( (!(lphc->wState & CBF_EUI) && wParam == VK_F4) ||
3193 ( (lphc->wState & CBF_EUI) && !(lphc->wState & CBF_DROPPED)
3194 && (wParam == VK_DOWN || wParam == VK_UP)) )
3195 {
3196 COMBO_FlipListbox( lphc, FALSE, FALSE );
3197 return 0;
3198 }
3199 }
3201 case WM_CHAR:
3202 {
3203 WCHAR charW;
3204 if(unicode)
3205 charW = (WCHAR)wParam;
3206 else
3207 {
3208 CHAR charA = (CHAR)wParam;
3209 MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
3210 }
3211 return LISTBOX_HandleChar( descr, charW );
3212 }
3213 case WM_SYSTIMER:
3215 case WM_ERASEBKGND:
3216 if ((IS_OWNERDRAW(descr)) && !(descr->style & LBS_DISPLAYCHANGED))
3217 {
3218 RECT rect;
3219#ifdef __REACTOS__
3220 HBRUSH hbrush = GetControlColor( descr->owner, descr->self, (HDC)wParam, WM_CTLCOLORLISTBOX);
3221#else
3222 HBRUSH hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
3223 wParam, (LPARAM)descr->self );
3224#endif
3225 TRACE("hbrush = %p\n", hbrush);
3226 if(!hbrush)
3228 if(hbrush)
3229 {
3230 GetClientRect(descr->self, &rect);
3232 }
3233 }
3234 return 1;
3235 case WM_DROPFILES:
3236 if( lphc ) return 0;
3237 return unicode ? SendMessageW( descr->owner, msg, wParam, lParam ) :
3238 SendMessageA( descr->owner, msg, wParam, lParam );
3239
3240 case WM_NCDESTROY:
3241 if( lphc && (lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE )
3242 lphc->hWndLBox = 0;
3243#ifdef __REACTOS__
3245#endif
3246 break;
3247
3248 case WM_NCACTIVATE:
3249 if (lphc) return 0;
3250 break;
3251// ReactOS
3252 case WM_UPDATEUISTATE:
3253 if (unicode)
3255 else
3257
3259 {
3260 /* redraw text */
3261 if (descr->focus_item != -1)
3262 LISTBOX_DrawFocusRect( descr, descr->in_focus );
3263 }
3264 break;
3265//
3266 default:
3267 if ((msg >= WM_USER) && (msg < 0xc000))
3268 WARN("[%p]: unknown msg %04x wp %08lx lp %08lx\n",
3269 hwnd, msg, wParam, lParam );
3270 }
3271
3272 return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
3274}
3275
3276/***********************************************************************
3277 * ListBoxWndProcA
3278 */
3280{
3282}
3283
3284/***********************************************************************
3285 * ListBoxWndProcW
3286 */
3288{
3290}
static HRGN hrgn
static HBRUSH hbrush
signed short INT16
Arabic default style
Definition: afstyles.h:94
unsigned int dir
Definition: maze.c:112
static const char * wine_dbgstr_rect(const RECT *prc)
Definition: atltest.h:160
#define msg(x)
Definition: auth_time.c:54
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define index(s, c)
Definition: various.h:29
#define CHAR(Char)
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
Definition: _locale.h:75
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define WM_SYSTIMER
Definition: comctl32.h:125
#define LB_INSERTSTRING_LOWER
Definition: controls.h:87
#define CBF_SELCHANGE
Definition: controls.h:55
#define CBF_DROPPED
Definition: controls.h:45
#define LB_INSERTSTRING_UPPER
Definition: controls.h:86
#define LB_ADDSTRING_LOWER
Definition: controls.h:89
#define CBF_EUI
Definition: controls.h:59
#define CBF_NOROLLUP
Definition: controls.h:47
#define LB_ADDSTRING_UPPER
Definition: controls.h:88
static char selected[MAX_PATH+1]
Definition: dirdlg.c:7
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
HRGN set_control_clipping(HDC hdc, const RECT *rect)
Definition: button.c:242
BOOL COMBO_FlipListbox(LPHEADCOMBO lphc, BOOL ok, BOOL bRedrawButton)
Definition: combo.c:1082
static LRESULT LISTBOX_RemoveItem(LB_DESCR *descr, INT index)
Definition: listbox.c:1764
#define SEND_NOTIFICATION(descr, code)
Definition: listbox.c:111
static LRESULT LISTBOX_InsertString(LB_DESCR *descr, INT index, LPCWSTR str)
Definition: listbox.c:1701
static void LISTBOX_DrawFocusRect(LB_DESCR *descr, BOOL on)
Definition: listbox.c:775
static void LISTBOX_SetHorizontalPos(LB_DESCR *descr, INT pos)
Definition: listbox.c:1332
static LRESULT LISTBOX_HandleKeyDown(LB_DESCR *descr, DWORD key)
Definition: listbox.c:2429
static LRESULT LISTBOX_SetCaretIndex(LB_DESCR *descr, INT index, BOOL fully_visible)
Definition: listbox.c:1478
static BOOL LISTBOX_SetTabStops(LB_DESCR *descr, INT count, LPINT tabs)
Definition: listbox.c:815
static LRESULT LISTBOX_HandleLButtonUp(LB_DESCR *descr)
Definition: listbox.c:2309
#define ATTRIBS
static void LISTBOX_DeleteItem(LB_DESCR *descr, INT index)
Definition: listbox.c:1736
static void LISTBOX_InvalidateItems(LB_DESCR *descr, INT index)
Definition: listbox.c:1243
static LRESULT LISTBOX_GetSelCount(const LB_DESCR *descr)
Definition: listbox.c:1053
static void LISTBOX_SetRedraw(LB_DESCR *descr, BOOL on)
Definition: listbox.c:715
static void LISTBOX_InvalidateItemRect(LB_DESCR *descr, INT index)
Definition: listbox.c:1267
static LRESULT LISTBOX_GetText(LB_DESCR *descr, INT index, LPWSTR buffer, BOOL unicode)
Definition: listbox.c:847
#define ISWIN31
Definition: listbox.c:115
static LRESULT LISTBOX_InitStorage(LB_DESCR *descr, INT nb_items)
Definition: listbox.c:802
static void LISTBOX_MakeItemVisible(LB_DESCR *descr, INT index, BOOL fully)
Definition: listbox.c:1439
static INT LISTBOX_FindFileStrPos(LB_DESCR *descr, LPCWSTR str)
Definition: listbox.c:949
static LRESULT LISTBOX_SetSelection(LB_DESCR *descr, INT index, BOOL on, BOOL send_notify)
Definition: listbox.c:1547
static LRESULT LISTBOX_HandleLButtonDownCombo(LB_DESCR *descr, UINT msg, DWORD keys, INT x, INT y)
Definition: listbox.c:2231
static LRESULT LISTBOX_HandleVScroll(LB_DESCR *descr, WORD scrollReq, WORD pos)
Definition: listbox.c:1958
#define IS_MULTISELECT(descr)
Definition: listbox.c:107
static void LISTBOX_ResetContent(LB_DESCR *descr)
Definition: listbox.c:1816
static LRESULT LISTBOX_HandleTimer(LB_DESCR *descr, INT index, TIMER_DIRECTION dir)
Definition: listbox.c:2331
#define HAS_STRINGS(descr)
Definition: listbox.c:103
static LRESULT LISTBOX_HandleMouseWheel(LB_DESCR *descr, SHORT delta)
Definition: listbox.c:2088
TIMER_DIRECTION
Definition: listbox.c:119
@ LB_TIMER_NONE
Definition: listbox.c:120
@ LB_TIMER_UP
Definition: listbox.c:121
@ LB_TIMER_RIGHT
Definition: listbox.c:124
@ LB_TIMER_DOWN
Definition: listbox.c:123
@ LB_TIMER_LEFT
Definition: listbox.c:122
static LRESULT LISTBOX_SetHorizontalExtent(LB_DESCR *descr, INT extent)
Definition: listbox.c:1360
static LRESULT LISTBOX_InsertItem(LB_DESCR *descr, INT index, LPWSTR str, ULONG_PTR data)
Definition: listbox.c:1637
static void LISTBOX_MoveCaret(LB_DESCR *descr, INT index, BOOL fully_visible)
Definition: listbox.c:1590
static LRESULT LISTBOX_GetSelItems(const LB_DESCR *descr, INT max, LPINT array)
Definition: listbox.c:1069
static LRESULT LISTBOX_Paint(LB_DESCR *descr, HDC hdc)
Definition: listbox.c:1083
static void LISTBOX_UpdateScroll(LB_DESCR *descr)
Definition: listbox.c:303
static TIMER_DIRECTION LISTBOX_Timer
Definition: listbox.c:127
static LRESULT LISTBOX_SetTopItem(LB_DESCR *descr, INT index, BOOL scroll)
Definition: listbox.c:386
static INT LISTBOX_SetFont(LB_DESCR *descr, HFONT font)
Definition: listbox.c:1408
static LRESULT LISTBOX_SetColumnWidth(LB_DESCR *descr, INT column_width)
Definition: listbox.c:1386
static LRESULT LISTBOX_HandleHScroll(LB_DESCR *descr, WORD scrollReq, WORD pos)
Definition: listbox.c:2002
static LRESULT LISTBOX_SelectItemRange(LB_DESCR *descr, INT first, INT last, BOOL on)
Definition: listbox.c:1507
static void LISTBOX_RepaintItem(LB_DESCR *descr, INT index, UINT action)
Definition: listbox.c:742
static LRESULT LISTBOX_GetItemRect(const LB_DESCR *descr, INT index, RECT *rect)
Definition: listbox.c:500
static INT LISTBOX_FindString(LB_DESCR *descr, INT start, LPCWSTR str, BOOL exact)
Definition: listbox.c:993
static BOOL LISTBOX_Destroy(LB_DESCR *descr)
Definition: listbox.c:2660
#define LB_ARRAY_GRANULARITY
Definition: listbox.c:43
static LRESULT LISTBOX_HandleSystemTimer(LB_DESCR *descr)
Definition: listbox.c:2365
#define LB_TIMER_ID
Definition: listbox.c:49
static LRESULT LISTBOX_Directory(LB_DESCR *descr, UINT attrib, LPCWSTR filespec, BOOL long_names)
Definition: listbox.c:1875
static void LISTBOX_HandleMouseMove(LB_DESCR *descr, INT x, INT y)
Definition: listbox.c:2381
static LRESULT LISTBOX_GetItemHeight(const LB_DESCR *descr, INT index)
Definition: listbox.c:1278
#define LB_SCROLL_TIMEOUT
Definition: listbox.c:46
static INT LISTBOX_FindStringPos(LB_DESCR *descr, LPCWSTR str, BOOL exact)
Definition: listbox.c:905
static void LISTBOX_PaintItem(LB_DESCR *descr, HDC hdc, const RECT *rect, INT index, UINT action, BOOL ignoreFocus)
Definition: listbox.c:605
#define IS_OWNERDRAW(descr)
Definition: listbox.c:100
static INT LISTBOX_GetItemFromPoint(const LB_DESCR *descr, INT x, INT y)
Definition: listbox.c:558
static INT LISTBOX_lstrcmpiW(LCID lcid, LPCWSTR str1, LPCWSTR str2)
Definition: listbox.c:887
#define LBS_DISPLAYCHANGED
Definition: listbox.c:52
static LRESULT LISTBOX_HandleChar(LB_DESCR *descr, WCHAR charW)
Definition: listbox.c:2540
static void LISTBOX_UpdatePage(LB_DESCR *descr)
Definition: listbox.c:435
static LRESULT LISTBOX_SetItemHeight(LB_DESCR *descr, INT index, INT height, BOOL repaint)
Definition: listbox.c:1296
static void LISTBOX_UpdateSize(LB_DESCR *descr)
Definition: listbox.c:455
static INT LISTBOX_GetCurrentPageSize(const LB_DESCR *descr)
Definition: listbox.c:253
static LRESULT LISTBOX_SetCount(LB_DESCR *descr, UINT count)
Definition: listbox.c:1836
static INT LISTBOX_GetMaxTopIndex(const LB_DESCR *descr)
Definition: listbox.c:271
static BOOL LISTBOX_Create(HWND hwnd, LPHEADCOMBO lphc)
Definition: listbox.c:2572
static LRESULT LISTBOX_HandleLButtonDown(LB_DESCR *descr, DWORD keys, INT x, INT y)
Definition: listbox.c:2126
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define CP_ACP
Definition: compat.h:109
#define SetLastError(x)
Definition: compat.h:752
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define HeapFree(x, y, z)
Definition: compat.h:735
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
UINT WINAPI GetDriveTypeW(IN LPCWSTR lpRootPathName)
Definition: disk.c:497
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: locale.c:4017
BOOL WINAPI IsValidLocale(LCID lcid, DWORD flags)
Definition: locale.c:2925
LCID WINAPI GetUserDefaultLCID(void)
Definition: locale.c:1216
LCID lcid
Definition: locale.c:5656
const UINT * keys
Definition: locale.c:416
LPWSTR WINAPI CharLowerW(WCHAR *str)
Definition: string.c:1092
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
#define pt(x, y)
Definition: drawing.c:79
return ret
Definition: mutex.c:146
action
Definition: namespace.c:707
#define ULONG_PTR
Definition: config.h:101
#define abs(i)
Definition: fconv.c:206
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
pKey DeleteObject()
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLint GLint GLsizei width
Definition: gl.h:1546
GLuint res
Definition: glext.h:9613
GLuint buffer
Definition: glext.h:5915
GLuint index
Definition: glext.h:6031
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
const GLint * first
Definition: glext.h:5794
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define FNID_DESTROY
Definition: ntuser.h:898
#define FNID_LISTBOX
Definition: ntuser.h:871
BOOL NTAPI NtUserSetWindowFNID(HWND hWnd, WORD fnID)
Definition: window.c:4348
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
uint32_t entry
Definition: isohybrid.c:63
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
if(dx< 0)
Definition: linetemp.h:194
LONG_PTR LPARAM
Definition: minwindef.h:175
LONG_PTR LRESULT
Definition: minwindef.h:176
UINT_PTR WPARAM
Definition: minwindef.h:174
int * LPINT
Definition: minwindef.h:151
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
HDC hdc
Definition: main.c:9
static const char textA[]
Definition: registrar.c:40
static HDC
Definition: imagelist.c:88
static void send_notify(HWND pager, UINT unicode, UINT ansi, LPARAM lParam, BOOL code_change)
Definition: pager.c:918
static const WCHAR textW[]
Definition: itemdlg.c:1559
static UINT UINT last
Definition: font.c:45
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
static DWORD page_size
Definition: loader.c:53
static const WCHAR dotW[]
Definition: directory.c:80
static float(__cdecl *square_half_float)(float x
#define WM_LBTRACKPOINT
Definition: msg.c:59
#define min(a, b)
Definition: monoChain.cc:55
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
Definition: muldiv.c:25
Definition: mk_font.cpp:20
unsigned int UINT
Definition: ndis.h:50
#define LPDWORD
Definition: nt_native.h:46
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define DWORD
Definition: nt_native.h:44
#define MAXBYTE
static TCHAR * items[]
Definition: page1.c:45
#define LOWORD(l)
Definition: pedump.c:82
#define LBS_DISABLENOSCROLL
Definition: pedump.c:690
#define LBS_SORT
Definition: pedump.c:679
#define LBS_OWNERDRAWFIXED
Definition: pedump.c:682
#define LBS_HASSTRINGS
Definition: pedump.c:684
#define LBS_MULTICOLUMN
Definition: pedump.c:687
#define WS_VSCROLL
Definition: pedump.c:627
#define LBS_OWNERDRAWVARIABLE
Definition: pedump.c:683
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
#define LBS_MULTIPLESEL
Definition: pedump.c:681
#define LBS_USETABSTOPS
Definition: pedump.c:685
#define WS_HSCROLL
Definition: pedump.c:628
#define LBS_NOINTEGRALHEIGHT
Definition: pedump.c:686
#define LBS_NOTIFY
Definition: pedump.c:678
#define LBS_EXTENDEDSEL
Definition: pedump.c:689
#define LBS_WANTKEYBOARDINPUT
Definition: pedump.c:688
#define LBS_NOREDRAW
Definition: pedump.c:680
#define INT
Definition: polytest.cpp:20
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
#define WM_PRINTCLIENT
Definition: richedit.h:70
const WCHAR * str
DWORD LCID
Definition: nls.h:13
const char * descr
Definition: boot.c:45
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE(s)
Definition: solgame.cpp:4
& rect
Definition: startmenu.cpp:1413
INT fixedOwnerDrawHeight
Definition: comctl32.h:161
UINT wState
Definition: comctl32.h:155
HWND hWndLBox
Definition: comctl32.h:154
INT droppedIndex
Definition: comctl32.h:160
HWND self
Definition: comctl32.h:150
UINT dwStyle
Definition: comctl32.h:152
LPHEADCOMBO lphc
Definition: listbox.c:86
LONG UIState
Definition: listbox.c:87
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
Definition: ntuser.h:694
DWORD fnid
Definition: ntuser.h:709
Definition: copy.c:22
Definition: module.h:576
ULONG_PTR itemData1
Definition: winuser.h:3096
ULONG_PTR itemData2
Definition: winuser.h:3098
LPVOID lpCreateParams
Definition: winuser.h:3057
ULONG_PTR itemData
Definition: winuser.h:3146
ULONG_PTR itemData
Definition: winuser.h:3195
ULONG_PTR itemData
Definition: winuser.h:3748
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
Definition: windef.h:99
LONG right
Definition: windef.h:102
LONG bottom
Definition: windef.h:103
LONG top
Definition: windef.h:101
#define max(a, b)
Definition: svc.c:63
#define WHEEL_DELTA
Definition: treelist.c:99
#define WM_MOUSEWHEEL
Definition: treelist.c:96
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MAKELONG(a, b)
Definition: typedefs.h:249
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
#define HIWORD(l)
Definition: typedefs.h:247
#define WS_EX_DRAGDETECT
Definition: undocuser.h:23
#define LB_CARETON
Definition: undocuser.h:53
#define LB_CARETOFF
Definition: undocuser.h:54
#define WM_BEGINDRAG
Definition: undocuser.h:58
const char * SPY_GetMsgName(UINT msg, HWND hWnd)
Definition: spy.c:2218
#define ValidateHwnd(hwnd)
Definition: precomp.h:101
HBRUSH FASTCALL GetControlColor(PWND pwndParent, PWND pwnd, HDC hdc, UINT CtlMsg)
Definition: misc.c:154
static const WCHAR empty_stringW[]
Definition: edit.c:173
const struct builtin_class_descr LISTBOX_builtin_class
Definition: listbox.c:126
static const WCHAR listboxW[]
Definition: listbox.c:125
LRESULT WINAPI ListBoxWndProcW(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: listbox.c:3287
LRESULT WINAPI ListBoxWndProcA(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: listbox.c:3279
static const WCHAR combolboxW[]
Definition: listbox.c:141
static BOOL LISTBOX_update_uistate(LB_DESCR *descr)
Definition: listbox.c:2500
#define CHECK_DRIVE(item)
const struct builtin_class_descr COMBOLBOX_builtin_class
Definition: listbox.c:142
LRESULT WINAPI ListBoxWndProc_common(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode)
Definition: listbox.c:2616
#define DRIVE_NO_ROOT_DIR
Definition: winbase.h:281
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
DWORD COLORREF
Definition: windef.h:94
#define WINAPI
Definition: msvc.h:6
#define strncmpiW(s1, s2, n)
Definition: unicode.h:46
#define strcmpW(s1, s2)
Definition: unicode.h:44
#define struprW(s)
Definition: unicode.h:63
#define strlenW(s)
Definition: unicode.h:34
#define strlwrW(s)
Definition: unicode.h:62
#define strcatW(d, s)
Definition: unicode.h:36
#define strcpyW(d, s)
Definition: unicode.h:35
#define ERROR_INVALID_INDEX
Definition: winerror.h:1239
#define ERROR_SETCOUNT_ON_BAD_LB
Definition: winerror.h:1259
#define ERROR_LB_WITHOUT_TABSTOPS
Definition: winerror.h:1260
#define ERROR_NO_MORE_FILES
Definition: winerror.h:243
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:999
BOOL WINAPI SetWindowOrgEx(_In_ HDC, _In_ int, _In_ int, _Out_opt_ LPPOINT)
Definition: coord.c:532
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1546
#define ETO_CLIPPED
Definition: wingdi.h:648
BOOL WINAPI ExtTextOutW(_In_ HDC hdc, _In_ int x, _In_ int y, _In_ UINT options, _In_opt_ const RECT *lprect, _In_reads_opt_(c) LPCWSTR lpString, _In_ UINT c, _In_reads_opt_(c) const INT *lpDx)
#define ETO_OPAQUE
Definition: wingdi.h:647
int WINAPI FillRect(HDC, LPCRECT, HBRUSH)
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:917
int WINAPI SelectClipRgn(_In_ HDC, _In_opt_ HRGN)
BOOL WINAPI GetTextExtentPointA(_In_ HDC hdc, _In_reads_(c) LPCSTR lpString, _In_ int c, _Out_ LPSIZE lpsz)
#define NORM_IGNORECASE
Definition: winnls.h:187
#define LCID_INSTALLED
Definition: winnls.h:214
#define CSTR_EQUAL
Definition: winnls.h:500
#define CSTR_LESS_THAN
Definition: winnls.h:499
#define CSTR_GREATER_THAN
Definition: winnls.h:501
#define WM_PAINT
Definition: winuser.h:1648
#define ODS_DISABLED
Definition: winuser.h:2583
#define LB_ERR
Definition: winuser.h:2468
HWND WINAPI SetCapture(_In_ HWND hWnd)
#define LB_ADDFILE
Definition: winuser.h:2059
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define WM_ERASEBKGND
Definition: winuser.h:1653
DWORD WINAPI GetSysColor(_In_ int)
#define LBN_ERRSPACE
Definition: winuser.h:2108
#define MAKEWPARAM(l, h)
Definition: winuser.h:4111
BOOL WINAPI IsWindow(_In_opt_ HWND)
#define MK_SHIFT
Definition: winuser.h:2405
#define LB_GETCOUNT
Definition: winuser.h:2067
#define ODS_SELECTED
Definition: winuser.h:2581
#define LB_FINDSTRINGEXACT
Definition: winuser.h:2064
#define SWP_NOACTIVATE
Definition: winuser.h:1253
#define LB_GETITEMDATA
Definition: winuser.h:2070
#define SB_THUMBTRACK
Definition: winuser.h:573
#define GetWindowLongPtrW
Definition: winuser.h:4931
#define WM_ENABLE
Definition: winuser.h:1643
#define SB_LINEUP
Definition: winuser.h:564
#define WM_HSCROLL
Definition: winuser.h:1771
#define MAKELPARAM(l, h)
Definition: winuser.h:4110
#define LB_SETHORIZONTALEXTENT
Definition: winuser.h:2100
#define COLOR_GRAYTEXT
Definition: winuser.h:943
#define COLOR_WINDOW
Definition: winuser.h:929
#define DCX_CACHE
Definition: winuser.h:2150
BOOL WINAPI ReleaseCapture(void)
Definition: message.c:2890
#define WM_CHARTOITEM
Definition: winuser.h:1677
#define ODA_DRAWENTIRE
Definition: winuser.h:2578
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define LBN_SELCANCEL
Definition: winuser.h:2110
#define CBS_DROPDOWNLIST
Definition: winuser.h:284
#define LB_SETCOUNT
Definition: winuser.h:2098
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define LB_OKAY
Definition: winuser.h:2467
#define LB_GETTEXT
Definition: winuser.h:2085
#define LB_SETTOPINDEX
Definition: winuser.h:2106
#define WM_VSCROLL
Definition: winuser.h:1772
#define SW_SCROLLCHILDREN
Definition: winuser.h:2614
#define LBN_DBLCLK
Definition: winuser.h:2107
BOOL WINAPI GetWindowRect(_In_ HWND, _Out_ LPRECT)
#define SIF_RANGE
Definition: winuser.h:1246
#define WM_CREATE
Definition: winuser.h:1636
#define DLGC_WANTCHARS
Definition: winuser.h:2660
BOOL WINAPI SetWindowPos(_In_ HWND, _In_opt_ HWND, _In_ int, _In_ int, _In_ int, _In_ int, _In_ UINT)
#define SB_PAGERIGHT
Definition: winuser.h:571
#define SM_CXVSCROLL
Definition: winuser.h:972
#define VK_SPACE
Definition: winuser.h:2255
#define LB_DIR
Definition: winuser.h:2062
#define WM_SIZE
Definition: winuser.h:1639
#define COLOR_HIGHLIGHT
Definition: winuser.h:937
HBRUSH WINAPI GetSysColorBrush(_In_ int)
#define SB_VERT
Definition: winuser.h:553
#define SB_LEFT
Definition: winuser.h:575
#define WM_DROPFILES
Definition: winuser.h:1853
#define SB_BOTTOM
Definition: winuser.h:577
#define LB_GETSELCOUNT
Definition: winuser.h:2083
#define WM_LBUTTONDBLCLK
Definition: winuser.h:1806
#define SWP_NOMOVE
Definition: winuser.h:1255
#define SW_INVALIDATE
Definition: winuser.h:2615
#define LB_GETITEMRECT
Definition: winuser.h:2072
#define ODA_FOCUS
Definition: winuser.h:2580
#define HTVSCROLL
Definition: winuser.h:2518
#define HTHSCROLL
Definition: winuser.h:2517
#define IDC_ARROW
Definition: winuser.h:695
#define LBN_SETFOCUS
Definition: winuser.h:2112
#define LB_GETTOPINDEX
Definition: winuser.h:2087
#define LB_GETANCHORINDEX
Definition: winuser.h:2065
#define LB_ERRSPACE
Definition: winuser.h:2469
#define VK_UP
Definition: winuser.h:2261
LRESULT WINAPI SendMessageA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define DDL_DRIVES
Definition: winuser.h:425
#define WM_SETFOCUS
Definition: winuser.h:1641
#define SIF_PAGE
Definition: winuser.h:1244
#define WM_MOUSEMOVE
Definition: winuser.h:1803
#define LB_GETLOCALE
Definition: winuser.h:2081
HDC WINAPI GetDCEx(_In_opt_ HWND, _In_opt_ HRGN, _In_ DWORD)
HWND WINAPI GetCapture(void)
Definition: message.c:2881
#define LB_SETLOCALE
Definition: winuser.h:2103
#define SB_LINERIGHT
Definition: winuser.h:567
#define CS_DBLCLKS
Definition: winuser.h:659
#define WM_LBUTTONDOWN
Definition: winuser.h:1804
#define LB_GETSEL
Definition: winuser.h:2082
#define LB_ADDSTRING
Definition: winuser.h:2060
#define LB_SETCOLUMNWIDTH
Definition: winuser.h:2097
#define SIF_TRACKPOS
Definition: winuser.h:1248
#define WM_GETFONT
Definition: winuser.h:1679
#define WM_DELETEITEM
Definition: winuser.h:1675
BOOL WINAPI ClientToScreen(_In_ HWND, _Inout_ LPPOINT)
#define LB_SELITEMRANGEEX
Definition: winuser.h:2094
#define SM_CYHSCROLL
Definition: winuser.h:973
#define WM_DRAWITEM
Definition: winuser.h:1673
#define VK_NEXT
Definition: winuser.h:2257
#define LB_SELITEMRANGE
Definition: winuser.h:2093
#define LB_SETANCHORINDEX
Definition: winuser.h:2095
#define LB_SETITEMHEIGHT
Definition: winuser.h:2102
BOOL WINAPI PtInRect(_In_ LPCRECT, _In_ POINT)
#define DDL_EXCLUSIVE
Definition: winuser.h:426
#define CBS_SIMPLE
Definition: winuser.h:291
UINT_PTR WINAPI SetSystemTimer(HWND, UINT_PTR, UINT, TIMERPROC)
Definition: ntwrapper.h:106
#define LB_SELECTSTRING
Definition: winuser.h:2092
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define WM_NCACTIVATE
Definition: winuser.h:1716
#define LBS_COMBOBOX
Definition: winuser.h:324
#define LB_RESETCONTENT
Definition: winuser.h:2091
#define LB_DELETESTRING
Definition: winuser.h:2061
#define SB_LINELEFT
Definition: winuser.h:566
BOOL WINAPI KillSystemTimer(HWND, UINT_PTR)
Definition: timer.c:35
HWND WINAPI SetFocus(_In_opt_ HWND)
#define LB_FINDSTRING
Definition: winuser.h:2063
#define MK_CONTROL
Definition: winuser.h:2406
#define DDL_DIRECTORY
Definition: winuser.h:422
#define LB_GETITEMHEIGHT
Definition: winuser.h:2071
#define WM_SETFONT
Definition: winuser.h:1678
#define VK_END
Definition: winuser.h:2258
#define VK_HOME
Definition: winuser.h:2259
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define LB_GETHORIZONTALEXTENT
Definition: winuser.h:2069
#define DLGC_WANTARROWS
Definition: winuser.h:2652
#define SIF_DISABLENOSCROLL
Definition: winuser.h:1247
#define LB_INSERTSTRING
Definition: winuser.h:2089
#define LBS_NODATA
Definition: winuser.h:313
#define SB_PAGEDOWN
Definition: winuser.h:569
#define COLOR_HIGHLIGHTTEXT
Definition: winuser.h:938
BOOL WINAPI DragDetect(_In_ HWND, _In_ POINT)
#define LB_ITEMFROMPOINT
Definition: winuser.h:2090
#define SB_LINEDOWN
Definition: winuser.h:565
#define CBS_DROPDOWN
Definition: winuser.h:283
#define WM_MEASUREITEM
Definition: winuser.h:1674
#define VK_F4
Definition: winuser.h:2294
#define WM_LBUTTONUP
Definition: winuser.h:1805
BOOL WINAPI SystemParametersInfoW(_In_ UINT uiAction, _In_ UINT uiParam, _Inout_opt_ PVOID pvParam, _In_ UINT fWinIni)
#define WM_CHAR
Definition: winuser.h:1745
BOOL WINAPI IsWindowEnabled(_In_ HWND)
#define LB_GETTEXTLEN
Definition: winuser.h:2086
HWND WINAPI GetParent(_In_ HWND)
#define LB_SETITEMDATA
Definition: winuser.h:2101
#define VK_LEFT
Definition: winuser.h:2260
#define LBN_SELCHANGE
Definition: winuser.h:2111
#define WM_NCDESTROY
Definition: winuser.h:1712
#define VK_RIGHT
Definition: winuser.h:2262
#define ODA_SELECT
Definition: winuser.h:2579
#define SB_TOP
Definition: winuser.h:578
#define CS_SAVEBITS
Definition: winuser.h:665
#define SIF_POS
Definition: winuser.h:1245
#define VK_DOWN
Definition: winuser.h:2263
#define LB_GETCARETINDEX
Definition: winuser.h:2066
#define GWLP_ID
Definition: winuser.h:871
#define SW_ERASE
Definition: winuser.h:2616
#define WM_USER
Definition: winuser.h:1923
#define LBN_KILLFOCUS
Definition: winuser.h:2109
#define WM_CTLCOLORLISTBOX
Definition: winuser.h:1796
#define LB_SETTABSTOPS
Definition: winuser.h:2105
#define VK_SHIFT
Definition: winuser.h:2238
#define LB_SETSEL
Definition: winuser.h:2104
#define VK_PRIOR
Definition: winuser.h:2256
int WINAPI SetScrollInfo(_In_ HWND, _In_ int, _In_ LPCSCROLLINFO, _In_ BOOL)
#define WM_DESTROY
Definition: winuser.h:1637
#define LBS_NOSEL
Definition: winuser.h:316
#define LB_SETCURSEL
Definition: winuser.h:2099
BOOL WINAPI ShowScrollBar(_In_ HWND, _In_ int, _In_ BOOL)
#define WM_KEYDOWN
Definition: winuser.h:1743
BOOL WINAPI DrawFocusRect(_In_ HDC, _In_ LPCRECT)
#define SB_RIGHT
Definition: winuser.h:576
#define WM_COMPAREITEM
Definition: winuser.h:1683
BOOL WINAPI InvalidateRect(_In_opt_ HWND, _In_opt_ LPCRECT, _In_ BOOL)
#define SWP_NOZORDER
Definition: winuser.h:1258
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
#define LB_GETCURSEL
Definition: winuser.h:2068
#define SetWindowLongPtrW
Definition: winuser.h:5457
#define GWL_STYLE
Definition: winuser.h:863
#define LB_GETSELITEMS
Definition: winuser.h:2084
BOOL WINAPI GetScrollInfo(_In_ HWND, _In_ int, _Inout_ LPSCROLLINFO)
#define LB_INITSTORAGE
Definition: winuser.h:2088
BOOL WINAPI IsWindowVisible(_In_ HWND)
int WINAPI ScrollWindowEx(_In_ HWND, _In_ int, _In_ int, _In_opt_ LPCRECT, _In_opt_ LPCRECT, _In_opt_ HRGN, _Out_opt_ LPRECT, _In_ UINT)
#define ODT_LISTBOX
Definition: winuser.h:2574
#define WM_KILLFOCUS
Definition: winuser.h:1642
#define ODS_FOCUS
Definition: winuser.h:2585
int WINAPI GetSystemMetrics(_In_ int)
#define SB_PAGEUP
Definition: winuser.h:568
#define WM_NCLBUTTONDOWN
Definition: winuser.h:1720
#define LB_SETCARETINDEX
Definition: winuser.h:2096
#define WM_GETDLGCODE
Definition: winuser.h:1717
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define SB_HORZ
Definition: winuser.h:552
SHORT WINAPI GetKeyState(_In_ int)
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
#define WM_VKEYTOITEM
Definition: winuser.h:1676
#define SB_PAGELEFT
Definition: winuser.h:570
#define GWL_EXSTYLE
Definition: winuser.h:862
#define WM_SETREDRAW
Definition: winuser.h:1644
#define SB_THUMBPOSITION
Definition: winuser.h:572
LONG WINAPI TabbedTextOutW(_In_ HDC hdc, _In_ int x, _In_ int y, _In_reads_(chCount) LPCWSTR lpString, _In_ int chCount, _In_ int nTabPositions, _In_reads_opt_(nTabPositions) CONST INT *lpnTabStopPositions, _In_ int nTabOrigin)
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char * LPSTR
Definition: xmlstorage.h:182
char CHAR
Definition: xmlstorage.h:175