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