ReactOS 0.4.16-dev-2491-g3dc6630
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#ifdef __REACTOS__
589 else
590 {
591 HBRUSH br = GetCurrentObject(hdc, OBJ_BRUSH);
592 FillRect(hdc, rect, br);
593 }
594#endif
595
596 TRACE("[%p]: painting %d (%s) action=%02x rect=%s\n",
597 descr->self, index, item ? debugstr_w(item->str) : "", action,
599 if (!item)
600 ExtTextOutW( hdc, rect->left + 1, rect->top,
602 else if (!(descr->style & LBS_USETABSTOPS))
603#ifdef __REACTOS__
604 {
605 RECT rc = *rect;
606 if (!item->selected)
607 {
608 SIZE sz;
609 GetTextExtentPoint32(hdc, item->str, strlenW(item->str), &sz);
610 rc.right = min(sz.cx, rc.right);
611 }
612 ExtTextOutW( hdc, rect->left + 1, rect->top,
613 ETO_OPAQUE | ETO_CLIPPED, &rc, item->str,
614 strlenW(item->str), NULL);
615 }
616#else
617 ExtTextOutW( hdc, rect->left + 1, rect->top,
619 strlenW(item->str), NULL );
620#endif
621 else
622 {
623 /* Output empty string to paint background in the full width. */
624 ExtTextOutW( hdc, rect->left + 1, rect->top,
626 TabbedTextOutW( hdc, rect->left + 1 , rect->top,
627 item->str, strlenW(item->str),
628 descr->nb_tabs, descr->tabs, 0);
629 }
630 if (item && item->selected)
631 {
632 SetBkColor( hdc, oldBk );
633 SetTextColor( hdc, oldText );
634 }
635 if (!ignoreFocus && (descr->focus_item == index) &&
636 (descr->caret_on) &&
637 (descr->in_focus) &&
638 !(descr->UIState & UISF_HIDEFOCUS)) DrawFocusRect( hdc, rect );
639 }
640}
641
642
643/***********************************************************************
644 * LISTBOX_SetRedraw
645 *
646 * Change the redraw flag.
647 */
649{
650 if (on)
651 {
652 if (!(descr->style & LBS_NOREDRAW)) return;
653 descr->style &= ~LBS_NOREDRAW;
654 if (descr->style & LBS_DISPLAYCHANGED)
655 { /* page was changed while setredraw false, refresh automatically */
656 InvalidateRect(descr->self, NULL, TRUE);
657 if ((descr->top_item + descr->page_size) > descr->nb_items)
658 { /* reset top of page if less than number of items/page */
659 descr->top_item = descr->nb_items - descr->page_size;
660 if (descr->top_item < 0) descr->top_item = 0;
661 }
662 descr->style &= ~LBS_DISPLAYCHANGED;
663 }
665 }
666 else descr->style |= LBS_NOREDRAW;
667}
668
669
670/***********************************************************************
671 * LISTBOX_RepaintItem
672 *
673 * Repaint a single item synchronously.
674 */
676{
677 HDC hdc;
678 RECT rect;
679 HFONT oldFont = 0;
680 HBRUSH hbrush, oldBrush = 0;
681
682 /* Do not repaint the item if the item is not visible */
683 if (!IsWindowVisible(descr->self)) return;
684 if (descr->style & LBS_NOREDRAW)
685 {
686 descr->style |= LBS_DISPLAYCHANGED;
687 return;
688 }
689 if (LISTBOX_GetItemRect( descr, index, &rect ) != 1) return;
690 if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE ))) return;
691 if (descr->font) oldFont = SelectObject( hdc, descr->font );
692#ifdef __REACTOS__
694#else
695 hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
696 (WPARAM)hdc, (LPARAM)descr->self );
697#endif
698 if (hbrush) oldBrush = SelectObject( hdc, hbrush );
699 if (!IsWindowEnabled(descr->self))
701 SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
703 if (oldFont) SelectObject( hdc, oldFont );
704 if (oldBrush) SelectObject( hdc, oldBrush );
705 ReleaseDC( descr->self, hdc );
706}
707
708
709/***********************************************************************
710 * LISTBOX_DrawFocusRect
711 */
713{
714 HDC hdc;
715 RECT rect;
716 HFONT oldFont = 0;
717
718 /* Do not repaint the item if the item is not visible */
719 if (!IsWindowVisible(descr->self)) return;
720
721 if (descr->focus_item == -1) return;
722 if (!descr->caret_on || !descr->in_focus) return;
723
724 if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) != 1) return;
725 if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE ))) return;
726 if (descr->font) oldFont = SelectObject( hdc, descr->font );
727 if (!IsWindowEnabled(descr->self))
729 SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
730 LISTBOX_PaintItem( descr, hdc, &rect, descr->focus_item, ODA_FOCUS, !on );
731 if (oldFont) SelectObject( hdc, oldFont );
732 ReleaseDC( descr->self, hdc );
733}
734
735
736/***********************************************************************
737 * LISTBOX_InitStorage
738 */
740{
742
743 nb_items += LB_ARRAY_GRANULARITY - 1;
744 nb_items -= (nb_items % LB_ARRAY_GRANULARITY);
745 if (descr->items) {
746 nb_items += HeapSize( GetProcessHeap(), 0, descr->items ) / sizeof(*item);
747 item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
748 nb_items * sizeof(LB_ITEMDATA));
749 }
750 else {
752 nb_items * sizeof(LB_ITEMDATA));
753 }
754
755 if (!item)
756 {
758 return LB_ERRSPACE;
759 }
760 descr->items = item;
761 return LB_OKAY;
762}
763
764
765/***********************************************************************
766 * LISTBOX_SetTabStops
767 */
769{
770 INT i;
771
772 if (!(descr->style & LBS_USETABSTOPS))
773 {
775 return FALSE;
776 }
777
778 HeapFree( GetProcessHeap(), 0, descr->tabs );
779 if (!(descr->nb_tabs = count))
780 {
781 descr->tabs = NULL;
782 return TRUE;
783 }
784 if (!(descr->tabs = HeapAlloc( GetProcessHeap(), 0,
785 descr->nb_tabs * sizeof(INT) )))
786 return FALSE;
787 memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT) );
788
789 /* convert into "dialog units"*/
790 for (i = 0; i < descr->nb_tabs; i++)
791 descr->tabs[i] = MulDiv(descr->tabs[i], descr->avg_char_width, 4);
792
793 return TRUE;
794}
795
796
797/***********************************************************************
798 * LISTBOX_GetText
799 */
801{
802 DWORD len;
803
804 if ((index < 0) || (index >= descr->nb_items))
805 {
807 return LB_ERR;
808 }
809 if (HAS_STRINGS(descr))
810 {
811 if (!buffer)
812 {
813 len = strlenW(descr->items[index].str);
814 if( unicode )
815 return len;
816 return WideCharToMultiByte( CP_ACP, 0, descr->items[index].str, len,
817 NULL, 0, NULL, NULL );
818 }
819
820 TRACE("index %d (0x%04x) %s\n", index, index, debugstr_w(descr->items[index].str));
821
822 _SEH2_TRY /* hide a Delphi bug that passes a read-only buffer */
823 {
824 if(unicode)
825 {
826 strcpyW( buffer, descr->items[index].str );
827 len = strlenW(buffer);
828 }
829 else
830 {
831 len = WideCharToMultiByte(CP_ACP, 0, descr->items[index].str, -1,
832 (LPSTR)buffer, 0x7FFFFFFF, NULL, NULL) - 1;
833 }
834 }
836 {
837 ERR( "got an invalid buffer (Delphi bug?)\n" );
839 len = LB_ERR;
840 }
842 } else {
843 if (buffer)
844 *((LPDWORD)buffer)=*(LPDWORD)(&descr->items[index].data);
845 len = sizeof(DWORD);
846 }
847 return len;
848}
849
851{
853 if (ret == CSTR_LESS_THAN)
854 return -1;
855 if (ret == CSTR_EQUAL)
856 return 0;
857 if (ret == CSTR_GREATER_THAN)
858 return 1;
859 return -1;
860}
861
862/***********************************************************************
863 * LISTBOX_FindStringPos
864 *
865 * Find the nearest string located before a given string in sort order.
866 * If 'exact' is TRUE, return an error if we don't get an exact match.
867 */
869{
870 INT index, min, max, res;
871
872 if (!(descr->style & LBS_SORT)) return -1; /* Add it at the end */
873 min = 0;
874 max = descr->nb_items;
875 while (min != max)
876 {
877 index = (min + max) / 2;
878 if (HAS_STRINGS(descr))
879 res = LISTBOX_lstrcmpiW( descr->locale, str, descr->items[index].str);
880 else
881 {
883 UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
884
885 cis.CtlType = ODT_LISTBOX;
886 cis.CtlID = id;
887 cis.hwndItem = descr->self;
888 /* note that some application (MetaStock) expects the second item
889 * to be in the listbox */
890 cis.itemID1 = -1;
891 cis.itemData1 = (ULONG_PTR)str;
892 cis.itemID2 = index;
893 cis.itemData2 = descr->items[index].data;
894 cis.dwLocaleId = descr->locale;
895 res = SendMessageW( descr->owner, WM_COMPAREITEM, id, (LPARAM)&cis );
896 }
897 if (!res) return index;
898 if (res < 0) max = index;
899 else min = index + 1;
900 }
901 return exact ? -1 : max;
902}
903
904
905/***********************************************************************
906 * LISTBOX_FindFileStrPos
907 *
908 * Find the nearest string located before a given string in directory
909 * sort order (i.e. first files, then directories, then drives).
910 */
912{
913 INT min, max, res;
914
915 if (!HAS_STRINGS(descr))
917 min = 0;
918 max = descr->nb_items;
919 while (min != max)
920 {
921 INT index = (min + max) / 2;
922 LPCWSTR p = descr->items[index].str;
923 if (*p == '[') /* drive or directory */
924 {
925 if (*str != '[') res = -1;
926 else if (p[1] == '-') /* drive */
927 {
928 if (str[1] == '-') res = str[2] - p[2];
929 else res = -1;
930 }
931 else /* directory */
932 {
933 if (str[1] == '-') res = 1;
934 else res = LISTBOX_lstrcmpiW( descr->locale, str, p );
935 }
936 }
937 else /* filename */
938 {
939 if (*str == '[') res = 1;
940 else res = LISTBOX_lstrcmpiW( descr->locale, str, p );
941 }
942 if (!res) return index;
943 if (res < 0) max = index;
944 else min = index + 1;
945 }
946 return max;
947}
948
949
950/***********************************************************************
951 * LISTBOX_FindString
952 *
953 * Find the item beginning with a given string.
954 */
956{
957 INT i;
959
960 if (start >= descr->nb_items) start = -1;
961 item = descr->items + start + 1;
962 if (HAS_STRINGS(descr))
963 {
964 if (!str || ! str[0] ) return LB_ERR;
965 if (exact)
966 {
967 for (i = start + 1; i < descr->nb_items; i++, item++)
968 if (!LISTBOX_lstrcmpiW( descr->locale, str, item->str )) return i;
969 for (i = 0, item = descr->items; i <= start; i++, item++)
970 if (!LISTBOX_lstrcmpiW( descr->locale, str, item->str )) return i;
971 }
972 else
973 {
974 /* Special case for drives and directories: ignore prefix */
975#define CHECK_DRIVE(item) \
976 if ((item)->str[0] == '[') \
977 { \
978 if (!strncmpiW( str, (item)->str+1, len )) return i; \
979 if (((item)->str[1] == '-') && !strncmpiW(str, (item)->str+2, len)) \
980 return i; \
981 }
982
983 INT len = strlenW(str);
984 for (i = start + 1; i < descr->nb_items; i++, item++)
985 {
986 if (!strncmpiW( str, item->str, len )) return i;
988 }
989 for (i = 0, item = descr->items; i <= start; i++, item++)
990 {
991 if (!strncmpiW( str, item->str, len )) return i;
993 }
994#undef CHECK_DRIVE
995 }
996 }
997 else
998 {
999 if (exact && (descr->style & LBS_SORT))
1000 /* If sorted, use a WM_COMPAREITEM binary search */
1001 return LISTBOX_FindStringPos( descr, str, TRUE );
1002
1003 /* Otherwise use a linear search */
1004 for (i = start + 1; i < descr->nb_items; i++, item++)
1005 if (item->data == (ULONG_PTR)str) return i;
1006 for (i = 0, item = descr->items; i <= start; i++, item++)
1007 if (item->data == (ULONG_PTR)str) return i;
1008 }
1009 return LB_ERR;
1010}
1011
1012
1013/***********************************************************************
1014 * LISTBOX_GetSelCount
1015 */
1017{
1018 INT i, count;
1019 const LB_ITEMDATA *item = descr->items;
1020
1021 if (!(descr->style & LBS_MULTIPLESEL) ||
1022 (descr->style & LBS_NOSEL))
1023 return LB_ERR;
1024 for (i = count = 0; i < descr->nb_items; i++, item++)
1025 if (item->selected) count++;
1026 return count;
1027}
1028
1029
1030/***********************************************************************
1031 * LISTBOX_GetSelItems
1032 */
1034{
1035 INT i, count;
1036 const LB_ITEMDATA *item = descr->items;
1037
1038 if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
1039 for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
1040 if (item->selected) array[count++] = i;
1041 return count;
1042}
1043
1044
1045/***********************************************************************
1046 * LISTBOX_Paint
1047 */
1049{
1050 INT i, col_pos = descr->page_size - 1;
1051 RECT rect;
1052 RECT focusRect = {-1, -1, -1, -1};
1053 HFONT oldFont = 0;
1054 HBRUSH hbrush, oldBrush = 0;
1055
1056 if (descr->style & LBS_NOREDRAW) return 0;
1057
1058 SetRect( &rect, 0, 0, descr->width, descr->height );
1059 if (descr->style & LBS_MULTICOLUMN)
1060 rect.right = rect.left + descr->column_width;
1061 else if (descr->horz_pos)
1062 {
1063 SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
1064 rect.right += descr->horz_pos;
1065 }
1066
1067 if (descr->font) oldFont = SelectObject( hdc, descr->font );
1068#ifdef __REACTOS__
1070#else
1071 hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
1072 (WPARAM)hdc, (LPARAM)descr->self );
1073#endif
1074 if (hbrush) oldBrush = SelectObject( hdc, hbrush );
1076
1077 if (!descr->nb_items && (descr->focus_item != -1) && descr->caret_on &&
1078 (descr->in_focus))
1079 {
1080 /* Special case for empty listbox: paint focus rect */
1081 rect.bottom = rect.top + descr->item_height;
1083 &rect, NULL, 0, NULL );
1084 LISTBOX_PaintItem( descr, hdc, &rect, descr->focus_item, ODA_FOCUS, FALSE );
1085 rect.top = rect.bottom;
1086 }
1087
1088 /* Paint all the item, regarding the selection
1089 Focus state will be painted after */
1090
1091 for (i = descr->top_item; i < descr->nb_items; i++)
1092 {
1093 if (!(descr->style & LBS_OWNERDRAWVARIABLE))
1094 rect.bottom = rect.top + descr->item_height;
1095 else
1096 rect.bottom = rect.top + descr->items[i].height;
1097
1098 /* keep the focus rect, to paint the focus item after */
1099 if (i == descr->focus_item)
1100 focusRect = rect;
1101#ifdef __REACTOS__
1102 rect.bottom = min(rect.bottom, descr->height);
1103#endif
1105 rect.top = rect.bottom;
1106
1107 if ((descr->style & LBS_MULTICOLUMN) && !col_pos)
1108 {
1109 if (!IS_OWNERDRAW(descr))
1110 {
1111 /* Clear the bottom of the column */
1112 if (rect.top < descr->height)
1113 {
1114 rect.bottom = descr->height;
1116 &rect, NULL, 0, NULL );
1117 }
1118 }
1119
1120 /* Go to the next column */
1121 rect.left += descr->column_width;
1122 rect.right += descr->column_width;
1123 rect.top = 0;
1124 col_pos = descr->page_size - 1;
1125 }
1126 else
1127 {
1128 col_pos--;
1129 if (rect.top >= descr->height) break;
1130 }
1131 }
1132
1133 /* Paint the focus item now */
1134 if (focusRect.top != focusRect.bottom &&
1135 descr->caret_on && descr->in_focus)
1136 LISTBOX_PaintItem( descr, hdc, &focusRect, descr->focus_item, ODA_FOCUS, FALSE );
1137
1138 if (!IS_OWNERDRAW(descr))
1139 {
1140 /* Clear the remainder of the client area */
1141 if (rect.top < descr->height)
1142 {
1143 rect.bottom = descr->height;
1144#ifdef __REACTOS__
1145 HBRUSH br = GetCurrentObject(hdc, OBJ_BRUSH);
1146 FillRect(hdc, &rect, br);
1147#else
1149 &rect, NULL, 0, NULL );
1150#endif
1151 }
1152 if (rect.right < descr->width)
1153 {
1154 rect.left = rect.right;
1155 rect.right = descr->width;
1156 rect.top = 0;
1157 rect.bottom = descr->height;
1158#ifdef __REACTOS__
1159 HBRUSH br = GetCurrentObject(hdc, OBJ_BRUSH);
1160 FillRect(hdc, &rect, br);
1161#else
1163 &rect, NULL, 0, NULL );
1164#endif
1165 }
1166 }
1167 if (oldFont) SelectObject( hdc, oldFont );
1168 if (oldBrush) SelectObject( hdc, oldBrush );
1169 return 0;
1170}
1171
1172
1173/***********************************************************************
1174 * LISTBOX_InvalidateItems
1175 *
1176 * Invalidate all items from a given item. If the specified item is not
1177 * visible, nothing happens.
1178 */
1180{
1181 RECT rect;
1182
1183 if (LISTBOX_GetItemRect( descr, index, &rect ) == 1)
1184 {
1185 if (descr->style & LBS_NOREDRAW)
1186 {
1187 descr->style |= LBS_DISPLAYCHANGED;
1188 return;
1189 }
1190 rect.bottom = descr->height;
1191 InvalidateRect( descr->self, &rect, TRUE );
1192 if (descr->style & LBS_MULTICOLUMN)
1193 {
1194 /* Repaint the other columns */
1195 rect.left = rect.right;
1196 rect.right = descr->width;
1197 rect.top = 0;
1198 InvalidateRect( descr->self, &rect, TRUE );
1199 }
1200 }
1201}
1202
1204{
1205 RECT rect;
1206
1207 if (LISTBOX_GetItemRect( descr, index, &rect ) == 1)
1208 InvalidateRect( descr->self, &rect, TRUE );
1209}
1210
1211/***********************************************************************
1212 * LISTBOX_GetItemHeight
1213 */
1215{
1216 if (descr->style & LBS_OWNERDRAWVARIABLE && descr->nb_items > 0)
1217 {
1218 if ((index < 0) || (index >= descr->nb_items))
1219 {
1221 return LB_ERR;
1222 }
1223 return descr->items[index].height;
1224 }
1225 else return descr->item_height;
1226}
1227
1228
1229/***********************************************************************
1230 * LISTBOX_SetItemHeight
1231 */
1233{
1234 if (height > MAXBYTE)
1235 return -1;
1236
1237 if (!height) height = 1;
1238
1239 if (descr->style & LBS_OWNERDRAWVARIABLE)
1240 {
1241 if ((index < 0) || (index >= descr->nb_items))
1242 {
1244 return LB_ERR;
1245 }
1246 TRACE("[%p]: item %d height = %d\n", descr->self, index, height );
1247 descr->items[index].height = height;
1249 if (repaint)
1251 }
1252 else if (height != descr->item_height)
1253 {
1254 TRACE("[%p]: new height = %d\n", descr->self, height );
1255 descr->item_height = height;
1258 if (repaint)
1259 InvalidateRect( descr->self, 0, TRUE );
1260 }
1261 return LB_OKAY;
1262}
1263
1264
1265/***********************************************************************
1266 * LISTBOX_SetHorizontalPos
1267 */
1269{
1270 INT diff;
1271
1272 if (pos > descr->horz_extent - descr->width)
1273 pos = descr->horz_extent - descr->width;
1274 if (pos < 0) pos = 0;
1275 if (!(diff = descr->horz_pos - pos)) return;
1276 TRACE("[%p]: new horz pos = %d\n", descr->self, pos );
1277 descr->horz_pos = pos;
1279 if (abs(diff) < descr->width)
1280 {
1281 RECT rect;
1282 /* Invalidate the focused item so it will be repainted correctly */
1283 if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1)
1284 InvalidateRect( descr->self, &rect, TRUE );
1285 ScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL,
1287 }
1288 else
1289 InvalidateRect( descr->self, NULL, TRUE );
1290}
1291
1292
1293/***********************************************************************
1294 * LISTBOX_SetHorizontalExtent
1295 */
1297{
1298 if (descr->style & LBS_MULTICOLUMN)
1299 return LB_OKAY;
1300 if (extent == descr->horz_extent) return LB_OKAY;
1301 TRACE("[%p]: new horz extent = %d\n", descr->self, extent );
1302 descr->horz_extent = extent;
1303 if (descr->style & WS_HSCROLL) {
1305 info.cbSize = sizeof(info);
1306 info.nMin = 0;
1307 info.nMax = descr->horz_extent ? descr->horz_extent - 1 : 0;
1308 info.fMask = SIF_RANGE;
1309 if (descr->style & LBS_DISABLENOSCROLL)
1310 info.fMask |= SIF_DISABLENOSCROLL;
1311 SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
1312 }
1313 if (descr->horz_pos > extent - descr->width)
1315 return LB_OKAY;
1316}
1317
1318
1319/***********************************************************************
1320 * LISTBOX_SetColumnWidth
1321 */
1323{
1324 if (width == descr->column_width) return LB_OKAY;
1325 TRACE("[%p]: new column width = %d\n", descr->self, width );
1326 descr->column_width = width;
1328 return LB_OKAY;
1329}
1330
1331
1332/***********************************************************************
1333 * LISTBOX_SetFont
1334 *
1335 * Returns the item height.
1336 */
1338{
1339 HDC hdc;
1340 HFONT oldFont = 0;
1341 const char *alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
1342 SIZE sz;
1343
1344 descr->font = font;
1345
1346 if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE )))
1347 {
1348 ERR("unable to get DC.\n" );
1349 return 16;
1350 }
1351 if (font) oldFont = SelectObject( hdc, font );
1352 GetTextExtentPointA( hdc, alphabet, 52, &sz);
1353 if (oldFont) SelectObject( hdc, oldFont );
1354 ReleaseDC( descr->self, hdc );
1355
1356 descr->avg_char_width = (sz.cx / 26 + 1) / 2;
1357 if (!IS_OWNERDRAW(descr))
1359 return sz.cy;
1360}
1361
1362
1363/***********************************************************************
1364 * LISTBOX_MakeItemVisible
1365 *
1366 * Make sure that a given item is partially or fully visible.
1367 */
1369{
1370 INT top;
1371
1372 TRACE("current top item %d, index %d, fully %d\n", descr->top_item, index, fully);
1373
1374 if (index <= descr->top_item) top = index;
1375 else if (descr->style & LBS_MULTICOLUMN)
1376 {
1377 INT cols = descr->width;
1378 if (!fully) cols += descr->column_width - 1;
1379 if (cols >= descr->column_width) cols /= descr->column_width;
1380 else cols = 1;
1381 if (index < descr->top_item + (descr->page_size * cols)) return;
1382 top = index - descr->page_size * (cols - 1);
1383 }
1384 else if (descr->style & LBS_OWNERDRAWVARIABLE)
1385 {
1386 INT height = fully ? descr->items[index].height : 1;
1387 for (top = index; top > descr->top_item; top--)
1388 if ((height += descr->items[top-1].height) > descr->height) break;
1389 }
1390 else
1391 {
1392 if (index < descr->top_item + descr->page_size) return;
1393 if (!fully && (index == descr->top_item + descr->page_size) &&
1394 (descr->height > (descr->page_size * descr->item_height))) return;
1395 top = index - descr->page_size + 1;
1396 }
1398}
1399
1400/***********************************************************************
1401 * LISTBOX_SetCaretIndex
1402 *
1403 * NOTES
1404 * index must be between 0 and descr->nb_items-1, or LB_ERR is returned.
1405 *
1406 */
1408{
1409 INT oldfocus = descr->focus_item;
1410
1411 TRACE("old focus %d, index %d\n", oldfocus, index);
1412
1413 if (descr->style & LBS_NOSEL) return LB_ERR;
1414 if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
1415 if (index == oldfocus) return LB_OKAY;
1416
1418 descr->focus_item = index;
1419
1420 LISTBOX_MakeItemVisible( descr, index, fully_visible );
1422
1423 return LB_OKAY;
1424}
1425
1426
1427/***********************************************************************
1428 * LISTBOX_SelectItemRange
1429 *
1430 * Select a range of items. Should only be used on a MULTIPLESEL listbox.
1431 */
1433 INT last, BOOL on )
1434{
1435 INT i;
1436
1437 /* A few sanity checks */
1438
1439 if (descr->style & LBS_NOSEL) return LB_ERR;
1440 if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
1441
1442 if (!descr->nb_items) return LB_OKAY;
1443
1444 if (last == -1 || last >= descr->nb_items) last = descr->nb_items - 1;
1445 if (first < 0) first = 0;
1446 if (last < first) return LB_OKAY;
1447
1448 if (on) /* Turn selection on */
1449 {
1450 for (i = first; i <= last; i++)
1451 {
1452 if (descr->items[i].selected) continue;
1453 descr->items[i].selected = TRUE;
1455 }
1456 }
1457 else /* Turn selection off */
1458 {
1459 for (i = first; i <= last; i++)
1460 {
1461 if (!descr->items[i].selected) continue;
1462 descr->items[i].selected = FALSE;
1464 }
1465 }
1466 return LB_OKAY;
1467}
1468
1469/***********************************************************************
1470 * LISTBOX_SetSelection
1471 */
1473 BOOL on, BOOL send_notify )
1474{
1475 TRACE( "cur_sel=%d index=%d notify=%s\n",
1476 descr->selected_item, index, send_notify ? "YES" : "NO" );
1477
1478 if (descr->style & LBS_NOSEL)
1479 {
1480 descr->selected_item = index;
1481 return LB_ERR;
1482 }
1483 if ((index < -1) || (index >= descr->nb_items)) return LB_ERR;
1484 if (descr->style & LBS_MULTIPLESEL)
1485 {
1486 if (index == -1) /* Select all items */
1487 return LISTBOX_SelectItemRange( descr, 0, descr->nb_items, on );
1488 else /* Only one item */
1489 return LISTBOX_SelectItemRange( descr, index, index, on );
1490 }
1491 else
1492 {
1493 INT oldsel = descr->selected_item;
1494 if (index == oldsel) return LB_OKAY;
1495 if (oldsel != -1) descr->items[oldsel].selected = FALSE;
1496 if (index != -1) descr->items[index].selected = TRUE;
1497 if (oldsel != -1) LISTBOX_RepaintItem( descr, oldsel, ODA_SELECT );
1498 descr->selected_item = index;
1500 if (send_notify && descr->nb_items) SEND_NOTIFICATION( descr,
1501 (index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL );
1502 else
1503 if( descr->lphc ) /* set selection change flag for parent combo */
1504 descr->lphc->wState |= CBF_SELCHANGE;
1505 }
1506 return LB_OKAY;
1507}
1508
1509
1510/***********************************************************************
1511 * LISTBOX_MoveCaret
1512 *
1513 * Change the caret position and extend the selection to the new caret.
1514 */
1515static void LISTBOX_MoveCaret( LB_DESCR *descr, INT index, BOOL fully_visible )
1516{
1517 TRACE("old focus %d, index %d\n", descr->focus_item, index);
1518
1519 if ((index < 0) || (index >= descr->nb_items))
1520 return;
1521
1522 /* Important, repaint needs to be done in this order if
1523 you want to mimic Windows behavior:
1524 1. Remove the focus and paint the item
1525 2. Remove the selection and paint the item(s)
1526 3. Set the selection and repaint the item(s)
1527 4. Set the focus to 'index' and repaint the item */
1528
1529 /* 1. remove the focus and repaint the item */
1531
1532 /* 2. then turn off the previous selection */
1533 /* 3. repaint the new selected item */
1534 if (descr->style & LBS_EXTENDEDSEL)
1535 {
1536 if (descr->anchor_item != -1)
1537 {
1538 INT first = min( index, descr->anchor_item );
1539 INT last = max( index, descr->anchor_item );
1540 if (first > 0)
1544 }
1545 }
1546 else if (!(descr->style & LBS_MULTIPLESEL))
1547 {
1548 /* Set selection to new caret item */
1550 }
1551
1552 /* 4. repaint the new item with the focus */
1553 descr->focus_item = index;
1554 LISTBOX_MakeItemVisible( descr, index, fully_visible );
1556}
1557
1558
1559/***********************************************************************
1560 * LISTBOX_InsertItem
1561 */
1564{
1566 INT max_items;
1567 INT oldfocus = descr->focus_item;
1568
1569 if (index == -1) index = descr->nb_items;
1570 else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
1571 if (!descr->items) max_items = 0;
1572 else max_items = HeapSize( GetProcessHeap(), 0, descr->items ) / sizeof(*item);
1573 if (descr->nb_items == max_items)
1574 {
1575 /* We need to grow the array */
1576 max_items += LB_ARRAY_GRANULARITY;
1577 if (descr->items)
1578 item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
1579 max_items * sizeof(LB_ITEMDATA) );
1580 else
1582 max_items * sizeof(LB_ITEMDATA) );
1583 if (!item)
1584 {
1586 return LB_ERRSPACE;
1587 }
1588 descr->items = item;
1589 }
1590
1591 /* Insert the item structure */
1592
1593 item = &descr->items[index];
1594 if (index < descr->nb_items)
1595 RtlMoveMemory( item + 1, item,
1596 (descr->nb_items - index) * sizeof(LB_ITEMDATA) );
1597 item->str = str;
1598 item->data = data;
1599 item->height = 0;
1600 item->selected = FALSE;
1601 descr->nb_items++;
1602
1603 /* Get item height */
1604
1605 if (descr->style & LBS_OWNERDRAWVARIABLE)
1606 {
1608 UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
1609
1610 mis.CtlType = ODT_LISTBOX;
1611 mis.CtlID = id;
1612 mis.itemID = index;
1613 mis.itemData = descr->items[index].data;
1614 mis.itemHeight = descr->item_height;
1615 SendMessageW( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
1616 item->height = mis.itemHeight ? mis.itemHeight : 1;
1617 TRACE("[%p]: measure item %d (%s) = %d\n",
1618 descr->self, index, str ? debugstr_w(str) : "", item->height );
1619 }
1620
1621 /* Repaint the items */
1622
1625
1626 /* Move selection and focused item */
1627 /* If listbox was empty, set focus to the first item */
1628 if (descr->nb_items == 1)
1630 /* single select don't change selection index in win31 */
1631 else if ((ISWIN31) && !(IS_MULTISELECT(descr)))
1632 {
1633 descr->selected_item++;
1634 LISTBOX_SetSelection( descr, descr->selected_item-1, TRUE, FALSE );
1635 }
1636 else
1637 {
1638 if (index <= descr->selected_item)
1639 {
1640 descr->selected_item++;
1641 descr->focus_item = oldfocus; /* focus not changed */
1642 }
1643 }
1644 return LB_OKAY;
1645}
1646
1647
1648/***********************************************************************
1649 * LISTBOX_InsertString
1650 */
1652{
1653 LPWSTR new_str = NULL;
1654 ULONG_PTR data = 0;
1655 LRESULT ret;
1656
1657 if (HAS_STRINGS(descr))
1658 {
1659 static const WCHAR empty_stringW[] = { 0 };
1660 if (!str) str = empty_stringW;
1661 if (!(new_str = HeapAlloc( GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR) )))
1662 {
1664 return LB_ERRSPACE;
1665 }
1666 strcpyW(new_str, str);
1667 }
1668 else data = (ULONG_PTR)str;
1669
1670 if (index == -1) index = descr->nb_items;
1671 if ((ret = LISTBOX_InsertItem( descr, index, new_str, data )) != 0)
1672 {
1673 HeapFree( GetProcessHeap(), 0, new_str );
1674 return ret;
1675 }
1676
1677 TRACE("[%p]: added item %d %s\n",
1678 descr->self, index, HAS_STRINGS(descr) ? debugstr_w(new_str) : "" );
1679 return index;
1680}
1681
1682
1683/***********************************************************************
1684 * LISTBOX_DeleteItem
1685 *
1686 * Delete the content of an item. 'index' must be a valid index.
1687 */
1689{
1690 /* save the item data before it gets freed by LB_RESETCONTENT */
1691 ULONG_PTR item_data = descr->items[index].data;
1692 LPWSTR item_str = descr->items[index].str;
1693
1694 if (!descr->nb_items)
1695 SendMessageW( descr->self, LB_RESETCONTENT, 0, 0 );
1696
1697 /* Note: Win 3.1 only sends DELETEITEM on owner-draw items,
1698 * while Win95 sends it for all items with user data.
1699 * It's probably better to send it too often than not
1700 * often enough, so this is what we do here.
1701 */
1702 if (IS_OWNERDRAW(descr) || item_data)
1703 {
1704 DELETEITEMSTRUCT dis;
1705 UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
1706
1707 dis.CtlType = ODT_LISTBOX;
1708 dis.CtlID = id;
1709 dis.itemID = index;
1710 dis.hwndItem = descr->self;
1711 dis.itemData = item_data;
1712 SendMessageW( descr->owner, WM_DELETEITEM, id, (LPARAM)&dis );
1713 }
1714 if (HAS_STRINGS(descr))
1715 HeapFree( GetProcessHeap(), 0, item_str );
1716}
1717
1718
1719/***********************************************************************
1720 * LISTBOX_RemoveItem
1721 *
1722 * Remove an item from the listbox and delete its content.
1723 */
1725{
1727 INT max_items;
1728
1729 if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
1730
1731 /* We need to invalidate the original rect instead of the updated one. */
1733
1734 descr->nb_items--;
1736
1737 if (!descr->nb_items) return LB_OKAY;
1738
1739 /* Remove the item */
1740
1741 item = &descr->items[index];
1742 if (index < descr->nb_items)
1743 RtlMoveMemory( item, item + 1,
1744 (descr->nb_items - index) * sizeof(LB_ITEMDATA) );
1745 if (descr->anchor_item == descr->nb_items) descr->anchor_item--;
1746
1747 /* Shrink the item array if possible */
1748
1749 max_items = HeapSize( GetProcessHeap(), 0, descr->items ) / sizeof(LB_ITEMDATA);
1750 if (descr->nb_items < max_items - 2*LB_ARRAY_GRANULARITY)
1751 {
1752 max_items -= LB_ARRAY_GRANULARITY;
1753 item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
1754 max_items * sizeof(LB_ITEMDATA) );
1755 if (item) descr->items = item;
1756 }
1757 /* Repaint the items */
1758
1760 /* if we removed the scrollbar, reset the top of the list
1761 (correct for owner-drawn ???) */
1762 if (descr->nb_items == descr->page_size)
1764
1765 /* Move selection and focused item */
1766 if (!IS_MULTISELECT(descr))
1767 {
1768 if (index == descr->selected_item)
1769 descr->selected_item = -1;
1770 else if (index < descr->selected_item)
1771 {
1772 descr->selected_item--;
1773 if (ISWIN31) /* win 31 do not change the selected item number */
1774 LISTBOX_SetSelection( descr, descr->selected_item + 1, TRUE, FALSE);
1775 }
1776 }
1777
1778 if (descr->focus_item >= descr->nb_items)
1779 {
1780 descr->focus_item = descr->nb_items - 1;
1781 if (descr->focus_item < 0) descr->focus_item = 0;
1782 }
1783 return LB_OKAY;
1784}
1785
1786
1787/***********************************************************************
1788 * LISTBOX_ResetContent
1789 */
1791{
1792 INT i;
1793
1794 for(i = descr->nb_items - 1; i>=0; i--) LISTBOX_DeleteItem( descr, i);
1795 HeapFree( GetProcessHeap(), 0, descr->items );
1796 descr->nb_items = 0;
1797 descr->top_item = 0;
1798 descr->selected_item = -1;
1799 descr->focus_item = 0;
1800 descr->anchor_item = -1;
1801 descr->items = NULL;
1802}
1803
1804
1805/***********************************************************************
1806 * LISTBOX_SetCount
1807 */
1809{
1810 LRESULT ret;
1811
1812 if (HAS_STRINGS(descr))
1813 {
1815 return LB_ERR;
1816 }
1817
1818 /* FIXME: this is far from optimal... */
1819 if (count > descr->nb_items)
1820 {
1821 while (count > descr->nb_items)
1822 if ((ret = LISTBOX_InsertString( descr, -1, 0 )) < 0)
1823 return ret;
1824 }
1825 else if (count < descr->nb_items)
1826 {
1827 while (count < descr->nb_items)
1828 if ((ret = LISTBOX_RemoveItem( descr, (descr->nb_items - 1) )) < 0)
1829 return ret;
1830 }
1831
1832 InvalidateRect( descr->self, NULL, TRUE );
1833 return LB_OKAY;
1834}
1835
1836
1837/***********************************************************************
1838 * LISTBOX_Directory
1839 */
1841 LPCWSTR filespec, BOOL long_names )
1842{
1843 HANDLE handle;
1846 int pos;
1847 LRESULT maxinsert = LB_ERR;
1848
1849 /* don't scan directory if we just want drives exclusively */
1850 if (attrib != (DDL_DRIVES | DDL_EXCLUSIVE)) {
1851 /* scan directory */
1852 if ((handle = FindFirstFileW(filespec, &entry)) == INVALID_HANDLE_VALUE)
1853 {
1854 int le = GetLastError();
1855 if ((le != ERROR_NO_MORE_FILES) && (le != ERROR_FILE_NOT_FOUND)) return LB_ERR;
1856 }
1857 else
1858 {
1859 do
1860 {
1861 WCHAR buffer[270];
1862 if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1863 {
1864 static const WCHAR bracketW[] = { ']',0 };
1865 static const WCHAR dotW[] = { '.',0 };
1866 if (!(attrib & DDL_DIRECTORY) ||
1867 !strcmpW( entry.cFileName, dotW )) continue;
1868 buffer[0] = '[';
1869 if (!long_names && entry.cAlternateFileName[0])
1870 strcpyW( buffer + 1, entry.cAlternateFileName );
1871 else
1872 strcpyW( buffer + 1, entry.cFileName );
1873 strcatW(buffer, bracketW);
1874 }
1875 else /* not a directory */
1876 {
1877#define ATTRIBS (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | \
1878 FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE)
1879
1880 if ((attrib & DDL_EXCLUSIVE) &&
1881 ((attrib & ATTRIBS) != (entry.dwFileAttributes & ATTRIBS)))
1882 continue;
1883#undef ATTRIBS
1884 if (!long_names && entry.cAlternateFileName[0])
1885 strcpyW( buffer, entry.cAlternateFileName );
1886 else
1887 strcpyW( buffer, entry.cFileName );
1888 }
1889 if (!long_names) CharLowerW( buffer );
1891 if ((ret = LISTBOX_InsertString( descr, pos, buffer )) < 0)
1892 break;
1893 if (ret <= maxinsert) maxinsert++; else maxinsert = ret;
1894 } while (FindNextFileW( handle, &entry ));
1895 FindClose( handle );
1896 }
1897 }
1898 if (ret >= 0)
1899 {
1900 ret = maxinsert;
1901
1902 /* scan drives */
1903 if (attrib & DDL_DRIVES)
1904 {
1905 WCHAR buffer[] = {'[','-','a','-',']',0};
1906 WCHAR root[] = {'A',':','\\',0};
1907 int drive;
1908 for (drive = 0; drive < 26; drive++, buffer[2]++, root[0]++)
1909 {
1910 if (GetDriveTypeW(root) <= DRIVE_NO_ROOT_DIR) continue;
1911 if ((ret = LISTBOX_InsertString( descr, -1, buffer )) < 0)
1912 break;
1913 }
1914 }
1915 }
1916 return ret;
1917}
1918
1919
1920/***********************************************************************
1921 * LISTBOX_HandleVScroll
1922 */
1924{
1926
1927 if (descr->style & LBS_MULTICOLUMN) return 0;
1928 switch(scrollReq)
1929 {
1930 case SB_LINEUP:
1931 LISTBOX_SetTopItem( descr, descr->top_item - 1, TRUE );
1932 break;
1933 case SB_LINEDOWN:
1934 LISTBOX_SetTopItem( descr, descr->top_item + 1, TRUE );
1935 break;
1936 case SB_PAGEUP:
1937 LISTBOX_SetTopItem( descr, descr->top_item -
1939 break;
1940 case SB_PAGEDOWN:
1941 LISTBOX_SetTopItem( descr, descr->top_item +
1943 break;
1944 case SB_THUMBPOSITION:
1946 break;
1947 case SB_THUMBTRACK:
1948 info.cbSize = sizeof(info);
1949 info.fMask = SIF_TRACKPOS;
1950 GetScrollInfo( descr->self, SB_VERT, &info );
1951 LISTBOX_SetTopItem( descr, info.nTrackPos, TRUE );
1952 break;
1953 case SB_TOP:
1955 break;
1956 case SB_BOTTOM:
1957 LISTBOX_SetTopItem( descr, descr->nb_items, TRUE );
1958 break;
1959 }
1960 return 0;
1961}
1962
1963
1964/***********************************************************************
1965 * LISTBOX_HandleHScroll
1966 */
1968{
1970 INT page;
1971
1972 if (descr->style & LBS_MULTICOLUMN)
1973 {
1974 switch(scrollReq)
1975 {
1976 case SB_LINELEFT:
1977 LISTBOX_SetTopItem( descr, descr->top_item-descr->page_size,
1978 TRUE );
1979 break;
1980 case SB_LINERIGHT:
1981 LISTBOX_SetTopItem( descr, descr->top_item+descr->page_size,
1982 TRUE );
1983 break;
1984 case SB_PAGELEFT:
1985 page = descr->width / descr->column_width;
1986 if (page < 1) page = 1;
1988 descr->top_item - page * descr->page_size, TRUE );
1989 break;
1990 case SB_PAGERIGHT:
1991 page = descr->width / descr->column_width;
1992 if (page < 1) page = 1;
1994 descr->top_item + page * descr->page_size, TRUE );
1995 break;
1996 case SB_THUMBPOSITION:
1997 LISTBOX_SetTopItem( descr, pos*descr->page_size, TRUE );
1998 break;
1999 case SB_THUMBTRACK:
2000 info.cbSize = sizeof(info);
2001 info.fMask = SIF_TRACKPOS;
2002#ifdef __REACTOS__
2003 GetScrollInfo( descr->self, SB_HORZ, &info );
2004#else
2005 GetScrollInfo( descr->self, SB_VERT, &info );
2006#endif
2007 LISTBOX_SetTopItem( descr, info.nTrackPos*descr->page_size,
2008 TRUE );
2009 break;
2010 case SB_LEFT:
2012 break;
2013 case SB_RIGHT:
2014 LISTBOX_SetTopItem( descr, descr->nb_items, TRUE );
2015 break;
2016 }
2017 }
2018 else if (descr->horz_extent)
2019 {
2020 switch(scrollReq)
2021 {
2022 case SB_LINELEFT:
2023 LISTBOX_SetHorizontalPos( descr, descr->horz_pos - 1 );
2024 break;
2025 case SB_LINERIGHT:
2026 LISTBOX_SetHorizontalPos( descr, descr->horz_pos + 1 );
2027 break;
2028 case SB_PAGELEFT:
2030 descr->horz_pos - descr->width );
2031 break;
2032 case SB_PAGERIGHT:
2034 descr->horz_pos + descr->width );
2035 break;
2036 case SB_THUMBPOSITION:
2038 break;
2039 case SB_THUMBTRACK:
2040 info.cbSize = sizeof(info);
2041 info.fMask = SIF_TRACKPOS;
2042 GetScrollInfo( descr->self, SB_HORZ, &info );
2043 LISTBOX_SetHorizontalPos( descr, info.nTrackPos );
2044 break;
2045 case SB_LEFT:
2047 break;
2048 case SB_RIGHT:
2050 descr->horz_extent - descr->width );
2051 break;
2052 }
2053 }
2054 return 0;
2055}
2056
2058{
2059 UINT pulScrollLines = 3;
2060
2061 SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
2062
2063 /* if scrolling changes direction, ignore left overs */
2064 if ((delta < 0 && descr->wheel_remain < 0) ||
2065 (delta > 0 && descr->wheel_remain > 0))
2066 descr->wheel_remain += delta;
2067 else
2068 descr->wheel_remain = delta;
2069
2070 if (descr->wheel_remain && pulScrollLines)
2071 {
2072 int cLineScroll;
2073 pulScrollLines = min((UINT) descr->page_size, pulScrollLines);
2074 cLineScroll = pulScrollLines * (float)descr->wheel_remain / WHEEL_DELTA;
2075 descr->wheel_remain -= WHEEL_DELTA * cLineScroll / (int)pulScrollLines;
2076#ifdef __REACTOS__
2077 if (cLineScroll < 0)
2078 cLineScroll -= descr->page_size;
2079#endif
2080 LISTBOX_SetTopItem( descr, descr->top_item - cLineScroll, TRUE );
2081 }
2082 return 0;
2083}
2084
2085/***********************************************************************
2086 * LISTBOX_HandleLButtonDown
2087 */
2089{
2091
2092 TRACE("[%p]: lbuttondown %d,%d item %d, focus item %d\n",
2093 descr->self, x, y, index, descr->focus_item);
2094
2095 if (!descr->caret_on && (descr->in_focus)) return 0;
2096
2097 if (!descr->in_focus)
2098 {
2099 if( !descr->lphc ) SetFocus( descr->self );
2100 else SetFocus( (descr->lphc->hWndEdit) ? descr->lphc->hWndEdit : descr->lphc->self );
2101 }
2102
2103 if (index == -1) return 0;
2104
2105 if (!descr->lphc)
2106 {
2107 if (descr->style & LBS_NOTIFY )
2109 MAKELPARAM( x, y ) );
2110 }
2111
2112 descr->captured = TRUE;
2113 SetCapture( descr->self );
2114
2115 if (descr->style & (LBS_EXTENDEDSEL | LBS_MULTIPLESEL))
2116 {
2117 /* we should perhaps make sure that all items are deselected
2118 FIXME: needed for !LBS_EXTENDEDSEL, too ?
2119 if (!(keys & (MK_SHIFT|MK_CONTROL)))
2120 LISTBOX_SetSelection( descr, -1, FALSE, FALSE);
2121 */
2122
2123 if (!(keys & MK_SHIFT)) descr->anchor_item = index;
2124 if (keys & MK_CONTROL)
2125 {
2128 !descr->items[index].selected,
2129 (descr->style & LBS_NOTIFY) != 0);
2130 }
2131 else
2132 {
2134
2135 if (descr->style & LBS_EXTENDEDSEL)
2136 {
2138 descr->items[index].selected,
2139 (descr->style & LBS_NOTIFY) != 0 );
2140 }
2141 else
2142 {
2144 !descr->items[index].selected,
2145 (descr->style & LBS_NOTIFY) != 0 );
2146 }
2147 }
2148 }
2149 else
2150 {
2151 descr->anchor_item = index;
2154 TRUE, (descr->style & LBS_NOTIFY) != 0 );
2155 }
2156
2157 if (!descr->lphc)
2158 { // See rev 40864 use Ptr for 64 bit.
2160 {
2161 POINT pt;
2162
2163 pt.x = x;
2164 pt.y = y;
2165
2166 if (DragDetect( descr->self, pt ))
2167 SendMessageW( descr->owner, WM_BEGINDRAG, 0, 0 );
2168 }
2169 }
2170 return 0;
2171}
2172
2173
2174/*************************************************************************
2175 * LISTBOX_HandleLButtonDownCombo [Internal]
2176 *
2177 * Process LButtonDown message for the ComboListBox
2178 *
2179 * PARAMS
2180 * pWnd [I] The windows internal structure
2181 * pDescr [I] The ListBox internal structure
2182 * keys [I] Key Flag (WM_LBUTTONDOWN doc for more info)
2183 * x [I] X Mouse Coordinate
2184 * y [I] Y Mouse Coordinate
2185 *
2186 * RETURNS
2187 * 0 since we are processing the WM_LBUTTONDOWN Message
2188 *
2189 * NOTES
2190 * This function is only to be used when a ListBox is a ComboListBox
2191 */
2192
2194{
2195 RECT clientRect, screenRect;
2196 POINT mousePos;
2197
2198 mousePos.x = x;
2199 mousePos.y = y;
2200
2201 GetClientRect(descr->self, &clientRect);
2202
2203 if(PtInRect(&clientRect, mousePos))
2204 {
2205 /* MousePos is in client, resume normal processing */
2206 if (msg == WM_LBUTTONDOWN)
2207 {
2208 descr->lphc->droppedIndex = descr->nb_items ? descr->selected_item : -1;
2210 }
2211 else if (descr->style & LBS_NOTIFY)
2213 }
2214 else
2215 {
2216 POINT screenMousePos;
2217 HWND hWndOldCapture;
2218
2219 /* Check the Non-Client Area */
2220 screenMousePos = mousePos;
2221 hWndOldCapture = GetCapture();
2223 GetWindowRect(descr->self, &screenRect);
2224 ClientToScreen(descr->self, &screenMousePos);
2225
2226 if(!PtInRect(&screenRect, screenMousePos))
2227 {
2228 LISTBOX_SetCaretIndex( descr, descr->lphc->droppedIndex, FALSE );
2229 LISTBOX_SetSelection( descr, descr->lphc->droppedIndex, FALSE, FALSE );
2231 }
2232 else
2233 {
2234 /* Check to see the NC is a scrollbar */
2235 INT nHitTestType=0;
2237 /* Check Vertical scroll bar */
2238 if (style & WS_VSCROLL)
2239 {
2240 clientRect.right += GetSystemMetrics(SM_CXVSCROLL);
2241 if (PtInRect( &clientRect, mousePos ))
2242 nHitTestType = HTVSCROLL;
2243 }
2244 /* Check horizontal scroll bar */
2245 if (style & WS_HSCROLL)
2246 {
2247 clientRect.bottom += GetSystemMetrics(SM_CYHSCROLL);
2248 if (PtInRect( &clientRect, mousePos ))
2249 nHitTestType = HTHSCROLL;
2250 }
2251 /* Windows sends this message when a scrollbar is clicked
2252 */
2253
2254 if(nHitTestType != 0)
2255 {
2256 SendMessageW(descr->self, WM_NCLBUTTONDOWN, nHitTestType,
2257 MAKELONG(screenMousePos.x, screenMousePos.y));
2258 }
2259 /* Resume the Capture after scrolling is complete
2260 */
2261 if(hWndOldCapture != 0)
2262 SetCapture(hWndOldCapture);
2263 }
2264 }
2265 return 0;
2266}
2267
2268/***********************************************************************
2269 * LISTBOX_HandleLButtonUp
2270 */
2272{
2276 if (descr->captured)
2277 {
2278 descr->captured = FALSE;
2279 if (GetCapture() == descr->self) ReleaseCapture();
2280 if ((descr->style & LBS_NOTIFY) && descr->nb_items)
2282 }
2283 return 0;
2284}
2285
2286
2287/***********************************************************************
2288 * LISTBOX_HandleTimer
2289 *
2290 * Handle scrolling upon a timer event.
2291 * Return TRUE if scrolling should continue.
2292 */
2294{
2295 switch(dir)
2296 {
2297 case LB_TIMER_UP:
2298 if (descr->top_item) index = descr->top_item - 1;
2299 else index = 0;
2300 break;
2301 case LB_TIMER_LEFT:
2302 if (descr->top_item) index -= descr->page_size;
2303 break;
2304 case LB_TIMER_DOWN:
2306 if (index == descr->focus_item) index++;
2307 if (index >= descr->nb_items) index = descr->nb_items - 1;
2308 break;
2309 case LB_TIMER_RIGHT:
2310 if (index + descr->page_size < descr->nb_items)
2311 index += descr->page_size;
2312 break;
2313 case LB_TIMER_NONE:
2314 break;
2315 }
2316 if (index == descr->focus_item) return FALSE;
2318 return TRUE;
2319}
2320
2321
2322/***********************************************************************
2323 * LISTBOX_HandleSystemTimer
2324 *
2325 * WM_SYSTIMER handler.
2326 */
2328{
2329 if (!LISTBOX_HandleTimer( descr, descr->focus_item, LISTBOX_Timer ))
2330 {
2333 }
2334 return 0;
2335}
2336
2337
2338/***********************************************************************
2339 * LISTBOX_HandleMouseMove
2340 *
2341 * WM_MOUSEMOVE handler.
2342 */
2344 INT x, INT y )
2345{
2346 INT index;
2348
2349 if (!descr->captured) return;
2350
2351 if (descr->style & LBS_MULTICOLUMN)
2352 {
2353 if (y < 0) y = 0;
2354 else if (y >= descr->item_height * descr->page_size)
2355 y = descr->item_height * descr->page_size - 1;
2356
2357 if (x < 0)
2358 {
2360 x = 0;
2361 }
2362 else if (x >= descr->width)
2363 {
2365 x = descr->width - 1;
2366 }
2367 }
2368 else
2369 {
2370 if (y < 0) dir = LB_TIMER_UP; /* above */
2371 else if (y >= descr->height) dir = LB_TIMER_DOWN; /* below */
2372 }
2373
2375 if (index == -1) index = descr->focus_item;
2377
2378 /* Start/stop the system timer */
2379
2380 if (dir != LB_TIMER_NONE)
2382 else if (LISTBOX_Timer != LB_TIMER_NONE)
2385}
2386
2387
2388/***********************************************************************
2389 * LISTBOX_HandleKeyDown
2390 */
2392{
2393 INT caret = -1;
2394 BOOL bForceSelection = TRUE; /* select item pointed to by focus_item */
2395 if ((IS_MULTISELECT(descr)) || (descr->selected_item == descr->focus_item))
2396 bForceSelection = FALSE; /* only for single select list */
2397
2398 if (descr->style & LBS_WANTKEYBOARDINPUT)
2399 {
2400 caret = SendMessageW( descr->owner, WM_VKEYTOITEM,
2401 MAKEWPARAM(LOWORD(key), descr->focus_item),
2402 (LPARAM)descr->self );
2403 if (caret == -2) return 0;
2404 }
2405 if (caret == -1) switch(key)
2406 {
2407 case VK_LEFT:
2408 if (descr->style & LBS_MULTICOLUMN)
2409 {
2410 bForceSelection = FALSE;
2411 if (descr->focus_item >= descr->page_size)
2412 caret = descr->focus_item - descr->page_size;
2413 break;
2414 }
2415 /* fall through */
2416 case VK_UP:
2417 caret = descr->focus_item - 1;
2418 if (caret < 0) caret = 0;
2419 break;
2420 case VK_RIGHT:
2421 if (descr->style & LBS_MULTICOLUMN)
2422 {
2423 bForceSelection = FALSE;
2424 if (descr->focus_item + descr->page_size < descr->nb_items)
2425 caret = descr->focus_item + descr->page_size;
2426 break;
2427 }
2428 /* fall through */
2429 case VK_DOWN:
2430 caret = descr->focus_item + 1;
2431 if (caret >= descr->nb_items) caret = descr->nb_items - 1;
2432 break;
2433
2434 case VK_PRIOR:
2435 if (descr->style & LBS_MULTICOLUMN)
2436 {
2437 INT page = descr->width / descr->column_width;
2438 if (page < 1) page = 1;
2439 caret = descr->focus_item - (page * descr->page_size) + 1;
2440 }
2441 else caret = descr->focus_item-LISTBOX_GetCurrentPageSize(descr) + 1;
2442 if (caret < 0) caret = 0;
2443 break;
2444 case VK_NEXT:
2445 if (descr->style & LBS_MULTICOLUMN)
2446 {
2447 INT page = descr->width / descr->column_width;
2448 if (page < 1) page = 1;
2449 caret = descr->focus_item + (page * descr->page_size) - 1;
2450 }
2451 else caret = descr->focus_item + LISTBOX_GetCurrentPageSize(descr) - 1;
2452 if (caret >= descr->nb_items) caret = descr->nb_items - 1;
2453 break;
2454 case VK_HOME:
2455 caret = 0;
2456 break;
2457 case VK_END:
2458 caret = descr->nb_items - 1;
2459 break;
2460 case VK_SPACE:
2461 if (descr->style & LBS_EXTENDEDSEL) caret = descr->focus_item;
2462 else if (descr->style & LBS_MULTIPLESEL)
2463 {
2464 LISTBOX_SetSelection( descr, descr->focus_item,
2465 !descr->items[descr->focus_item].selected,
2466 (descr->style & LBS_NOTIFY) != 0 );
2467 }
2468 break;
2469 default:
2470 bForceSelection = FALSE;
2471 }
2472 if (bForceSelection) /* focused item is used instead of key */
2473 caret = descr->focus_item;
2474 if (caret >= 0)
2475 {
2476 if (((descr->style & LBS_EXTENDEDSEL) &&
2477 !(GetKeyState( VK_SHIFT ) & 0x8000)) ||
2479 descr->anchor_item = caret;
2480 LISTBOX_MoveCaret( descr, caret, TRUE );
2481
2482 if (descr->style & LBS_MULTIPLESEL)
2483 descr->selected_item = caret;
2484 else
2486 if (descr->style & LBS_NOTIFY)
2487 {
2488 if (descr->lphc && IsWindowVisible( descr->self ))
2489 {
2490 /* make sure that combo parent doesn't hide us */
2491 descr->lphc->wState |= CBF_NOROLLUP;
2492 }
2493 if (descr->nb_items) SEND_NOTIFICATION( descr, LBN_SELCHANGE );
2494 }
2495 }
2496 return 0;
2497}
2498
2499
2500/***********************************************************************
2501 * LISTBOX_HandleChar
2502 */
2504{
2505 INT caret = -1;
2506 WCHAR str[2];
2507
2508 str[0] = charW;
2509 str[1] = '\0';
2510
2511 if (descr->style & LBS_WANTKEYBOARDINPUT)
2512 {
2513 caret = SendMessageW( descr->owner, WM_CHARTOITEM,
2514 MAKEWPARAM(charW, descr->focus_item),
2515 (LPARAM)descr->self );
2516 if (caret == -2) return 0;
2517 }
2518 if (caret == -1)
2519 caret = LISTBOX_FindString( descr, descr->focus_item, str, FALSE);
2520 if (caret != -1)
2521 {
2522 if ((!IS_MULTISELECT(descr)) && descr->selected_item == -1)
2524 LISTBOX_MoveCaret( descr, caret, TRUE );
2525 if ((descr->style & LBS_NOTIFY) && descr->nb_items)
2527 }
2528 return 0;
2529}
2530
2531/* ReactOS Retrieve the UI state for the control */
2533{
2534 LONG prev_flags;
2535
2536 prev_flags = descr->UIState;
2537 descr->UIState = DefWindowProcW(descr->self, WM_QUERYUISTATE, 0, 0);
2538 return prev_flags != descr->UIState;
2539}
2540
2541
2542/***********************************************************************
2543 * LISTBOX_Create
2544 */
2546{
2547 LB_DESCR *descr;
2549 RECT rect;
2550
2551 if (!(descr = HeapAlloc( GetProcessHeap(), 0, sizeof(*descr) )))
2552 return FALSE;
2553
2554 GetClientRect( hwnd, &rect );
2555 descr->self = hwnd;
2556 descr->owner = GetParent( descr->self );
2557 descr->style = GetWindowLongPtrW( descr->self, GWL_STYLE );
2558 descr->width = rect.right - rect.left;
2559 descr->height = rect.bottom - rect.top;
2560 descr->items = NULL;
2561 descr->nb_items = 0;
2562 descr->top_item = 0;
2563 descr->selected_item = -1;
2564 descr->focus_item = 0;
2565 descr->anchor_item = -1;
2566 descr->item_height = 1;
2567 descr->page_size = 1;
2568 descr->column_width = 150;
2569 descr->horz_extent = 0;
2570 descr->horz_pos = 0;
2571 descr->nb_tabs = 0;
2572 descr->tabs = NULL;
2573 descr->wheel_remain = 0;
2574 descr->caret_on = !lphc;
2575 if (descr->style & LBS_NOSEL) descr->caret_on = FALSE;
2576 descr->in_focus = FALSE;
2577 descr->captured = FALSE;
2578 descr->font = 0;
2579 descr->locale = GetUserDefaultLCID();
2580 descr->lphc = lphc;
2581
2582 if( lphc )
2583 {
2584 TRACE("[%p]: resetting owner %p -> %p\n", descr->self, descr->owner, lphc->self );
2585 descr->owner = lphc->self;
2586 }
2587
2588 SetWindowLongPtrW( descr->self, 0, (LONG_PTR)descr );
2589
2590 LISTBOX_update_uistate(descr); // ReactOS
2591
2592/* if (wnd->dwExStyle & WS_EX_NOPARENTNOTIFY) descr->style &= ~LBS_NOTIFY;
2593 */
2594 if (descr->style & LBS_EXTENDEDSEL) descr->style |= LBS_MULTIPLESEL;
2595 if (descr->style & LBS_MULTICOLUMN) descr->style &= ~LBS_OWNERDRAWVARIABLE;
2596 if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT;
2597
2599 /* A no-data list box must also have the LBS_OWNERDRAWFIXED style, but must
2600 not have the LBS_SORT or LBS_HASSTRINGS style. */
2601 if ( descr->style & LBS_NODATA &&
2602 (!(descr->style & LBS_OWNERDRAWFIXED) || descr->style & (LBS_HASSTRINGS|LBS_SORT) ) )
2603 descr->style &= ~LBS_NODATA;
2605 descr->item_height = LISTBOX_SetFont( descr, 0 );
2606
2607 if (descr->style & LBS_OWNERDRAWFIXED)
2608 {
2609 if( descr->lphc && (descr->lphc->dwStyle & CBS_DROPDOWN))
2610 {
2611 /* WinWord gets VERY unhappy if we send WM_MEASUREITEM from here */
2612 descr->item_height = lphc->fixedOwnerDrawHeight;
2613 }
2614 else
2615 {
2616 UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
2617 mis.CtlType = ODT_LISTBOX;
2618 mis.CtlID = id;
2619 mis.itemID = -1;
2620 mis.itemWidth = 0;
2621 mis.itemData = 0;
2622 mis.itemHeight = descr->item_height;
2623 SendMessageW( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
2624 descr->item_height = mis.itemHeight ? mis.itemHeight : 1;
2625 }
2626 }
2627
2628 TRACE("owner: %p, style: %08x, width: %d, height: %d\n", descr->owner, descr->style, descr->width, descr->height);
2629 return TRUE;
2630}
2631
2632
2633/***********************************************************************
2634 * LISTBOX_Destroy
2635 */
2637{
2639 SetWindowLongPtrW( descr->self, 0, 0 );
2640 HeapFree( GetProcessHeap(), 0, descr );
2641 return TRUE;
2642}
2643
2644
2645/***********************************************************************
2646 * ListBoxWndProc_common
2647 */
2649 WPARAM wParam, LPARAM lParam, BOOL unicode )
2650{
2652 LPHEADCOMBO lphc = 0;
2653 LRESULT ret;
2654#ifdef __REACTOS__
2655 PWND pWnd;
2656
2657 pWnd = ValidateHwnd(hwnd);
2658 if (pWnd)
2659 {
2660 if (!pWnd->fnid)
2661 {
2662 NtUserSetWindowFNID(hwnd, FNID_LISTBOX); // Could be FNID_COMBOLBOX by class.
2663 }
2664 else
2665 {
2666 if (pWnd->fnid != FNID_LISTBOX)
2667 {
2668 ERR("Wrong window class for listbox! fnId 0x%x\n",pWnd->fnid);
2669 return 0;
2670 }
2671 }
2672 }
2673#endif
2674
2675 if (!descr)
2676 {
2677 if (!IsWindow(hwnd)) return 0;
2678
2679 if (msg == WM_CREATE)
2680 {
2682 if (lpcs->style & LBS_COMBOBOX) lphc = lpcs->lpCreateParams;
2683 if (!LISTBOX_Create( hwnd, lphc )) return -1;
2684 TRACE("creating hwnd %p descr %p\n", hwnd, (void *)GetWindowLongPtrW( hwnd, 0 ) );
2685 return 0;
2686 }
2687 /* Ignore all other messages before we get a WM_CREATE */
2688 return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
2690 }
2691 if (descr->style & LBS_COMBOBOX) lphc = descr->lphc;
2692
2693 TRACE("[%p]: msg %s wp %08lx lp %08lx\n",
2694 descr->self, SPY_GetMsgName(msg, descr->self), wParam, lParam );
2695
2696 switch(msg)
2697 {
2698 case LB_RESETCONTENT:
2701 InvalidateRect( descr->self, NULL, TRUE );
2702 return 0;
2703
2704 case LB_ADDSTRING:
2705#ifdef __REACTOS__
2706 case LB_ADDSTRING_LOWER:
2707 case LB_ADDSTRING_UPPER:
2708#endif
2709 {
2710 INT ret;
2711 LPWSTR textW;
2712 if(unicode || !HAS_STRINGS(descr))
2713 textW = (LPWSTR)lParam;
2714 else
2715 {
2717 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
2718 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
2719 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
2720 else
2721 return LB_ERRSPACE;
2722 }
2723#ifdef __REACTOS__
2724 /* in the unicode the version, the string is really overwritten
2725 during the converting case */
2726 if (msg == LB_ADDSTRING_LOWER)
2727 strlwrW(textW);
2728 else if (msg == LB_ADDSTRING_UPPER)
2729 struprW(textW);
2730#endif
2733 if (!unicode && HAS_STRINGS(descr))
2735 return ret;
2736 }
2737
2738 case LB_INSERTSTRING:
2739#ifdef __REACTOS__
2742#endif
2743 {
2744 INT ret;
2745 LPWSTR textW;
2746 if(unicode || !HAS_STRINGS(descr))
2747 textW = (LPWSTR)lParam;
2748 else
2749 {
2751 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
2752 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
2753 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
2754 else
2755 return LB_ERRSPACE;
2756 }
2757#ifdef __REACTOS__
2758 /* in the unicode the version, the string is really overwritten
2759 during the converting case */
2761 strlwrW(textW);
2762 else if (msg == LB_INSERTSTRING_UPPER)
2763 struprW(textW);
2764#endif
2766 if(!unicode && HAS_STRINGS(descr))
2768 return ret;
2769 }
2770
2771 case LB_ADDFILE:
2772 {
2773 INT ret;
2774 LPWSTR textW;
2775 if(unicode || !HAS_STRINGS(descr))
2776 textW = (LPWSTR)lParam;
2777 else
2778 {
2780 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
2781 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
2782 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
2783 else
2784 return LB_ERRSPACE;
2785 }
2788 if(!unicode && HAS_STRINGS(descr))
2790 return ret;
2791 }
2792
2793 case LB_DELETESTRING:
2795 return descr->nb_items;
2796 else
2797 {
2799 return LB_ERR;
2800 }
2801
2802 case LB_GETITEMDATA:
2803 if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
2804 {
2806 return LB_ERR;
2807 }
2808 return descr->items[wParam].data;
2809
2810 case LB_SETITEMDATA:
2811 if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
2812 {
2814 return LB_ERR;
2815 }
2816 descr->items[wParam].data = lParam;
2817 /* undocumented: returns TRUE, not LB_OKAY (0) */
2818 return TRUE;
2819
2820 case LB_GETCOUNT:
2821 return descr->nb_items;
2822
2823 case LB_GETTEXT:
2824 return LISTBOX_GetText( descr, wParam, (LPWSTR)lParam, unicode );
2825
2826 case LB_GETTEXTLEN:
2827 if ((INT)wParam >= descr->nb_items || (INT)wParam < 0)
2828 {
2830 return LB_ERR;
2831 }
2832 if (!HAS_STRINGS(descr)) return sizeof(DWORD);
2833 if (unicode) return strlenW( descr->items[wParam].str );
2834 return WideCharToMultiByte( CP_ACP, 0, descr->items[wParam].str,
2835 strlenW(descr->items[wParam].str), NULL, 0, NULL, NULL );
2836
2837 case LB_GETCURSEL:
2838 if (descr->nb_items == 0)
2839 return LB_ERR;
2840 if (!IS_MULTISELECT(descr))
2841 return descr->selected_item;
2842 if (descr->selected_item != -1)
2843 return descr->selected_item;
2844 return descr->focus_item;
2845 /* otherwise, if the user tries to move the selection with the */
2846 /* arrow keys, we will give the application something to choke on */
2847 case LB_GETTOPINDEX:
2848 return descr->top_item;
2849
2850 case LB_GETITEMHEIGHT:
2852
2853 case LB_SETITEMHEIGHT:
2855
2856 case LB_ITEMFROMPOINT:
2857 {
2858 POINT pt;
2859 RECT rect;
2860 int index;
2861 BOOL hit = TRUE;
2862
2863 /* The hiword of the return value is not a client area
2864 hittest as suggested by MSDN, but rather a hittest on
2865 the returned listbox item. */
2866
2867 if(descr->nb_items == 0)
2868 return 0x1ffff; /* win9x returns 0x10000, we copy winnt */
2869
2870 pt.x = (short)LOWORD(lParam);
2871 pt.y = (short)HIWORD(lParam);
2872
2873 SetRect(&rect, 0, 0, descr->width, descr->height);
2874
2875 if(!PtInRect(&rect, pt))
2876 {
2877 pt.x = min(pt.x, rect.right - 1);
2878 pt.x = max(pt.x, 0);
2879 pt.y = min(pt.y, rect.bottom - 1);
2880 pt.y = max(pt.y, 0);
2881 hit = FALSE;
2882 }
2883
2885
2886 if(index == -1)
2887 {
2888 index = descr->nb_items - 1;
2889 hit = FALSE;
2890 }
2891 return MAKELONG(index, hit ? 0 : 1);
2892 }
2893
2894 case LB_SETCARETINDEX:
2895 if ((!IS_MULTISELECT(descr)) && (descr->selected_item != -1)) return LB_ERR;
2897 return LB_ERR;
2898 else if (ISWIN31)
2899 return wParam;
2900 else
2901 return LB_OKAY;
2902
2903 case LB_GETCARETINDEX:
2904 return descr->focus_item;
2905
2906 case LB_SETTOPINDEX:
2907 return LISTBOX_SetTopItem( descr, wParam, TRUE );
2908
2909 case LB_SETCOLUMNWIDTH:
2911
2912 case LB_GETITEMRECT:
2914
2915 case LB_FINDSTRING:
2916 {
2917 INT ret;
2918 LPWSTR textW;
2919 if(unicode || !HAS_STRINGS(descr))
2920 textW = (LPWSTR)lParam;
2921 else
2922 {
2924 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
2925 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
2926 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
2927 }
2929 if(!unicode && HAS_STRINGS(descr))
2931 return ret;
2932 }
2933
2934 case LB_FINDSTRINGEXACT:
2935 {
2936 INT ret;
2937 LPWSTR textW;
2938 if(unicode || !HAS_STRINGS(descr))
2939 textW = (LPWSTR)lParam;
2940 else
2941 {
2943 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
2944 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
2945 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
2946 }
2948 if(!unicode && HAS_STRINGS(descr))
2950 return ret;
2951 }
2952
2953 case LB_SELECTSTRING:
2954 {
2955 INT index;
2956 LPWSTR textW;
2957
2958 if(HAS_STRINGS(descr))
2959 TRACE("LB_SELECTSTRING: %s\n", unicode ? debugstr_w((LPWSTR)lParam) :
2961 if(unicode || !HAS_STRINGS(descr))
2962 textW = (LPWSTR)lParam;
2963 else
2964 {
2966 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
2967 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
2968 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
2969 }
2971 if(!unicode && HAS_STRINGS(descr))
2973 if (index != LB_ERR)
2974 {
2977 }
2978 return index;
2979 }
2980
2981 case LB_GETSEL:
2982 if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
2983 return LB_ERR;
2984 return descr->items[wParam].selected;
2985
2986 case LB_SETSEL:
2988
2989 case LB_SETCURSEL:
2990 if (IS_MULTISELECT(descr)) return LB_ERR;
2993 if (ret != LB_ERR) ret = descr->selected_item;
2994 return ret;
2995
2996 case LB_GETSELCOUNT:
2997 return LISTBOX_GetSelCount( descr );
2998
2999 case LB_GETSELITEMS:
3001
3002 case LB_SELITEMRANGE:
3003 if (LOWORD(lParam) <= HIWORD(lParam))
3005 HIWORD(lParam), wParam );
3006 else
3008 LOWORD(lParam), wParam );
3009
3010 case LB_SELITEMRANGEEX:
3011 if ((INT)lParam >= (INT)wParam)
3013 else
3015
3017 return descr->horz_extent;
3018
3021
3022 case LB_GETANCHORINDEX:
3023 return descr->anchor_item;
3024
3025 case LB_SETANCHORINDEX:
3026 if (((INT)wParam < -1) || ((INT)wParam >= descr->nb_items))
3027 {
3029 return LB_ERR;
3030 }
3031 descr->anchor_item = (INT)wParam;
3032 return LB_OKAY;
3033
3034 case LB_DIR:
3035 {
3036 INT ret;
3037 LPWSTR textW;
3038 if(unicode)
3039 textW = (LPWSTR)lParam;
3040 else
3041 {
3043 INT countW = MultiByteToWideChar(CP_ACP, 0, textA, -1, NULL, 0);
3044 if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
3045 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
3046 }
3048 if(!unicode)
3050 return ret;
3051 }
3052
3053 case LB_GETLOCALE:
3054 return descr->locale;
3055
3056 case LB_SETLOCALE:
3057 {
3058 LCID ret;
3060 return LB_ERR;
3061 ret = descr->locale;
3062 descr->locale = (LCID)wParam;
3063 return ret;
3064 }
3065
3066 case LB_INITSTORAGE:
3067 return LISTBOX_InitStorage( descr, wParam );
3068
3069 case LB_SETCOUNT:
3070 return LISTBOX_SetCount( descr, (INT)wParam );
3071
3072 case LB_SETTABSTOPS:
3074
3075 case LB_CARETON:
3076 if (descr->caret_on)
3077 return LB_OKAY;
3078 descr->caret_on = TRUE;
3079 if ((descr->focus_item != -1) && (descr->in_focus))
3080 LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
3081 return LB_OKAY;
3082
3083 case LB_CARETOFF:
3084 if (!descr->caret_on)
3085 return LB_OKAY;
3086 descr->caret_on = FALSE;
3087 if ((descr->focus_item != -1) && (descr->in_focus))
3088 LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
3089 return LB_OKAY;
3090
3091 case LB_GETLISTBOXINFO:
3092 return descr->page_size;
3093
3094 case WM_DESTROY:
3095 return LISTBOX_Destroy( descr );
3096
3097 case WM_ENABLE:
3098 InvalidateRect( descr->self, NULL, TRUE );
3099 return 0;
3100
3101 case WM_SETREDRAW:
3103 return 0;
3104
3105 case WM_GETDLGCODE:
3107
3108 case WM_PRINTCLIENT:
3109 case WM_PAINT:
3110 {
3111 PAINTSTRUCT ps;
3112 HDC hdc = ( wParam ) ? ((HDC)wParam) : BeginPaint( descr->self, &ps );
3113 ret = LISTBOX_Paint( descr, hdc );
3114 if( !wParam ) EndPaint( descr->self, &ps );
3115 }
3116 return ret;
3117 case WM_SIZE:
3119 return 0;
3120 case WM_GETFONT:
3121 return (LRESULT)descr->font;
3122 case WM_SETFONT:
3124 if (lParam) InvalidateRect( descr->self, 0, TRUE );
3125 return 0;
3126 case WM_SETFOCUS:
3127 descr->in_focus = TRUE;
3128 descr->caret_on = TRUE;
3129 if (descr->focus_item != -1)
3132 return 0;
3133 case WM_KILLFOCUS:
3134 LISTBOX_HandleLButtonUp( descr ); /* Release capture if we have it */
3135 descr->in_focus = FALSE;
3136 descr->wheel_remain = 0;
3137 if ((descr->focus_item != -1) && descr->caret_on)
3138 LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
3140 return 0;
3141 case WM_HSCROLL:
3143 case WM_VSCROLL:
3145 case WM_MOUSEWHEEL:
3146 if (wParam & (MK_SHIFT | MK_CONTROL))
3147 return DefWindowProcW( descr->self, msg, wParam, lParam );
3149 case WM_LBUTTONDOWN:
3150 if (lphc)
3153 (INT16)HIWORD(lParam) );
3156 (INT16)HIWORD(lParam) );
3157 case WM_LBUTTONDBLCLK:
3158 if (lphc)
3161 (INT16)HIWORD(lParam) );
3162 if (descr->style & LBS_NOTIFY)
3164 return 0;
3165 case WM_MOUSEMOVE:
3166 if ( lphc && ((lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE) )
3167 {
3168 BOOL captured = descr->captured;
3169 POINT mousePos;
3170 RECT clientRect;
3171
3172 mousePos.x = (INT16)LOWORD(lParam);
3173 mousePos.y = (INT16)HIWORD(lParam);
3174
3175 /*
3176 * If we are in a dropdown combobox, we simulate that
3177 * the mouse is captured to show the tracking of the item.
3178 */
3179 if (GetClientRect(descr->self, &clientRect) && PtInRect( &clientRect, mousePos ))
3180 descr->captured = TRUE;
3181
3182 LISTBOX_HandleMouseMove( descr, mousePos.x, mousePos.y);
3183
3184 descr->captured = captured;
3185 }
3186 else if (GetCapture() == descr->self)
3187 {
3189 (INT16)HIWORD(lParam) );
3190 }
3191 return 0;
3192 case WM_LBUTTONUP:
3193 if (lphc)
3194 {
3195 POINT mousePos;
3196 RECT clientRect;
3197
3198 /*
3199 * If the mouse button "up" is not in the listbox,
3200 * we make sure there is no selection by re-selecting the
3201 * item that was selected when the listbox was made visible.
3202 */
3203 mousePos.x = (INT16)LOWORD(lParam);
3204 mousePos.y = (INT16)HIWORD(lParam);
3205
3206 GetClientRect(descr->self, &clientRect);
3207
3208 /*
3209 * When the user clicks outside the combobox and the focus
3210 * is lost, the owning combobox will send a fake buttonup with
3211 * 0xFFFFFFF as the mouse location, we must also revert the
3212 * selection to the original selection.
3213 */
3214 if ( (lParam == (LPARAM)-1) || (!PtInRect( &clientRect, mousePos )) )
3216 }
3218 case WM_KEYDOWN:
3219 if( lphc && (lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE )
3220 {
3221 /* for some reason Windows makes it possible to
3222 * show/hide ComboLBox by sending it WM_KEYDOWNs */
3223
3224 if( (!(lphc->wState & CBF_EUI) && wParam == VK_F4) ||
3225 ( (lphc->wState & CBF_EUI) && !(lphc->wState & CBF_DROPPED)
3226 && (wParam == VK_DOWN || wParam == VK_UP)) )
3227 {
3228 COMBO_FlipListbox( lphc, FALSE, FALSE );
3229 return 0;
3230 }
3231 }
3233 case WM_CHAR:
3234 {
3235 WCHAR charW;
3236 if(unicode)
3237 charW = (WCHAR)wParam;
3238 else
3239 {
3240 CHAR charA = (CHAR)wParam;
3241 MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
3242 }
3243 return LISTBOX_HandleChar( descr, charW );
3244 }
3245 case WM_SYSTIMER:
3247 case WM_ERASEBKGND:
3248 if ((IS_OWNERDRAW(descr)) && !(descr->style & LBS_DISPLAYCHANGED))
3249 {
3250 RECT rect;
3251#ifdef __REACTOS__
3252 HBRUSH hbrush = GetControlColor( descr->owner, descr->self, (HDC)wParam, WM_CTLCOLORLISTBOX);
3253#else
3254 HBRUSH hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
3255 wParam, (LPARAM)descr->self );
3256#endif
3257 TRACE("hbrush = %p\n", hbrush);
3258 if(!hbrush)
3260 if(hbrush)
3261 {
3262 GetClientRect(descr->self, &rect);
3264 }
3265 }
3266 return 1;
3267 case WM_DROPFILES:
3268 if( lphc ) return 0;
3269 return unicode ? SendMessageW( descr->owner, msg, wParam, lParam ) :
3270 SendMessageA( descr->owner, msg, wParam, lParam );
3271
3272 case WM_NCDESTROY:
3273 if( lphc && (lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE )
3274 lphc->hWndLBox = 0;
3275#ifdef __REACTOS__
3277#endif
3278 break;
3279
3280 case WM_NCACTIVATE:
3281 if (lphc) return 0;
3282 break;
3283// ReactOS
3284 case WM_UPDATEUISTATE:
3285 if (unicode)
3287 else
3289
3291 {
3292 /* redraw text */
3293 if (descr->focus_item != -1)
3294 LISTBOX_DrawFocusRect( descr, descr->in_focus );
3295 }
3296 break;
3297//
3298 default:
3299 if ((msg >= WM_USER) && (msg < 0xc000))
3300 WARN("[%p]: unknown msg %04x wp %08lx lp %08lx\n",
3301 hwnd, msg, wParam, lParam );
3302 }
3303
3304 return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
3306}
3307
3308/***********************************************************************
3309 * ListBoxWndProcA
3310 */
3312{
3314}
3315
3316/***********************************************************************
3317 * ListBoxWndProcW
3318 */
3320{
3322}
static HRGN hrgn
static HBRUSH hbrush
short INT16
Definition: actypes.h:130
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:1086
static LRESULT LISTBOX_RemoveItem(LB_DESCR *descr, INT index)
Definition: listbox.c:1796
#define SEND_NOTIFICATION(descr, code)
Definition: listbox.c:111
static LRESULT LISTBOX_InsertString(LB_DESCR *descr, INT index, LPCWSTR str)
Definition: listbox.c:1733
static void LISTBOX_DrawFocusRect(LB_DESCR *descr, BOOL on)
Definition: listbox.c:797
static void LISTBOX_SetHorizontalPos(LB_DESCR *descr, INT pos)
Definition: listbox.c:1364
static LRESULT LISTBOX_HandleKeyDown(LB_DESCR *descr, DWORD key)
Definition: listbox.c:2461
static LRESULT LISTBOX_SetCaretIndex(LB_DESCR *descr, INT index, BOOL fully_visible)
Definition: listbox.c:1510
static BOOL LISTBOX_SetTabStops(LB_DESCR *descr, INT count, LPINT tabs)
Definition: listbox.c:837
static LRESULT LISTBOX_HandleLButtonUp(LB_DESCR *descr)
Definition: listbox.c:2341
#define ATTRIBS
static void LISTBOX_DeleteItem(LB_DESCR *descr, INT index)
Definition: listbox.c:1768
static void LISTBOX_InvalidateItems(LB_DESCR *descr, INT index)
Definition: listbox.c:1275
static LRESULT LISTBOX_GetSelCount(const LB_DESCR *descr)
Definition: listbox.c:1075
static void LISTBOX_SetRedraw(LB_DESCR *descr, BOOL on)
Definition: listbox.c:737
static void LISTBOX_InvalidateItemRect(LB_DESCR *descr, INT index)
Definition: listbox.c:1299
static LRESULT LISTBOX_GetText(LB_DESCR *descr, INT index, LPWSTR buffer, BOOL unicode)
Definition: listbox.c:869
#define ISWIN31
Definition: listbox.c:115
static LRESULT LISTBOX_InitStorage(LB_DESCR *descr, INT nb_items)
Definition: listbox.c:824
static void LISTBOX_MakeItemVisible(LB_DESCR *descr, INT index, BOOL fully)
Definition: listbox.c:1471
static INT LISTBOX_FindFileStrPos(LB_DESCR *descr, LPCWSTR str)
Definition: listbox.c:971
static LRESULT LISTBOX_SetSelection(LB_DESCR *descr, INT index, BOOL on, BOOL send_notify)
Definition: listbox.c:1579
static LRESULT LISTBOX_HandleLButtonDownCombo(LB_DESCR *descr, UINT msg, DWORD keys, INT x, INT y)
Definition: listbox.c:2263
static LRESULT LISTBOX_HandleVScroll(LB_DESCR *descr, WORD scrollReq, WORD pos)
Definition: listbox.c:1990
#define IS_MULTISELECT(descr)
Definition: listbox.c:107
static void LISTBOX_ResetContent(LB_DESCR *descr)
Definition: listbox.c:1848
static LRESULT LISTBOX_HandleTimer(LB_DESCR *descr, INT index, TIMER_DIRECTION dir)
Definition: listbox.c:2363
#define HAS_STRINGS(descr)
Definition: listbox.c:103
static LRESULT LISTBOX_HandleMouseWheel(LB_DESCR *descr, SHORT delta)
Definition: listbox.c:2120
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:1392
static LRESULT LISTBOX_InsertItem(LB_DESCR *descr, INT index, LPWSTR str, ULONG_PTR data)
Definition: listbox.c:1669
static void LISTBOX_MoveCaret(LB_DESCR *descr, INT index, BOOL fully_visible)
Definition: listbox.c:1622
static LRESULT LISTBOX_GetSelItems(const LB_DESCR *descr, INT max, LPINT array)
Definition: listbox.c:1091
static LRESULT LISTBOX_Paint(LB_DESCR *descr, HDC hdc)
Definition: listbox.c:1105
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:1440
static LRESULT LISTBOX_SetColumnWidth(LB_DESCR *descr, INT column_width)
Definition: listbox.c:1418
static LRESULT LISTBOX_HandleHScroll(LB_DESCR *descr, WORD scrollReq, WORD pos)
Definition: listbox.c:2034
static LRESULT LISTBOX_SelectItemRange(LB_DESCR *descr, INT first, INT last, BOOL on)
Definition: listbox.c:1539
static void LISTBOX_RepaintItem(LB_DESCR *descr, INT index, UINT action)
Definition: listbox.c:764
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:1015
static BOOL LISTBOX_Destroy(LB_DESCR *descr)
Definition: listbox.c:2692
#define LB_ARRAY_GRANULARITY
Definition: listbox.c:43
static LRESULT LISTBOX_HandleSystemTimer(LB_DESCR *descr)
Definition: listbox.c:2397
#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:1907
static void LISTBOX_HandleMouseMove(LB_DESCR *descr, INT x, INT y)
Definition: listbox.c:2413
static LRESULT LISTBOX_GetItemHeight(const LB_DESCR *descr, INT index)
Definition: listbox.c:1310
#define LB_SCROLL_TIMEOUT
Definition: listbox.c:46
static INT LISTBOX_FindStringPos(LB_DESCR *descr, LPCWSTR str, BOOL exact)
Definition: listbox.c:927
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:909
#define LBS_DISPLAYCHANGED
Definition: listbox.c:52
static LRESULT LISTBOX_HandleChar(LB_DESCR *descr, WCHAR charW)
Definition: listbox.c:2572
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:1328
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:1868
static INT LISTBOX_GetMaxTopIndex(const LB_DESCR *descr)
Definition: listbox.c:271
static BOOL LISTBOX_Create(HWND hwnd, LPHEADCOMBO lphc)
Definition: listbox.c:2604
static LRESULT LISTBOX_HandleLButtonDown(LB_DESCR *descr, DWORD keys, INT x, INT y)
Definition: listbox.c:2158
#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:3946
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:4351
#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:54
static const WCHAR dotW[]
Definition: directory.c:80
static float(__cdecl *square_half_float)(float x
#define WM_LBTRACKPOINT
Definition: msg.c:61
#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
#define OBJ_BRUSH
Definition: objidl.idl:1015
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:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
#define WM_PRINTCLIENT
Definition: richedit.h:70
const WCHAR * str
DWORD LCID
Definition: nls.h:13
XML_HIDDEN void xmlParserErrors const char const xmlChar const xmlChar * str2
Definition: parser.h:35
XML_HIDDEN void xmlParserErrors const char const xmlChar * str1
Definition: parser.h:35
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: undname.c:54
Definition: copy.c:22
Definition: module.h:576
ULONG_PTR itemData1
Definition: winuser.h:3102
ULONG_PTR itemData2
Definition: winuser.h:3104
LPVOID lpCreateParams
Definition: winuser.h:3063
ULONG_PTR itemData
Definition: winuser.h:3152
ULONG_PTR itemData
Definition: winuser.h:3201
ULONG_PTR itemData
Definition: winuser.h:3754
long y
Definition: polytest.cpp:48
long x
Definition: polytest.cpp:48
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
#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:98
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:3319
LRESULT WINAPI ListBoxWndProcA(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: listbox.c:3311
static const WCHAR combolboxW[]
Definition: listbox.c:141
static BOOL LISTBOX_update_uistate(LB_DESCR *descr)
Definition: listbox.c:2532
#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:2648
#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:100
#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
#define GetTextExtentPoint32
Definition: wingdi.h:4918
HGDIOBJ WINAPI GetCurrentObject(_In_ HDC, _In_ UINT)
Definition: dc.c:428
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:4117
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:4983
#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:4116
#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:5512
#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