ReactOS  0.4.13-dev-259-g5ca9c9c
combo.c
Go to the documentation of this file.
1 /*
2  * Combo controls
3  *
4  * Copyright 1997 Alex Korobka
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * NOTES
21  *
22  * This code was audited for completeness against the documented features
23  * of Comctl32.dll version 6.0 on Oct. 4, 2004, by Dimitrie O. Paun.
24  *
25  * Unless otherwise noted, we believe this code to be complete, as per
26  * the specification mentioned above.
27  * If you discover missing features, or bugs, please note them below.
28  *
29  * TODO:
30  * - ComboBox_[GS]etMinVisible()
31  * - CB_GETMINVISIBLE, CB_SETMINVISIBLE
32  * - CB_SETTOPINDEX
33  */
34 
35 #include <user32.h>
36 
38 
39 /*
40  * Additional combo box definitions
41  */
42 
43 #define CB_NOTIFY( lphc, code ) \
44  (SendMessageW((lphc)->owner, WM_COMMAND, \
45  MAKEWPARAM(GetWindowLongPtrW((lphc)->self,GWLP_ID), (code)), (LPARAM)(lphc)->self))
46 
47 #define CB_DISABLED( lphc ) (!IsWindowEnabled((lphc)->self))
48 #define CB_OWNERDRAWN( lphc ) ((lphc)->dwStyle & (CBS_OWNERDRAWFIXED | CBS_OWNERDRAWVARIABLE))
49 #define CB_HASSTRINGS( lphc ) ((lphc)->dwStyle & CBS_HASSTRINGS)
50 #define CB_HWND( lphc ) ((lphc)->self)
51 #ifndef __REACTOS__
52 /* ReactOS already define in include/controls.h We have it here as a sync note. */
53 #define CB_GETTYPE( lphc ) ((lphc)->dwStyle & (CBS_DROPDOWNLIST))
54 #endif
55 
56 #define ISWIN31 (LOWORD(GetVersion()) == 0x0a03)
57 
58 /*
59  * Drawing globals
60  */
61 static HBITMAP hComboBmp = 0;
63 
64 /*
65  * Look and feel dependent "constants"
66  */
67 
68 #define COMBO_YBORDERGAP 5
69 #define COMBO_XBORDERSIZE() 2
70 #define COMBO_YBORDERSIZE() 2
71 #define COMBO_EDITBUTTONSPACE() 0
72 #define EDIT_CONTROL_PADDING() 1
73 
74 /*********************************************************************
75  * combo class descriptor
76  */
77 static const WCHAR comboboxW[] = {'C','o','m','b','o','B','o','x',0};
79 {
80  comboboxW, /* name */
81  CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, /* style */
82 #ifdef __REACTOS__
83  ComboWndProcA, /* procA */
84  ComboWndProcW, /* procW */
85 #else
86  WINPROC_COMBO, /* proc */
87 #endif
88  sizeof(HEADCOMBO *), /* extra */
89  IDC_ARROW, /* cursor */
90  0 /* brush */
91 };
92 
93 
94 /***********************************************************************
95  * COMBO_Init
96  *
97  * Load combo button bitmap.
98  */
99 static BOOL COMBO_Init(void)
100 {
101  HDC hDC;
102 
103  if( hComboBmp ) return TRUE;
104  if( (hDC = CreateCompatibleDC(0)) )
105  {
106  BOOL bRet = FALSE;
108  {
109  BITMAP bm;
110  HBITMAP hPrevB;
111  RECT r;
112 
113  GetObjectW( hComboBmp, sizeof(bm), &bm );
114  CBitHeight = bm.bmHeight;
115  CBitWidth = bm.bmWidth;
116 
117  TRACE("combo bitmap [%i,%i]\n", CBitWidth, CBitHeight );
118 
119  hPrevB = SelectObject( hDC, hComboBmp);
120  SetRect( &r, 0, 0, CBitWidth, CBitHeight );
121  InvertRect( hDC, &r );
122  SelectObject( hDC, hPrevB );
123  bRet = TRUE;
124  }
125  DeleteDC( hDC );
126  return bRet;
127  }
128  return FALSE;
129 }
130 
131 #ifdef __REACTOS__
132 /* Retrieve the UI state for the control */
133 static BOOL COMBO_update_uistate(LPHEADCOMBO lphc)
134 {
135  LONG prev_flags;
136 
137  prev_flags = lphc->UIState;
138  lphc->UIState = DefWindowProcW(lphc->self, WM_QUERYUISTATE, 0, 0);
139  return prev_flags != lphc->UIState;
140 }
141 #endif
142 
143 /***********************************************************************
144  * COMBO_NCCreate
145  */
147 {
148  LPHEADCOMBO lphc;
149 
150  if (COMBO_Init() && (lphc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HEADCOMBO))) )
151  {
152  lphc->self = hwnd;
153  SetWindowLongPtrW( hwnd, 0, (LONG_PTR)lphc );
154 
155 #ifdef __REACTOS__
156  COMBO_update_uistate(lphc);
157 #endif
158 
159  /* some braindead apps do try to use scrollbar/border flags */
160 
161  lphc->dwStyle = style & ~(WS_BORDER | WS_HSCROLL | WS_VSCROLL);
163 
164  /*
165  * We also have to remove the client edge style to make sure
166  * we don't end-up with a non client area.
167  */
170 
172  lphc->dwStyle |= CBS_HASSTRINGS;
174  lphc->wState |= CBF_NOTIFY;
175 
176  TRACE("[%p], style = %08x\n", lphc, lphc->dwStyle );
177  return TRUE;
178  }
179  return FALSE;
180 }
181 
182 /***********************************************************************
183  * COMBO_NCDestroy
184  */
186 {
187 
188  if( lphc )
189  {
190  TRACE("[%p]: freeing storage\n", lphc->self);
191 
192  if( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox )
193  DestroyWindow( lphc->hWndLBox );
194 
195  SetWindowLongPtrW( lphc->self, 0, 0 );
196  HeapFree( GetProcessHeap(), 0, lphc );
197  }
198  return 0;
199 }
200 
201 /***********************************************************************
202  * CBGetTextAreaHeight
203  *
204  * This method will calculate the height of the text area of the
205  * combobox.
206  * The height of the text area is set in two ways.
207  * It can be set explicitly through a combobox message or through a
208  * WM_MEASUREITEM callback.
209  * If this is not the case, the height is set to font height + 4px
210  * This height was determined through experimentation.
211  * CBCalcPlacement will add 2*COMBO_YBORDERSIZE pixels for the border
212  */
214  HWND hwnd,
215  LPHEADCOMBO lphc)
216 {
217  INT iTextItemHeight;
218 
219  if( lphc->editHeight ) /* explicitly set height */
220  {
221  iTextItemHeight = lphc->editHeight;
222  }
223  else
224  {
225  TEXTMETRICW tm;
226  HDC hDC = GetDC(hwnd);
227  HFONT hPrevFont = 0;
228  INT baseUnitY;
229 
230  if (lphc->hFont)
231  hPrevFont = SelectObject( hDC, lphc->hFont );
232 
234 
235  baseUnitY = tm.tmHeight;
236 
237  if( hPrevFont )
238  SelectObject( hDC, hPrevFont );
239 
240  ReleaseDC(hwnd, hDC);
241 
242  iTextItemHeight = baseUnitY + 4;
243  }
244 
245  /*
246  * Check the ownerdraw case if we haven't asked the parent the size
247  * of the item yet.
248  */
249  if ( CB_OWNERDRAWN(lphc) &&
250  (lphc->wState & CBF_MEASUREITEM) )
251  {
252  MEASUREITEMSTRUCT measureItem;
253  RECT clientRect;
254  INT originalItemHeight = iTextItemHeight;
255  UINT id = (UINT)GetWindowLongPtrW( lphc->self, GWLP_ID );
256 
257  /*
258  * We use the client rect for the width of the item.
259  */
260  GetClientRect(hwnd, &clientRect);
261 
262  lphc->wState &= ~CBF_MEASUREITEM;
263 
264  /*
265  * Send a first one to measure the size of the text area
266  */
267  measureItem.CtlType = ODT_COMBOBOX;
268  measureItem.CtlID = id;
269  measureItem.itemID = -1;
270  measureItem.itemWidth = clientRect.right;
271  measureItem.itemHeight = iTextItemHeight - 6; /* ownerdrawn cb is taller */
272  measureItem.itemData = 0;
273  SendMessageW(lphc->owner, WM_MEASUREITEM, id, (LPARAM)&measureItem);
274  iTextItemHeight = 6 + measureItem.itemHeight;
275 
276  /*
277  * Send a second one in the case of a fixed ownerdraw list to calculate the
278  * size of the list items. (we basically do this on behalf of the listbox)
279  */
280  if (lphc->dwStyle & CBS_OWNERDRAWFIXED)
281  {
282  measureItem.CtlType = ODT_COMBOBOX;
283  measureItem.CtlID = id;
284  measureItem.itemID = 0;
285  measureItem.itemWidth = clientRect.right;
286  measureItem.itemHeight = originalItemHeight;
287  measureItem.itemData = 0;
288  SendMessageW(lphc->owner, WM_MEASUREITEM, id, (LPARAM)&measureItem);
289  lphc->fixedOwnerDrawHeight = measureItem.itemHeight;
290  }
291 
292  /*
293  * Keep the size for the next time
294  */
295  lphc->editHeight = iTextItemHeight;
296  }
297 
298  return iTextItemHeight;
299 }
300 
301 /***********************************************************************
302  * CBForceDummyResize
303  *
304  * The dummy resize is used for listboxes that have a popup to trigger
305  * a re-arranging of the contents of the combobox and the recalculation
306  * of the size of the "real" control window.
307  */
308 static void CBForceDummyResize(
309  LPHEADCOMBO lphc)
310 {
311  RECT windowRect;
312  int newComboHeight;
313 
314  newComboHeight = CBGetTextAreaHeight(lphc->self,lphc) + 2*COMBO_YBORDERSIZE();
315 
316  GetWindowRect(lphc->self, &windowRect);
317 
318  /*
319  * We have to be careful, resizing a combobox also has the meaning that the
320  * dropped rect will be resized. In this case, we want to trigger a resize
321  * to recalculate layout but we don't want to change the dropped rectangle
322  * So, we pass the height of text area of control as the height.
323  * this will cancel-out in the processing of the WM_WINDOWPOSCHANGING
324  * message.
325  */
326  SetWindowPos( lphc->self,
327  NULL,
328  0, 0,
329  windowRect.right - windowRect.left,
330  newComboHeight,
332 }
333 
334 /***********************************************************************
335  * CBCalcPlacement
336  *
337  * Set up component coordinates given valid lphc->RectCombo.
338  */
339 static void CBCalcPlacement(
340  HWND hwnd,
341  LPHEADCOMBO lphc,
342  LPRECT lprEdit,
343  LPRECT lprButton,
344  LPRECT lprLB)
345 {
346  /*
347  * Again, start with the client rectangle.
348  */
349  GetClientRect(hwnd, lprEdit);
350 
351  /*
352  * Remove the borders
353  */
355 
356  /*
357  * Chop off the bottom part to fit with the height of the text area.
358  */
359  lprEdit->bottom = lprEdit->top + CBGetTextAreaHeight(hwnd, lphc);
360 
361  /*
362  * The button starts the same vertical position as the text area.
363  */
364  CopyRect(lprButton, lprEdit);
365 
366  /*
367  * If the combobox is "simple" there is no button.
368  */
369  if( CB_GETTYPE(lphc) == CBS_SIMPLE )
370  lprButton->left = lprButton->right = lprButton->bottom = 0;
371  else
372  {
373  /*
374  * Let's assume the combobox button is the same width as the
375  * scrollbar button.
376  * size the button horizontally and cut-off the text area.
377  */
378  lprButton->left = lprButton->right - GetSystemMetrics(SM_CXVSCROLL);
379  lprEdit->right = lprButton->left;
380  }
381 
382  /*
383  * In the case of a dropdown, there is an additional spacing between the
384  * text area and the button.
385  */
386  if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
387  {
388  lprEdit->right -= COMBO_EDITBUTTONSPACE();
389  }
390 
391  /*
392  * If we have an edit control, we space it away from the borders slightly.
393  */
394  if (CB_GETTYPE(lphc) != CBS_DROPDOWNLIST)
395  {
397  }
398 
399  /*
400  * Adjust the size of the listbox popup.
401  */
402  if( CB_GETTYPE(lphc) == CBS_SIMPLE )
403  {
404  /*
405  * Use the client rectangle to initialize the listbox rectangle
406  */
407  GetClientRect(hwnd, lprLB);
408 
409  /*
410  * Then, chop-off the top part.
411  */
412  lprLB->top = lprEdit->bottom + COMBO_YBORDERSIZE();
413  }
414  else
415  {
416  /*
417  * Make sure the dropped width is as large as the combobox itself.
418  */
419  if (lphc->droppedWidth < (lprButton->right + COMBO_XBORDERSIZE()))
420  {
421  lprLB->right = lprLB->left + (lprButton->right + COMBO_XBORDERSIZE());
422 
423  /*
424  * In the case of a dropdown, the popup listbox is offset to the right.
425  * so, we want to make sure it's flush with the right side of the
426  * combobox
427  */
428  if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
429  lprLB->right -= COMBO_EDITBUTTONSPACE();
430  }
431  else
432  lprLB->right = lprLB->left + lphc->droppedWidth;
433  }
434 
435  /* don't allow negative window width */
436  if (lprEdit->right < lprEdit->left)
437  lprEdit->right = lprEdit->left;
438 
439  TRACE("\ttext\t= (%s)\n", wine_dbgstr_rect(lprEdit));
440 
441  TRACE("\tbutton\t= (%s)\n", wine_dbgstr_rect(lprButton));
442 
443  TRACE("\tlbox\t= (%s)\n", wine_dbgstr_rect(lprLB));
444 }
445 
446 /***********************************************************************
447  * CBGetDroppedControlRect
448  */
449 static void CBGetDroppedControlRect( LPHEADCOMBO lphc, LPRECT lpRect)
450 {
451  /* In windows, CB_GETDROPPEDCONTROLRECT returns the upper left corner
452  of the combo box and the lower right corner of the listbox */
453 
454  GetWindowRect(lphc->self, lpRect);
455 
456  lpRect->right = lpRect->left + lphc->droppedRect.right - lphc->droppedRect.left;
457  lpRect->bottom = lpRect->top + lphc->droppedRect.bottom - lphc->droppedRect.top;
458 
459 }
460 
461 /***********************************************************************
462  * COMBO_Create
463  */
465  BOOL unicode )
466 {
467  static const WCHAR clbName[] = {'C','o','m','b','o','L','B','o','x',0};
468  static const WCHAR editName[] = {'E','d','i','t',0};
469 
470  if( !CB_GETTYPE(lphc) ) lphc->dwStyle |= CBS_SIMPLE;
471  if( CB_GETTYPE(lphc) != CBS_DROPDOWNLIST ) lphc->wState |= CBF_EDIT;
472 
473  lphc->owner = hwndParent;
474 
475  /*
476  * The item height and dropped width are not set when the control
477  * is created.
478  */
479  lphc->droppedWidth = lphc->editHeight = 0;
480 
481  /*
482  * The first time we go through, we want to measure the ownerdraw item
483  */
484  lphc->wState |= CBF_MEASUREITEM;
485 
486  /* M$ IE 3.01 actually creates (and rapidly destroys) an ownerless combobox */
487 
488  if( lphc->owner || !(style & WS_VISIBLE) )
489  {
490  UINT lbeStyle = 0;
491  UINT lbeExStyle = 0;
492 
493  /*
494  * Initialize the dropped rect to the size of the client area of the
495  * control and then, force all the areas of the combobox to be
496  * recalculated.
497  */
498  GetClientRect( hwnd, &lphc->droppedRect );
499  CBCalcPlacement(hwnd, lphc, &lphc->textRect, &lphc->buttonRect, &lphc->droppedRect );
500 
501  /*
502  * Adjust the position of the popup listbox if it's necessary
503  */
504  if ( CB_GETTYPE(lphc) != CBS_SIMPLE )
505  {
506  lphc->droppedRect.top = lphc->textRect.bottom + COMBO_YBORDERSIZE();
507 
508  /*
509  * If it's a dropdown, the listbox is offset
510  */
511  if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
513 
514  if (lphc->droppedRect.bottom < lphc->droppedRect.top)
515  lphc->droppedRect.bottom = lphc->droppedRect.top;
516  if (lphc->droppedRect.right < lphc->droppedRect.left)
517  lphc->droppedRect.right = lphc->droppedRect.left;
518  MapWindowPoints( hwnd, 0, (LPPOINT)&lphc->droppedRect, 2 );
519  }
520 
521  /* create listbox popup */
522 
525 
526  if( lphc->dwStyle & CBS_SORT )
527  lbeStyle |= LBS_SORT;
528  if( lphc->dwStyle & CBS_HASSTRINGS )
529  lbeStyle |= LBS_HASSTRINGS;
530  if( lphc->dwStyle & CBS_NOINTEGRALHEIGHT )
531  lbeStyle |= LBS_NOINTEGRALHEIGHT;
532  if( lphc->dwStyle & CBS_DISABLENOSCROLL )
533  lbeStyle |= LBS_DISABLENOSCROLL;
534 
535  if( CB_GETTYPE(lphc) == CBS_SIMPLE ) /* child listbox */
536  {
537  lbeStyle |= WS_VISIBLE;
538 
539  /*
540  * In win 95 look n feel, the listbox in the simple combobox has
541  * the WS_EXCLIENTEDGE style instead of the WS_BORDER style.
542  */
543  lbeStyle &= ~WS_BORDER;
544  lbeExStyle |= WS_EX_CLIENTEDGE;
545  }
546  else
547  {
548  lbeExStyle |= (WS_EX_TOPMOST | WS_EX_TOOLWINDOW);
549  }
550 
551  if (unicode)
552  lphc->hWndLBox = CreateWindowExW(lbeExStyle, clbName, NULL, lbeStyle,
553  lphc->droppedRect.left,
554  lphc->droppedRect.top,
555  lphc->droppedRect.right - lphc->droppedRect.left,
556  lphc->droppedRect.bottom - lphc->droppedRect.top,
559  else
560  lphc->hWndLBox = CreateWindowExA(lbeExStyle, "ComboLBox", NULL, lbeStyle,
561  lphc->droppedRect.left,
562  lphc->droppedRect.top,
563  lphc->droppedRect.right - lphc->droppedRect.left,
564  lphc->droppedRect.bottom - lphc->droppedRect.top,
567 
568  if( lphc->hWndLBox )
569  {
570  BOOL bEdit = TRUE;
571  lbeStyle = WS_CHILD | WS_VISIBLE | ES_NOHIDESEL | ES_LEFT | ES_COMBO;
572 
573  if( lphc->wState & CBF_EDIT )
574  {
575  if( lphc->dwStyle & CBS_OEMCONVERT )
576  lbeStyle |= ES_OEMCONVERT;
577  if( lphc->dwStyle & CBS_AUTOHSCROLL )
578  lbeStyle |= ES_AUTOHSCROLL;
579  if( lphc->dwStyle & CBS_LOWERCASE )
580  lbeStyle |= ES_LOWERCASE;
581  else if( lphc->dwStyle & CBS_UPPERCASE )
582  lbeStyle |= ES_UPPERCASE;
583 
584  if (!IsWindowEnabled(hwnd)) lbeStyle |= WS_DISABLED;
585 
586  if (unicode)
587  lphc->hWndEdit = CreateWindowExW(0, editName, NULL, lbeStyle,
588  lphc->textRect.left, lphc->textRect.top,
589  lphc->textRect.right - lphc->textRect.left,
590  lphc->textRect.bottom - lphc->textRect.top,
593  else
594  lphc->hWndEdit = CreateWindowExA(0, "Edit", NULL, lbeStyle,
595  lphc->textRect.left, lphc->textRect.top,
596  lphc->textRect.right - lphc->textRect.left,
597  lphc->textRect.bottom - lphc->textRect.top,
600 
601  if( !lphc->hWndEdit )
602  bEdit = FALSE;
603  }
604 
605  if( bEdit )
606  {
607  if( CB_GETTYPE(lphc) != CBS_SIMPLE )
608  {
609  /* Now do the trick with parent */
611  /*
612  * If the combo is a dropdown, we must resize the control
613  * to fit only the text area and button. To do this,
614  * we send a dummy resize and the WM_WINDOWPOSCHANGING message
615  * will take care of setting the height for us.
616  */
617  CBForceDummyResize(lphc);
618  }
619 
620  TRACE("init done\n");
621  return 0;
622  }
623  ERR("edit control failure.\n");
624  } else ERR("listbox failure.\n");
625  } else ERR("no owner for visible combo.\n");
626 
627  /* CreateWindow() will send WM_NCDESTROY to cleanup */
628 
629  return -1;
630 }
631 
632 /***********************************************************************
633  * CBPaintButton
634  *
635  * Paint combo button (normal, pressed, and disabled states).
636  */
637 static void CBPaintButton( LPHEADCOMBO lphc, HDC hdc, RECT rectButton)
638 {
639  UINT buttonState = DFCS_SCROLLCOMBOBOX;
640 
641  if( lphc->wState & CBF_NOREDRAW )
642  return;
643 
644 
645  if (lphc->wState & CBF_BUTTONDOWN)
646  buttonState |= DFCS_PUSHED;
647 
648  if (CB_DISABLED(lphc))
649  buttonState |= DFCS_INACTIVE;
650 
651  DrawFrameControl(hdc, &rectButton, DFC_SCROLL, buttonState);
652 }
653 
654 /***********************************************************************
655  * CBPaintText
656  *
657  * Paint CBS_DROPDOWNLIST text field / update edit control contents.
658  */
659 static void CBPaintText(
660  LPHEADCOMBO lphc,
661  HDC hdc,
662  RECT rectEdit)
663 {
664  INT id, size = 0;
665  LPWSTR pText = NULL;
666 
667  if( lphc->wState & CBF_NOREDRAW ) return;
668 
669  TRACE("\n");
670 
671  /* follow Windows combobox that sends a bunch of text
672  * inquiries to its listbox while processing WM_PAINT. */
673 
674  if( (id = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0) ) != LB_ERR )
675  {
676  size = SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, id, 0);
677  if (size == LB_ERR)
678  FIXME("LB_ERR probably not handled yet\n");
679  if( (pText = HeapAlloc( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR))) )
680  {
681  /* size from LB_GETTEXTLEN may be too large, from LB_GETTEXT is accurate */
683  pText[size] = '\0'; /* just in case */
684  } else return;
685  }
686  else
687  if( !CB_OWNERDRAWN(lphc) )
688  return;
689 
690  if( lphc->wState & CBF_EDIT )
691  {
692  static const WCHAR empty_stringW[] = { 0 };
693  if( CB_HASSTRINGS(lphc) ) SetWindowTextW( lphc->hWndEdit, pText ? pText : empty_stringW );
694  if( lphc->wState & CBF_FOCUSED )
695  SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1));
696  }
697  else /* paint text field ourselves */
698  {
699  UINT itemState = ODS_COMBOBOXEDIT;
700  HFONT hPrevFont = (lphc->hFont) ? SelectObject(hdc, lphc->hFont) : 0;
701 
702  /*
703  * Give ourselves some space.
704  */
705  InflateRect( &rectEdit, -1, -1 );
706 
707  if( CB_OWNERDRAWN(lphc) )
708  {
709  DRAWITEMSTRUCT dis;
710  HRGN clipRegion;
711  UINT ctlid = (UINT)GetWindowLongPtrW( lphc->self, GWLP_ID );
712 
713  /* setup state for DRAWITEM message. Owner will highlight */
714  if ( (lphc->wState & CBF_FOCUSED) &&
715  !(lphc->wState & CBF_DROPPED) )
716  itemState |= ODS_SELECTED | ODS_FOCUS;
717 
718  if (!IsWindowEnabled(lphc->self)) itemState |= ODS_DISABLED;
719 
720  dis.CtlType = ODT_COMBOBOX;
721  dis.CtlID = ctlid;
722  dis.hwndItem = lphc->self;
724  dis.itemID = id;
725  dis.itemState = itemState;
726  dis.hDC = hdc;
727  dis.rcItem = rectEdit;
728  dis.itemData = SendMessageW(lphc->hWndLBox, LB_GETITEMDATA, id, 0);
729 
730  /*
731  * Clip the DC and have the parent draw the item.
732  */
733  clipRegion = set_control_clipping( hdc, &rectEdit );
734 
735  SendMessageW(lphc->owner, WM_DRAWITEM, ctlid, (LPARAM)&dis );
736 
737  SelectClipRgn( hdc, clipRegion );
738  if (clipRegion) DeleteObject( clipRegion );
739  }
740  else
741  {
742  static const WCHAR empty_stringW[] = { 0 };
743 
744  if ( (lphc->wState & CBF_FOCUSED) &&
745  !(lphc->wState & CBF_DROPPED) ) {
746 
747  /* highlight */
751  }
752 
753  ExtTextOutW( hdc,
754  rectEdit.left + 1,
755  rectEdit.top + 1,
757  &rectEdit,
758  pText ? pText : empty_stringW , size, NULL );
759 
760 #ifdef __REACTOS__
761  if(lphc->wState & CBF_FOCUSED &&
762  !(lphc->wState & CBF_DROPPED) &&
763  !(lphc->UIState & UISF_HIDEFOCUS))
764 #else
765  if(lphc->wState & CBF_FOCUSED && !(lphc->wState & CBF_DROPPED))
766 #endif
767  DrawFocusRect( hdc, &rectEdit );
768  }
769 
770  if( hPrevFont )
771  SelectObject(hdc, hPrevFont );
772  }
773 #ifdef __REACTOS__
774  if (pText)
775 #endif
776  HeapFree( GetProcessHeap(), 0, pText );
777 }
778 
779 /***********************************************************************
780  * CBPaintBorder
781  */
782 static void CBPaintBorder(
783  HWND hwnd,
784  const HEADCOMBO *lphc,
785  HDC hdc)
786 {
787  RECT clientRect;
788 
789  if (CB_GETTYPE(lphc) != CBS_SIMPLE)
790  {
791  GetClientRect(hwnd, &clientRect);
792  }
793  else
794  {
795  CopyRect(&clientRect, &lphc->textRect);
796 
799  }
800 
801  DrawEdge(hdc, &clientRect, EDGE_SUNKEN, BF_RECT);
802 }
803 
804 /***********************************************************************
805  * COMBO_PrepareColors
806  *
807  * This method will sent the appropriate WM_CTLCOLOR message to
808  * prepare and setup the colors for the combo's DC.
809  *
810  * It also returns the brush to use for the background.
811  */
812 static HBRUSH COMBO_PrepareColors(
813  LPHEADCOMBO lphc,
814  HDC hDC)
815 {
816  HBRUSH hBkgBrush;
817 
818  /*
819  * Get the background brush for this control.
820  */
821  if (CB_DISABLED(lphc))
822  {
823 #ifdef __REACTOS__
824  hBkgBrush = GetControlColor(lphc->owner, lphc->self, hDC, WM_CTLCOLORSTATIC);
825 #else
826  hBkgBrush = (HBRUSH)SendMessageW(lphc->owner, WM_CTLCOLORSTATIC,
827  (WPARAM)hDC, (LPARAM)lphc->self );
828 #endif
829  /*
830  * We have to change the text color since WM_CTLCOLORSTATIC will
831  * set it to the "enabled" color. This is the same behavior as the
832  * edit control
833  */
835  }
836  else
837  {
838  /* FIXME: In which cases WM_CTLCOLORLISTBOX should be sent? */
839 #ifdef __REACTOS__
840  hBkgBrush = GetControlColor(lphc->owner, lphc->self, hDC, WM_CTLCOLOREDIT);
841 #else
842  hBkgBrush = (HBRUSH)SendMessageW(lphc->owner, WM_CTLCOLOREDIT,
843  (WPARAM)hDC, (LPARAM)lphc->self );
844 #endif
845  }
846 
847  /*
848  * Catch errors.
849  */
850  if( !hBkgBrush )
851  hBkgBrush = GetSysColorBrush(COLOR_WINDOW);
852 
853  return hBkgBrush;
854 }
855 
856 
857 /***********************************************************************
858  * COMBO_Paint
859  */
860 static LRESULT COMBO_Paint(LPHEADCOMBO lphc, HDC hParamDC)
861 {
862  PAINTSTRUCT ps;
863  HDC hDC;
864 
865  hDC = (hParamDC) ? hParamDC
866  : BeginPaint( lphc->self, &ps);
867 
868  TRACE("hdc=%p\n", hDC);
869 
870  if( hDC && !(lphc->wState & CBF_NOREDRAW) )
871  {
872  HBRUSH hPrevBrush, hBkgBrush;
873 
874  /*
875  * Retrieve the background brush and select it in the
876  * DC.
877  */
878  hBkgBrush = COMBO_PrepareColors(lphc, hDC);
879 
880  hPrevBrush = SelectObject( hDC, hBkgBrush );
881  if (!(lphc->wState & CBF_EDIT))
882  FillRect(hDC, &lphc->textRect, hBkgBrush);
883 
884  /*
885  * In non 3.1 look, there is a sunken border on the combobox
886  */
887  CBPaintBorder(lphc->self, lphc, hDC);
888 
889  if( !IsRectEmpty(&lphc->buttonRect) )
890  {
891  CBPaintButton(lphc, hDC, lphc->buttonRect);
892  }
893 
894  /* paint the edit control padding area */
895  if (CB_GETTYPE(lphc) != CBS_DROPDOWNLIST)
896  {
897  RECT rPadEdit = lphc->textRect;
898 
900 
901  FrameRect( hDC, &rPadEdit, GetSysColorBrush(COLOR_WINDOW) );
902  }
903 
904  if( !(lphc->wState & CBF_EDIT) )
905  CBPaintText( lphc, hDC, lphc->textRect);
906 
907  if( hPrevBrush )
908  SelectObject( hDC, hPrevBrush );
909  }
910 
911  if( !hParamDC )
912  EndPaint(lphc->self, &ps);
913 
914  return 0;
915 }
916 
917 /***********************************************************************
918  * CBUpdateLBox
919  *
920  * Select listbox entry according to the contents of the edit control.
921  */
922 static INT CBUpdateLBox( LPHEADCOMBO lphc, BOOL bSelect )
923 {
924  INT length, idx;
925  LPWSTR pText = NULL;
926 
927  idx = LB_ERR;
928  length = SendMessageW( lphc->hWndEdit, WM_GETTEXTLENGTH, 0, 0 );
929 
930  if( length > 0 )
931  pText = HeapAlloc( GetProcessHeap(), 0, (length + 1) * sizeof(WCHAR));
932 
933  TRACE("\t edit text length %i\n", length );
934 
935  if( pText )
936  {
937  GetWindowTextW( lphc->hWndEdit, pText, length + 1);
939  HeapFree( GetProcessHeap(), 0, pText );
940  }
941 
942  SendMessageW(lphc->hWndLBox, LB_SETCURSEL, (WPARAM)(bSelect ? idx : -1), 0);
943 
944  /* probably superfluous but Windows sends this too */
945  SendMessageW(lphc->hWndLBox, LB_SETCARETINDEX, (WPARAM)(idx < 0 ? 0 : idx), 0);
946  SendMessageW(lphc->hWndLBox, LB_SETTOPINDEX, (WPARAM)(idx < 0 ? 0 : idx), 0);
947 
948  return idx;
949 }
950 
951 /***********************************************************************
952  * CBUpdateEdit
953  *
954  * Copy a listbox entry to the edit control.
955  */
956 static void CBUpdateEdit( LPHEADCOMBO lphc , INT index )
957 {
958  INT length;
959  LPWSTR pText = NULL;
960  static const WCHAR empty_stringW[] = { 0 };
961 
962  TRACE("\t %i\n", index );
963 
964  if( index >= 0 ) /* got an entry */
965  {
967  if( length != LB_ERR)
968  {
969  if( (pText = HeapAlloc( GetProcessHeap(), 0, (length + 1) * sizeof(WCHAR))) )
970  {
972  }
973  }
974  }
975 
976  if( CB_HASSTRINGS(lphc) )
977  {
980  lphc->wState &= ~(CBF_NOEDITNOTIFY | CBF_NOLBSELECT);
981  }
982 
983  if( lphc->wState & CBF_FOCUSED )
984  SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1));
985 
986  HeapFree( GetProcessHeap(), 0, pText );
987 }
988 
989 /***********************************************************************
990  * CBDropDown
991  *
992  * Show listbox popup.
993  */
994 static void CBDropDown( LPHEADCOMBO lphc )
995 {
996  HMONITOR monitor;
997  MONITORINFO mon_info;
998  RECT rect,r;
999  int nItems = 0;
1000  int nDroppedHeight;
1001 
1002  TRACE("[%p]: drop down\n", lphc->self);
1003 
1004  CB_NOTIFY( lphc, CBN_DROPDOWN );
1005 
1006  /* set selection */
1007 
1008  lphc->wState |= CBF_DROPPED;
1009  if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
1010  {
1011  lphc->droppedIndex = CBUpdateLBox( lphc, TRUE );
1012 
1013  /* Update edit only if item is in the list */
1014  if( !(lphc->wState & CBF_CAPTURE) && lphc->droppedIndex >= 0)
1015  CBUpdateEdit( lphc, lphc->droppedIndex );
1016  }
1017  else
1018  {
1019  lphc->droppedIndex = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
1020 
1022  (WPARAM)(lphc->droppedIndex == LB_ERR ? 0 : lphc->droppedIndex), 0 );
1023  SendMessageW(lphc->hWndLBox, LB_CARETON, 0, 0);
1024  }
1025 
1026  /* now set popup position */
1027  GetWindowRect( lphc->self, &rect );
1028 
1029  /*
1030  * If it's a dropdown, the listbox is offset
1031  */
1032  if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
1033  rect.left += COMBO_EDITBUTTONSPACE();
1034 
1035  /* if the dropped height is greater than the total height of the dropped
1036  items list, then force the drop down list height to be the total height
1037  of the items in the dropped list */
1038 
1039  /* And Remove any extra space (Best Fit) */
1040  nDroppedHeight = lphc->droppedRect.bottom - lphc->droppedRect.top;
1041  /* if listbox length has been set directly by its handle */
1042  GetWindowRect(lphc->hWndLBox, &r);
1043  if (nDroppedHeight < r.bottom - r.top)
1044  nDroppedHeight = r.bottom - r.top;
1045  nItems = (int)SendMessageW(lphc->hWndLBox, LB_GETCOUNT, 0, 0);
1046 
1047  if (nItems > 0)
1048  {
1049  int nHeight;
1050  int nIHeight;
1051 
1052  nIHeight = (int)SendMessageW(lphc->hWndLBox, LB_GETITEMHEIGHT, 0, 0);
1053 
1054  nHeight = nIHeight*nItems;
1055 
1056  if (nHeight < nDroppedHeight - COMBO_YBORDERSIZE())
1057  nDroppedHeight = nHeight + COMBO_YBORDERSIZE();
1058 
1059  if (nDroppedHeight < nHeight)
1060  {
1061  if (nItems < 5)
1062  nDroppedHeight = (nItems+1)*nIHeight;
1063  else if (nDroppedHeight < 6*nIHeight)
1064  nDroppedHeight = 6*nIHeight;
1065  }
1066  }
1067 
1068  r.left = rect.left;
1069  r.top = rect.bottom;
1070  r.right = r.left + lphc->droppedRect.right - lphc->droppedRect.left;
1071  r.bottom = r.top + nDroppedHeight;
1072 
1073  /*If height of dropped rectangle gets beyond a screen size it should go up, otherwise down.*/
1074  monitor = MonitorFromRect( &rect, MONITOR_DEFAULTTOPRIMARY );
1075  mon_info.cbSize = sizeof(mon_info);
1076  GetMonitorInfoW( monitor, &mon_info );
1077 
1078  if (r.bottom > mon_info.rcWork.bottom)
1079  {
1080  r.top = max( rect.top - nDroppedHeight, mon_info.rcWork.top );
1081  r.bottom = min( r.top + nDroppedHeight, mon_info.rcWork.bottom );
1082  }
1083 
1084  SetWindowPos( lphc->hWndLBox, HWND_TOPMOST, r.left, r.top, r.right - r.left, r.bottom - r.top,
1086 
1087 
1088  if( !(lphc->wState & CBF_NOREDRAW) )
1089  RedrawWindow( lphc->self, NULL, 0, RDW_INVALIDATE |
1091 
1092  EnableWindow( lphc->hWndLBox, TRUE );
1093  if (GetCapture() != lphc->self)
1094  SetCapture(lphc->hWndLBox);
1095 }
1096 
1097 /***********************************************************************
1098  * CBRollUp
1099  *
1100  * Hide listbox popup.
1101  */
1102 static void CBRollUp( LPHEADCOMBO lphc, BOOL ok, BOOL bButton )
1103 {
1104  HWND hWnd = lphc->self;
1105 
1106  TRACE("[%p]: sel ok? [%i] dropped? [%i]\n",
1107  lphc->self, ok, (INT)(lphc->wState & CBF_DROPPED));
1108 
1109  CB_NOTIFY( lphc, (ok) ? CBN_SELENDOK : CBN_SELENDCANCEL );
1110 
1111  if( IsWindow( hWnd ) && CB_GETTYPE(lphc) != CBS_SIMPLE )
1112  {
1113 
1114  if( lphc->wState & CBF_DROPPED )
1115  {
1116  RECT rect;
1117 
1118  lphc->wState &= ~CBF_DROPPED;
1119  ShowWindow( lphc->hWndLBox, SW_HIDE );
1120 
1121  if(GetCapture() == lphc->hWndLBox)
1122  {
1123  ReleaseCapture();
1124  }
1125 
1126  if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
1127  {
1128  rect = lphc->buttonRect;
1129  }
1130  else
1131  {
1132  if( bButton )
1133  {
1134  UnionRect( &rect,
1135  &lphc->buttonRect,
1136  &lphc->textRect);
1137  }
1138  else
1139  rect = lphc->textRect;
1140 
1141  bButton = TRUE;
1142  }
1143 
1144  if( bButton && !(lphc->wState & CBF_NOREDRAW) )
1147  CB_NOTIFY( lphc, CBN_CLOSEUP );
1148  }
1149  }
1150 }
1151 
1152 /***********************************************************************
1153  * COMBO_FlipListbox
1154  *
1155  * Used by the ComboLBox to show/hide itself in response to VK_F4, etc...
1156  */
1158 {
1159  if( lphc->wState & CBF_DROPPED )
1160  {
1161  CBRollUp( lphc, ok, bRedrawButton );
1162  return FALSE;
1163  }
1164 
1165  CBDropDown( lphc );
1166  return TRUE;
1167 }
1168 
1169 /***********************************************************************
1170  * CBRepaintButton
1171  */
1172 static void CBRepaintButton( LPHEADCOMBO lphc )
1173  {
1174  InvalidateRect(lphc->self, &lphc->buttonRect, TRUE);
1175  UpdateWindow(lphc->self);
1176 }
1177 
1178 /***********************************************************************
1179  * COMBO_SetFocus
1180  */
1181 static void COMBO_SetFocus( LPHEADCOMBO lphc )
1182 {
1183  if( !(lphc->wState & CBF_FOCUSED) )
1184  {
1185  if( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST )
1186  SendMessageW(lphc->hWndLBox, LB_CARETON, 0, 0);
1187 
1188  /* This is wrong. Message sequences seem to indicate that this
1189  is set *after* the notify. */
1190  /* lphc->wState |= CBF_FOCUSED; */
1191 
1192  if( !(lphc->wState & CBF_EDIT) )
1193  InvalidateRect(lphc->self, &lphc->textRect, TRUE);
1194 
1195  CB_NOTIFY( lphc, CBN_SETFOCUS );
1196  lphc->wState |= CBF_FOCUSED;
1197  }
1198 }
1199 
1200 /***********************************************************************
1201  * COMBO_KillFocus
1202  */
1203 static void COMBO_KillFocus( LPHEADCOMBO lphc )
1204 {
1205  HWND hWnd = lphc->self;
1206 
1207  if( lphc->wState & CBF_FOCUSED )
1208  {
1209  CBRollUp( lphc, FALSE, TRUE );
1210  if( IsWindow( hWnd ) )
1211  {
1212  if( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST )
1213  SendMessageW(lphc->hWndLBox, LB_CARETOFF, 0, 0);
1214 
1215  lphc->wState &= ~CBF_FOCUSED;
1216 
1217  /* redraw text */
1218  if( !(lphc->wState & CBF_EDIT) )
1219  InvalidateRect(lphc->self, &lphc->textRect, TRUE);
1220 
1221  CB_NOTIFY( lphc, CBN_KILLFOCUS );
1222  }
1223  }
1224 }
1225 
1226 /***********************************************************************
1227  * COMBO_Command
1228  */
1230 {
1231  if ( lphc->wState & CBF_EDIT && lphc->hWndEdit == hWnd )
1232  {
1233  /* ">> 8" makes gcc generate jump-table instead of cmp ladder */
1234 
1235  switch( HIWORD(wParam) >> 8 )
1236  {
1237  case (EN_SETFOCUS >> 8):
1238 
1239  TRACE("[%p]: edit [%p] got focus\n", lphc->self, lphc->hWndEdit );
1240 
1241  COMBO_SetFocus( lphc );
1242  break;
1243 
1244  case (EN_KILLFOCUS >> 8):
1245 
1246  TRACE("[%p]: edit [%p] lost focus\n", lphc->self, lphc->hWndEdit );
1247 
1248  /* NOTE: it seems that Windows' edit control sends an
1249  * undocumented message WM_USER + 0x1B instead of this
1250  * notification (only when it happens to be a part of
1251  * the combo). ?? - AK.
1252  */
1253 
1254  COMBO_KillFocus( lphc );
1255  break;
1256 
1257 
1258  case (EN_CHANGE >> 8):
1259  /*
1260  * In some circumstances (when the selection of the combobox
1261  * is changed for example) we don't want the EN_CHANGE notification
1262  * to be forwarded to the parent of the combobox. This code
1263  * checks a flag that is set in these occasions and ignores the
1264  * notification.
1265  */
1266  if (lphc->wState & CBF_NOLBSELECT)
1267  {
1268  lphc->wState &= ~CBF_NOLBSELECT;
1269  }
1270  else
1271  {
1272  CBUpdateLBox( lphc, lphc->wState & CBF_DROPPED );
1273  }
1274 
1275  if (!(lphc->wState & CBF_NOEDITNOTIFY))
1276  CB_NOTIFY( lphc, CBN_EDITCHANGE );
1277  break;
1278 
1279  case (EN_UPDATE >> 8):
1280  if (!(lphc->wState & CBF_NOEDITNOTIFY))
1281  CB_NOTIFY( lphc, CBN_EDITUPDATE );
1282  break;
1283 
1284  case (EN_ERRSPACE >> 8):
1285  CB_NOTIFY( lphc, CBN_ERRSPACE );
1286  }
1287  }
1288  else if( lphc->hWndLBox == hWnd )
1289  {
1290  switch( (short)HIWORD(wParam) )
1291  {
1292  case LBN_ERRSPACE:
1293  CB_NOTIFY( lphc, CBN_ERRSPACE );
1294  break;
1295 
1296  case LBN_DBLCLK:
1297  CB_NOTIFY( lphc, CBN_DBLCLK );
1298  break;
1299 
1300  case LBN_SELCHANGE:
1301  case LBN_SELCANCEL:
1302 
1303  TRACE("[%p]: lbox selection change [%x]\n", lphc->self, lphc->wState );
1304 
1305  /* do not roll up if selection is being tracked
1306  * by arrow keys in the dropdown listbox */
1307  if (!(lphc->wState & CBF_NOROLLUP))
1308  {
1309  CBRollUp( lphc, (HIWORD(wParam) == LBN_SELCHANGE), TRUE );
1310  }
1311  else lphc->wState &= ~CBF_NOROLLUP;
1312 
1313  CB_NOTIFY( lphc, CBN_SELCHANGE );
1314 
1315  if( HIWORD(wParam) == LBN_SELCHANGE)
1316  {
1317  if( lphc->wState & CBF_EDIT )
1318  {
1319  INT index = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
1320  lphc->wState |= CBF_NOLBSELECT;
1321  CBUpdateEdit( lphc, index );
1322  /* select text in edit, as Windows does */
1323  SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, (LPARAM)(-1));
1324  }
1325  else
1326  {
1327  InvalidateRect(lphc->self, &lphc->textRect, TRUE);
1328  UpdateWindow(lphc->self);
1329  }
1330  }
1331  break;
1332 
1333  case LBN_SETFOCUS:
1334  case LBN_KILLFOCUS:
1335  /* nothing to do here since ComboLBox always resets the focus to its
1336  * combo/edit counterpart */
1337  break;
1338  }
1339  }
1340  return 0;
1341 }
1342 
1343 /***********************************************************************
1344  * COMBO_ItemOp
1345  *
1346  * Fixup an ownerdrawn item operation and pass it up to the combobox owner.
1347  */
1349 {
1350  HWND hWnd = lphc->self;
1352 
1353  TRACE("[%p]: ownerdraw op %04x\n", lphc->self, msg );
1354 
1355  switch( msg )
1356  {
1357  case WM_DELETEITEM:
1358  {
1360  lpIS->CtlType = ODT_COMBOBOX;
1361  lpIS->CtlID = id;
1362  lpIS->hwndItem = hWnd;
1363  break;
1364  }
1365  case WM_DRAWITEM:
1366  {
1368  lpIS->CtlType = ODT_COMBOBOX;
1369  lpIS->CtlID = id;
1370  lpIS->hwndItem = hWnd;
1371  break;
1372  }
1373  case WM_COMPAREITEM:
1374  {
1376  lpIS->CtlType = ODT_COMBOBOX;
1377  lpIS->CtlID = id;
1378  lpIS->hwndItem = hWnd;
1379  break;
1380  }
1381  case WM_MEASUREITEM:
1382  {
1384  lpIS->CtlType = ODT_COMBOBOX;
1385  lpIS->CtlID = id;
1386  break;
1387  }
1388  }
1389  return SendMessageW(lphc->owner, msg, id, lParam);
1390 }
1391 
1392 
1393 /***********************************************************************
1394  * COMBO_GetTextW
1395  */
1397 {
1398  INT length;
1399 
1400  if( lphc->wState & CBF_EDIT )
1401  return SendMessageW( lphc->hWndEdit, WM_GETTEXT, count, (LPARAM)buf );
1402 
1403  /* get it from the listbox */
1404 
1405  if (!count || !buf) return 0;
1406  if( lphc->hWndLBox )
1407  {
1408  INT idx = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
1409  if (idx == LB_ERR) goto error;
1410  length = SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, idx, 0 );
1411  if (length == LB_ERR) goto error;
1412 
1413  /* 'length' is without the terminating character */
1414  if (length >= count)
1415  {
1416  LPWSTR lpBuffer = HeapAlloc(GetProcessHeap(), 0, (length + 1) * sizeof(WCHAR));
1417  if (!lpBuffer) goto error;
1419 
1420  /* truncate if buffer is too short */
1421  if (length != LB_ERR)
1422  {
1423  lstrcpynW( buf, lpBuffer, count );
1424  length = count;
1425  }
1426  HeapFree( GetProcessHeap(), 0, lpBuffer );
1427  }
1428  else length = SendMessageW(lphc->hWndLBox, LB_GETTEXT, idx, (LPARAM)buf);
1429 
1430  if (length == LB_ERR) return 0;
1431  return length;
1432  }
1433 
1434  error: /* error - truncate string, return zero */
1435  buf[0] = 0;
1436  return 0;
1437 }
1438 
1439 
1440 /***********************************************************************
1441  * COMBO_GetTextA
1442  *
1443  * NOTE! LB_GETTEXT does not count terminating \0, WM_GETTEXT does.
1444  * also LB_GETTEXT might return values < 0, WM_GETTEXT doesn't.
1445  */
1447 {
1448  INT length;
1449 
1450  if( lphc->wState & CBF_EDIT )
1451  return SendMessageA( lphc->hWndEdit, WM_GETTEXT, count, (LPARAM)buf );
1452 
1453  /* get it from the listbox */
1454 
1455  if (!count || !buf) return 0;
1456  if( lphc->hWndLBox )
1457  {
1458  INT idx = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
1459  if (idx == LB_ERR) goto error;
1460  length = SendMessageA(lphc->hWndLBox, LB_GETTEXTLEN, idx, 0 );
1461  if (length == LB_ERR) goto error;
1462 
1463  /* 'length' is without the terminating character */
1464  if (length >= count)
1465  {
1466  LPSTR lpBuffer = HeapAlloc(GetProcessHeap(), 0, (length + 1) );
1467  if (!lpBuffer) goto error;
1469 
1470  /* truncate if buffer is too short */
1471  if (length != LB_ERR)
1472  {
1473  lstrcpynA( buf, lpBuffer, count );
1474  length = count;
1475  }
1476  HeapFree( GetProcessHeap(), 0, lpBuffer );
1477  }
1478  else length = SendMessageA(lphc->hWndLBox, LB_GETTEXT, idx, (LPARAM)buf);
1479 
1480  if (length == LB_ERR) return 0;
1481  return length;
1482  }
1483 
1484  error: /* error - truncate string, return zero */
1485  buf[0] = 0;
1486  return 0;
1487 }
1488 
1489 
1490 /***********************************************************************
1491  * CBResetPos
1492  *
1493  * This function sets window positions according to the updated
1494  * component placement struct.
1495  */
1496 static void CBResetPos(
1497  LPHEADCOMBO lphc,
1498  const RECT *rectEdit,
1499  const RECT *rectLB,
1500  BOOL bRedraw)
1501 {
1502  BOOL bDrop = (CB_GETTYPE(lphc) != CBS_SIMPLE);
1503 
1504  /* NOTE: logs sometimes have WM_LBUTTONUP before a cascade of
1505  * sizing messages */
1506 
1507  if( lphc->wState & CBF_EDIT )
1508  SetWindowPos( lphc->hWndEdit, 0,
1509  rectEdit->left, rectEdit->top,
1510  rectEdit->right - rectEdit->left,
1511  rectEdit->bottom - rectEdit->top,
1512  SWP_NOZORDER | SWP_NOACTIVATE | ((bDrop) ? SWP_NOREDRAW : 0) );
1513 
1514  SetWindowPos( lphc->hWndLBox, 0,
1515  rectLB->left, rectLB->top,
1516  rectLB->right - rectLB->left,
1517  rectLB->bottom - rectLB->top,
1518  SWP_NOACTIVATE | SWP_NOZORDER | ((bDrop) ? SWP_NOREDRAW : 0) );
1519 
1520  if( bDrop )
1521  {
1522  if( lphc->wState & CBF_DROPPED )
1523  {
1524  lphc->wState &= ~CBF_DROPPED;
1525  ShowWindow( lphc->hWndLBox, SW_HIDE );
1526  }
1527 
1528  if( bRedraw && !(lphc->wState & CBF_NOREDRAW) )
1529  RedrawWindow( lphc->self, NULL, 0,
1531  }
1532 }
1533 
1534 
1535 /***********************************************************************
1536  * COMBO_Size
1537  */
1538 static void COMBO_Size( LPHEADCOMBO lphc )
1539 {
1540  /*
1541  * Those controls are always the same height. So we have to make sure
1542  * they are not resized to another value.
1543  */
1544  if( CB_GETTYPE(lphc) != CBS_SIMPLE )
1545  {
1546  int newComboHeight, curComboHeight, curComboWidth;
1547  RECT rc;
1548 
1549  GetWindowRect(lphc->self, &rc);
1550  curComboHeight = rc.bottom - rc.top;
1551  curComboWidth = rc.right - rc.left;
1552  newComboHeight = CBGetTextAreaHeight(lphc->self, lphc) + 2*COMBO_YBORDERSIZE();
1553 
1554  /*
1555  * Resizing a combobox has another side effect, it resizes the dropped
1556  * rectangle as well. However, it does it only if the new height for the
1557  * combobox is more than the height it should have. In other words,
1558  * if the application resizing the combobox only had the intention to resize
1559  * the actual control, for example, to do the layout of a dialog that is
1560  * resized, the height of the dropdown is not changed.
1561  */
1562  if( curComboHeight > newComboHeight )
1563  {
1564  TRACE("oldComboHeight=%d, newComboHeight=%d, oldDropBottom=%d, oldDropTop=%d\n",
1565  curComboHeight, newComboHeight, lphc->droppedRect.bottom,
1566  lphc->droppedRect.top);
1567  lphc->droppedRect.bottom = lphc->droppedRect.top + curComboHeight - newComboHeight;
1568  }
1569  /*
1570  * Restore original height
1571  */
1572  if( curComboHeight != newComboHeight )
1573  SetWindowPos(lphc->self, 0, 0, 0, curComboWidth, newComboHeight,
1575  }
1576 
1577  CBCalcPlacement(lphc->self,
1578  lphc,
1579  &lphc->textRect,
1580  &lphc->buttonRect,
1581  &lphc->droppedRect);
1582 
1583  CBResetPos( lphc, &lphc->textRect, &lphc->droppedRect, TRUE );
1584 }
1585 
1586 
1587 /***********************************************************************
1588  * COMBO_Font
1589  */
1590 static void COMBO_Font( LPHEADCOMBO lphc, HFONT hFont, BOOL bRedraw )
1591 {
1592  /*
1593  * Set the font
1594  */
1595  lphc->hFont = hFont;
1596 
1597  /*
1598  * Propagate to owned windows.
1599  */
1600  if( lphc->wState & CBF_EDIT )
1601  SendMessageW(lphc->hWndEdit, WM_SETFONT, (WPARAM)hFont, bRedraw);
1602  SendMessageW(lphc->hWndLBox, WM_SETFONT, (WPARAM)hFont, bRedraw);
1603 
1604  /*
1605  * Redo the layout of the control.
1606  */
1607  if ( CB_GETTYPE(lphc) == CBS_SIMPLE)
1608  {
1609  CBCalcPlacement(lphc->self,
1610  lphc,
1611  &lphc->textRect,
1612  &lphc->buttonRect,
1613  &lphc->droppedRect);
1614 
1615  CBResetPos( lphc, &lphc->textRect, &lphc->droppedRect, TRUE );
1616  }
1617  else
1618  {
1619  CBForceDummyResize(lphc);
1620  }
1621 }
1622 
1623 
1624 /***********************************************************************
1625  * COMBO_SetItemHeight
1626  */
1628 {
1629  LRESULT lRet = CB_ERR;
1630 
1631  if( index == -1 ) /* set text field height */
1632  {
1633  if( height < 32768 )
1634  {
1635  lphc->editHeight = height + 2; /* Is the 2 for 2*EDIT_CONTROL_PADDING? */
1636 
1637  /*
1638  * Redo the layout of the control.
1639  */
1640  if ( CB_GETTYPE(lphc) == CBS_SIMPLE)
1641  {
1642  CBCalcPlacement(lphc->self,
1643  lphc,
1644  &lphc->textRect,
1645  &lphc->buttonRect,
1646  &lphc->droppedRect);
1647 
1648  CBResetPos( lphc, &lphc->textRect, &lphc->droppedRect, TRUE );
1649  }
1650  else
1651  {
1652  CBForceDummyResize(lphc);
1653  }
1654 
1655  lRet = height;
1656  }
1657  }
1658  else if ( CB_OWNERDRAWN(lphc) ) /* set listbox item height */
1660  return lRet;
1661 }
1662 
1663 /***********************************************************************
1664  * COMBO_SelectString
1665  */
1667 {
1668  INT index = unicode ? SendMessageW(lphc->hWndLBox, LB_SELECTSTRING, (WPARAM)start, pText) :
1670  if( index >= 0 )
1671  {
1672  if( lphc->wState & CBF_EDIT )
1673  CBUpdateEdit( lphc, index );
1674  else
1675  {
1676  InvalidateRect(lphc->self, &lphc->textRect, TRUE);
1677  }
1678  }
1679  return (LRESULT)index;
1680 }
1681 
1682 /***********************************************************************
1683  * COMBO_LButtonDown
1684  */
1686 {
1687  POINT pt;
1688  BOOL bButton;
1689  HWND hWnd = lphc->self;
1690 
1691  pt.x = (short)LOWORD(lParam);
1692  pt.y = (short)HIWORD(lParam);
1693  bButton = PtInRect(&lphc->buttonRect, pt);
1694 
1695  if( (CB_GETTYPE(lphc) == CBS_DROPDOWNLIST) ||
1696  (bButton && (CB_GETTYPE(lphc) == CBS_DROPDOWN)) )
1697  {
1698  lphc->wState |= CBF_BUTTONDOWN;
1699  if( lphc->wState & CBF_DROPPED )
1700  {
1701  /* got a click to cancel selection */
1702 
1703  lphc->wState &= ~CBF_BUTTONDOWN;
1704  CBRollUp( lphc, TRUE, FALSE );
1705  if( !IsWindow( hWnd ) ) return;
1706 
1707  if( lphc->wState & CBF_CAPTURE )
1708  {
1709  lphc->wState &= ~CBF_CAPTURE;
1710  ReleaseCapture();
1711  }
1712  }
1713  else
1714  {
1715  /* drop down the listbox and start tracking */
1716 
1717  lphc->wState |= CBF_CAPTURE;
1718  SetCapture( hWnd );
1719  CBDropDown( lphc );
1720  }
1721  if( bButton ) CBRepaintButton( lphc );
1722  }
1723 }
1724 
1725 /***********************************************************************
1726  * COMBO_LButtonUp
1727  *
1728  * Release capture and stop tracking if needed.
1729  */
1730 static void COMBO_LButtonUp( LPHEADCOMBO lphc )
1731 {
1732  if( lphc->wState & CBF_CAPTURE )
1733  {
1734  lphc->wState &= ~CBF_CAPTURE;
1735  if( CB_GETTYPE(lphc) == CBS_DROPDOWN )
1736  {
1737  INT index = CBUpdateLBox( lphc, TRUE );
1738  /* Update edit only if item is in the list */
1739  if(index >= 0)
1740  {
1741  lphc->wState |= CBF_NOLBSELECT;
1742  CBUpdateEdit( lphc, index );
1743  lphc->wState &= ~CBF_NOLBSELECT;
1744  }
1745  }
1746  ReleaseCapture();
1747  SetCapture(lphc->hWndLBox);
1748  }
1749 
1750  if( lphc->wState & CBF_BUTTONDOWN )
1751  {
1752  lphc->wState &= ~CBF_BUTTONDOWN;
1753  CBRepaintButton( lphc );
1754  }
1755 }
1756 
1757 /***********************************************************************
1758  * COMBO_MouseMove
1759  *
1760  * Two things to do - track combo button and release capture when
1761  * pointer goes into the listbox.
1762  */
1764 {
1765  POINT pt;
1766  RECT lbRect;
1767 
1768  pt.x = (short)LOWORD(lParam);
1769  pt.y = (short)HIWORD(lParam);
1770 
1771  if( lphc->wState & CBF_BUTTONDOWN )
1772  {
1773  BOOL bButton;
1774 
1775  bButton = PtInRect(&lphc->buttonRect, pt);
1776 
1777  if( !bButton )
1778  {
1779  lphc->wState &= ~CBF_BUTTONDOWN;
1780  CBRepaintButton( lphc );
1781  }
1782  }
1783 
1784  GetClientRect( lphc->hWndLBox, &lbRect );
1785  MapWindowPoints( lphc->self, lphc->hWndLBox, &pt, 1 );
1786  if( PtInRect(&lbRect, pt) )
1787  {
1788  lphc->wState &= ~CBF_CAPTURE;
1789  ReleaseCapture();
1790  if( CB_GETTYPE(lphc) == CBS_DROPDOWN ) CBUpdateLBox( lphc, TRUE );
1791 
1792  /* hand over pointer tracking */
1794  }
1795 }
1796 
1798 {
1799  if (!pcbi || (pcbi->cbSize < sizeof(COMBOBOXINFO)))
1800  return FALSE;
1801 
1802  pcbi->rcItem = lphc->textRect;
1803  pcbi->rcButton = lphc->buttonRect;
1804  pcbi->stateButton = 0;
1805  if (lphc->wState & CBF_BUTTONDOWN)
1807  if (IsRectEmpty(&lphc->buttonRect))
1809  pcbi->hwndCombo = lphc->self;
1810  pcbi->hwndItem = lphc->hWndEdit;
1811  pcbi->hwndList = lphc->hWndLBox;
1812  return TRUE;
1813 }
1814 
1815 static char *strdupA(LPCSTR str)
1816 {
1817  char *ret;
1818  DWORD len;
1819 
1820  if(!str) return NULL;
1821 
1822  len = strlen(str);
1823  ret = HeapAlloc(GetProcessHeap(), 0, len + 1);
1824 #ifdef __REACTOS__
1825  if (ret != NULL)
1826 #endif
1827  memcpy(ret, str, len + 1);
1828  return ret;
1829 }
1830 
1831 /***********************************************************************
1832  * ComboWndProc_common
1833  */
1835 {
1837 #ifdef __REACTOS__
1838  PWND pWnd;
1839 
1840  pWnd = ValidateHwnd(hwnd);
1841  if (pWnd)
1842  {
1843  if (!pWnd->fnid)
1844  {
1846  }
1847  else
1848  {
1849  if (pWnd->fnid != FNID_COMBOBOX)
1850  {
1851  ERR("Wrong window class for ComboBox! fnId 0x%x\n",pWnd->fnid);
1852  return 0;
1853  }
1854  }
1855  }
1856 #endif
1857 
1858  TRACE("[%p]: msg %s wp %08lx lp %08lx\n",
1860 
1861 #ifndef __REACTOS__
1862  if (!IsWindow(hwnd)) return 0;
1863 #endif
1864 
1865  if( lphc || message == WM_NCCREATE )
1866  switch(message)
1867  {
1868 
1869  /* System messages */
1870 
1871  case WM_NCCREATE:
1872  {
1873  LONG style = unicode ? ((LPCREATESTRUCTW)lParam)->style :
1874  ((LPCREATESTRUCTA)lParam)->style;
1875  return COMBO_NCCreate(hwnd, style);
1876  }
1877  case WM_NCDESTROY:
1878  COMBO_NCDestroy(lphc);
1879 #ifdef __REACTOS__
1881 #endif
1882  break;/* -> DefWindowProc */
1883 
1884  case WM_CREATE:
1885  {
1886  HWND hwndParent;
1887  LONG style;
1888  if(unicode)
1889  {
1890  hwndParent = ((LPCREATESTRUCTW)lParam)->hwndParent;
1891  style = ((LPCREATESTRUCTW)lParam)->style;
1892  }
1893  else
1894  {
1895  hwndParent = ((LPCREATESTRUCTA)lParam)->hwndParent;
1896  style = ((LPCREATESTRUCTA)lParam)->style;
1897  }
1898  return COMBO_Create(hwnd, lphc, hwndParent, style, unicode);
1899  }
1900 
1901  case WM_PRINTCLIENT:
1902  /* Fallthrough */
1903  case WM_PAINT:
1904  /* wParam may contain a valid HDC! */
1905  return COMBO_Paint(lphc, (HDC)wParam);
1906 
1907  case WM_ERASEBKGND:
1908  /* do all painting in WM_PAINT like Windows does */
1909  return 1;
1910 
1911  case WM_GETDLGCODE:
1912  {
1914  if (lParam && (((LPMSG)lParam)->message == WM_KEYDOWN))
1915  {
1916  int vk = (int)((LPMSG)lParam)->wParam;
1917 
1918  if ((vk == VK_RETURN || vk == VK_ESCAPE) && (lphc->wState & CBF_DROPPED))
1920  }
1921  return result;
1922  }
1923  case WM_SIZE:
1924  if( lphc->hWndLBox &&
1925  !(lphc->wState & CBF_NORESIZE) ) COMBO_Size( lphc );
1926  return TRUE;
1927  case WM_SETFONT:
1928  COMBO_Font( lphc, (HFONT)wParam, (BOOL)lParam );
1929  return TRUE;
1930  case WM_GETFONT:
1931  return (LRESULT)lphc->hFont;
1932  case WM_SETFOCUS:
1933  if( lphc->wState & CBF_EDIT ) {
1934  SetFocus( lphc->hWndEdit );
1935  /* The first time focus is received, select all the text */
1936  if( !(lphc->wState & CBF_BEENFOCUSED) ) {
1937  SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, -1);
1938  lphc->wState |= CBF_BEENFOCUSED;
1939  }
1940  }
1941  else
1942  COMBO_SetFocus( lphc );
1943  return TRUE;
1944  case WM_KILLFOCUS:
1945  {
1946  HWND hwndFocus = WIN_GetFullHandle( (HWND)wParam );
1947  if( !hwndFocus ||
1948  (hwndFocus != lphc->hWndEdit && hwndFocus != lphc->hWndLBox ))
1949  COMBO_KillFocus( lphc );
1950  return TRUE;
1951  }
1952  case WM_COMMAND:
1953  return COMBO_Command( lphc, wParam, WIN_GetFullHandle( (HWND)lParam ) );
1954  case WM_GETTEXT:
1955  return unicode ? COMBO_GetTextW( lphc, wParam, (LPWSTR)lParam )
1956  : COMBO_GetTextA( lphc, wParam, (LPSTR)lParam );
1957  case WM_SETTEXT:
1958  case WM_GETTEXTLENGTH:
1959  case WM_CLEAR:
1960  if ((message == WM_GETTEXTLENGTH) && !ISWIN31 && !(lphc->wState & CBF_EDIT))
1961  {
1962  int j = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
1963  if (j == -1) return 0;
1964  return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, j, 0) :
1965  SendMessageA(lphc->hWndLBox, LB_GETTEXTLEN, j, 0);
1966  }
1967  else if( lphc->wState & CBF_EDIT )
1968  {
1969  LRESULT ret;
1970  lphc->wState |= CBF_NOEDITNOTIFY;
1971  ret = unicode ? SendMessageW(lphc->hWndEdit, message, wParam, lParam) :
1973  lphc->wState &= ~CBF_NOEDITNOTIFY;
1974  return ret;
1975  }
1976  else return CB_ERR;
1977  case WM_CUT:
1978  case WM_PASTE:
1979  case WM_COPY:
1980  if( lphc->wState & CBF_EDIT )
1981  {
1982  return unicode ? SendMessageW(lphc->hWndEdit, message, wParam, lParam) :
1984  }
1985  else return CB_ERR;
1986 
1987  case WM_DRAWITEM:
1988  case WM_DELETEITEM:
1989  case WM_COMPAREITEM:
1990  case WM_MEASUREITEM:
1991  return COMBO_ItemOp(lphc, message, lParam);
1992  case WM_ENABLE:
1993  if( lphc->wState & CBF_EDIT )
1994  EnableWindow( lphc->hWndEdit, (BOOL)wParam );
1995  EnableWindow( lphc->hWndLBox, (BOOL)wParam );
1996 
1997  /* Force the control to repaint when the enabled state changes. */
1998  InvalidateRect(lphc->self, NULL, TRUE);
1999  return TRUE;
2000  case WM_SETREDRAW:
2001  if( wParam )
2002  lphc->wState &= ~CBF_NOREDRAW;
2003  else
2004  lphc->wState |= CBF_NOREDRAW;
2005 
2006  if( lphc->wState & CBF_EDIT )
2009  return 0;
2010  case WM_SYSKEYDOWN:
2011 #ifdef __REACTOS__
2012  if( KF_ALTDOWN & HIWORD(lParam) )
2013 #else
2014  if( KEYDATA_ALT & HIWORD(lParam) )
2015 #endif
2016  if( wParam == VK_UP || wParam == VK_DOWN )
2017  COMBO_FlipListbox( lphc, FALSE, FALSE );
2018  return 0;
2019 
2020  case WM_KEYDOWN:
2021  if ((wParam == VK_RETURN || wParam == VK_ESCAPE) &&
2022  (lphc->wState & CBF_DROPPED))
2023  {
2024  CBRollUp( lphc, wParam == VK_RETURN, FALSE );
2025  return TRUE;
2026  }
2027  else if ((wParam == VK_F4) && !(lphc->wState & CBF_EUI))
2028  {
2029  COMBO_FlipListbox( lphc, FALSE, FALSE );
2030  return TRUE;
2031  }
2032  /* fall through */
2033  case WM_CHAR:
2034  case WM_IME_CHAR:
2035  {
2036  HWND hwndTarget;
2037 
2038  if( lphc->wState & CBF_EDIT )
2039  hwndTarget = lphc->hWndEdit;
2040  else
2041  hwndTarget = lphc->hWndLBox;
2042 
2043  return unicode ? SendMessageW(hwndTarget, message, wParam, lParam) :
2044  SendMessageA(hwndTarget, message, wParam, lParam);
2045  }
2046  case WM_LBUTTONDOWN:
2047  if( !(lphc->wState & CBF_FOCUSED) ) SetFocus( lphc->self );
2048  if( lphc->wState & CBF_FOCUSED ) COMBO_LButtonDown( lphc, lParam );
2049  return TRUE;
2050  case WM_LBUTTONUP:
2051  COMBO_LButtonUp( lphc );
2052  return TRUE;
2053  case WM_MOUSEMOVE:
2054  if( lphc->wState & CBF_CAPTURE )
2055  COMBO_MouseMove( lphc, wParam, lParam );
2056  return TRUE;
2057 
2058  case WM_MOUSEWHEEL:
2059  if (wParam & (MK_SHIFT | MK_CONTROL))
2060  return unicode ? DefWindowProcW(hwnd, message, wParam, lParam) :
2062 
2063  if (GET_WHEEL_DELTA_WPARAM(wParam) > 0) return SendMessageW(hwnd, WM_KEYDOWN, VK_UP, 0);
2064  if (GET_WHEEL_DELTA_WPARAM(wParam) < 0) return SendMessageW(hwnd, WM_KEYDOWN, VK_DOWN, 0);
2065  return TRUE;
2066 
2067  /* Combo messages */
2068 
2069  case CB_ADDSTRING:
2070  if( unicode )
2071  {
2072  if( lphc->dwStyle & CBS_LOWERCASE )
2074  else if( lphc->dwStyle & CBS_UPPERCASE )
2076  return SendMessageW(lphc->hWndLBox, LB_ADDSTRING, 0, lParam);
2077  }
2078  else /* unlike the unicode version, the ansi version does not overwrite
2079  the string if converting case */
2080  {
2081  char *string = NULL;
2082  LRESULT ret;
2083  if( lphc->dwStyle & CBS_LOWERCASE )
2084  {
2085  string = strdupA((LPSTR)lParam);
2086  CharLowerA(string);
2087  }
2088 
2089  else if( lphc->dwStyle & CBS_UPPERCASE )
2090  {
2091  string = strdupA((LPSTR)lParam);
2092  CharUpperA(string);
2093  }
2094 
2095  ret = SendMessageA(lphc->hWndLBox, LB_ADDSTRING, 0, string ? (LPARAM)string : lParam);
2096  HeapFree(GetProcessHeap(), 0, string);
2097  return ret;
2098  }
2099  case CB_INSERTSTRING:
2100  if( unicode )
2101  {
2102  if( lphc->dwStyle & CBS_LOWERCASE )
2104  else if( lphc->dwStyle & CBS_UPPERCASE )
2107  }
2108  else
2109  {
2110  if( lphc->dwStyle & CBS_LOWERCASE )
2112  else if( lphc->dwStyle & CBS_UPPERCASE )
2114 
2116  }
2117  case CB_DELETESTRING:
2118  return unicode ? SendMessageW(lphc->hWndLBox, LB_DELETESTRING, wParam, 0) :
2120  case CB_SELECTSTRING:
2121  return COMBO_SelectString(lphc, (INT)wParam, lParam, unicode);
2122  case CB_FINDSTRING:
2123  return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam) :
2125  case CB_FINDSTRINGEXACT:
2126  return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam) :
2128  case CB_SETITEMHEIGHT:
2129  return COMBO_SetItemHeight( lphc, (INT)wParam, (INT)lParam);
2130  case CB_GETITEMHEIGHT:
2131  if( (INT)wParam >= 0 ) /* listbox item */
2132  return SendMessageW(lphc->hWndLBox, LB_GETITEMHEIGHT, wParam, 0);
2133  return CBGetTextAreaHeight(hwnd, lphc);
2134  case CB_RESETCONTENT:
2135  SendMessageW(lphc->hWndLBox, LB_RESETCONTENT, 0, 0);
2136  if( (lphc->wState & CBF_EDIT) && CB_HASSTRINGS(lphc) )
2137  {
2138  static const WCHAR empty_stringW[] = { 0 };
2140  }
2141  else
2142  InvalidateRect(lphc->self, NULL, TRUE);
2143  return TRUE;
2144  case CB_INITSTORAGE:
2147  return SendMessageW(lphc->hWndLBox, LB_GETHORIZONTALEXTENT, 0, 0);
2150  case CB_GETTOPINDEX:
2151  return SendMessageW(lphc->hWndLBox, LB_GETTOPINDEX, 0, 0);
2152  case CB_GETLOCALE:
2153  return SendMessageW(lphc->hWndLBox, LB_GETLOCALE, 0, 0);
2154  case CB_SETLOCALE:
2155  return SendMessageW(lphc->hWndLBox, LB_SETLOCALE, wParam, 0);
2156  case CB_SETDROPPEDWIDTH:
2157  if( (CB_GETTYPE(lphc) == CBS_SIMPLE) ||
2158  (INT)wParam >= 32768 )
2159  return CB_ERR;
2160  /* new value must be higher than combobox width */
2161  if((INT)wParam >= lphc->droppedRect.right - lphc->droppedRect.left)
2162  lphc->droppedWidth = wParam;
2163  else if(wParam)
2164  lphc->droppedWidth = 0;
2165 
2166  /* recalculate the combobox area */
2167  CBCalcPlacement(hwnd, lphc, &lphc->textRect, &lphc->buttonRect, &lphc->droppedRect );
2168 
2169  /* fall through */
2170  case CB_GETDROPPEDWIDTH:
2171  if( lphc->droppedWidth )
2172  return lphc->droppedWidth;
2173  return lphc->droppedRect.right - lphc->droppedRect.left;
2176  return CB_OKAY;
2177  case CB_GETDROPPEDSTATE:
2178  return (lphc->wState & CBF_DROPPED) != 0;
2179  case CB_DIR:
2180  return unicode ? SendMessageW(lphc->hWndLBox, LB_DIR, wParam, lParam) :
2182 
2183  case CB_SHOWDROPDOWN:
2184  if( CB_GETTYPE(lphc) != CBS_SIMPLE )
2185  {
2186  if( wParam )
2187  {
2188  if( !(lphc->wState & CBF_DROPPED) )
2189  CBDropDown( lphc );
2190  }
2191  else
2192  if( lphc->wState & CBF_DROPPED )
2193  CBRollUp( lphc, FALSE, TRUE );
2194  }
2195  return TRUE;
2196  case CB_GETCOUNT:
2197  return SendMessageW(lphc->hWndLBox, LB_GETCOUNT, 0, 0);
2198  case CB_GETCURSEL:
2199  return SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
2200  case CB_SETCURSEL:
2202  if( lParam >= 0 )
2204 
2205  /* no LBN_SELCHANGE in this case, update manually */
2206  if( lphc->wState & CBF_EDIT )
2207  CBUpdateEdit( lphc, (INT)wParam );
2208  else
2209  InvalidateRect(lphc->self, &lphc->textRect, TRUE);
2210  lphc->wState &= ~CBF_SELCHANGE;
2211  return lParam;
2212  case CB_GETLBTEXT:
2213  return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXT, wParam, lParam) :
2215  case CB_GETLBTEXTLEN:
2216  return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, wParam, 0) :
2218  case CB_GETITEMDATA:
2219  return SendMessageW(lphc->hWndLBox, LB_GETITEMDATA, wParam, 0);
2220  case CB_SETITEMDATA:
2222  case CB_GETEDITSEL:
2223  /* Edit checks passed parameters itself */
2224  if( lphc->wState & CBF_EDIT )
2225  return SendMessageW(lphc->hWndEdit, EM_GETSEL, wParam, lParam);
2226  return CB_ERR;
2227  case CB_SETEDITSEL:
2228  if( lphc->wState & CBF_EDIT )
2229  return SendMessageW(lphc->hWndEdit, EM_SETSEL,
2231  return CB_ERR;
2232  case CB_SETEXTENDEDUI:
2233  if( CB_GETTYPE(lphc) == CBS_SIMPLE )
2234  return CB_ERR;
2235  if( wParam )
2236  lphc->wState |= CBF_EUI;
2237  else lphc->wState &= ~CBF_EUI;
2238  return CB_OKAY;
2239  case CB_GETEXTENDEDUI:
2240  return (lphc->wState & CBF_EUI) != 0;
2241  case CB_GETCOMBOBOXINFO:
2242  return COMBO_GetComboBoxInfo(lphc, (COMBOBOXINFO *)lParam);
2243  case CB_LIMITTEXT:
2244  if( lphc->wState & CBF_EDIT )
2245  return SendMessageW(lphc->hWndEdit, EM_LIMITTEXT, wParam, lParam);
2246  return TRUE;
2247 
2248 #ifdef __REACTOS__
2249  case WM_UPDATEUISTATE:
2250  if (unicode)
2252  else
2254 
2255  if (COMBO_update_uistate(lphc))
2256  {
2257  /* redraw text */
2258  if( !(lphc->wState & CBF_EDIT) )
2259  NtUserInvalidateRect(lphc->self, &lphc->textRect, TRUE);
2260  }
2261  break;
2262 
2263  case WM_CBLOSTTEXTFOCUS: /* undocumented message - deselects the text when focus is lost */
2264  if (lphc->hWndEdit != NULL)
2265  {
2266  SendMessage(lphc->self, WM_LBUTTONUP, 0, 0xFFFFFFFF);
2267  SendMessage(lphc->hWndEdit, EM_SETSEL, 0, 0);
2268  lphc->wState &= ~(CBF_FOCUSED | CBF_BEENFOCUSED);
2269  CB_NOTIFY(lphc, CBN_KILLFOCUS);
2270  }
2271  return TRUE;
2272 
2273 #endif
2274 
2275  default:
2276  if (message >= WM_USER)
2277  WARN("unknown msg WM_USER+%04x wp=%04lx lp=%08lx\n",
2278  message - WM_USER, wParam, lParam );
2279  break;
2280  }
2281  return unicode ? DefWindowProcW(hwnd, message, wParam, lParam) :
2283 }
2284 
2285 #ifdef __REACTOS__
2286 
2287 /***********************************************************************
2288  * ComboWndProcA
2289  *
2290  * This is just a wrapper for the real ComboWndProc which locks/unlocks
2291  * window structs.
2292  */
2294 {
2295  if (!IsWindow(hwnd)) return 0;
2297 }
2298 
2299 /***********************************************************************
2300  * ComboWndProcW
2301  */
2303 {
2304  if (!IsWindow(hwnd)) return 0;
2306 }
2307 
2308 #endif /* __REACTOS__ */
2309 
2310 /*************************************************************************
2311  * GetComboBoxInfo (USER32.@)
2312  */
2313 BOOL WINAPI GetComboBoxInfo(HWND hwndCombo, /* [in] handle to combo box */
2314  PCOMBOBOXINFO pcbi /* [in/out] combo box information */)
2315 {
2316  TRACE("(%p, %p)\n", hwndCombo, pcbi);
2317 #ifdef __REACTOS__
2318  return NtUserGetComboBoxInfo(hwndCombo, pcbi);
2319 #else
2320  return SendMessageW(hwndCombo, CB_GETCOMBOBOXINFO, 0, (LPARAM)pcbi);
2321 #endif
2322 }
#define CBS_OWNERDRAWFIXED
Definition: winuser.h:289
#define EM_LIMITTEXT
Definition: winuser.h:1961
#define CB_GETTOPINDEX
Definition: winuser.h:1916
#define WS_CLIPSIBLINGS
Definition: pedump.c:618
#define EDIT_CONTROL_PADDING()
Definition: combo.c:72
#define RDW_NOCHILDREN
Definition: winuser.h:1208
#define LB_SETCURSEL
Definition: winuser.h:2024
#define WM_GETTEXTLENGTH
Definition: winuser.h:1601
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 WS_DISABLED
Definition: pedump.c:621
#define CBS_SORT
Definition: winuser.h:292
#define CBN_SETFOCUS
Definition: winuser.h:1943
#define CB_SETITEMDATA
Definition: winuser.h:1927
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
static INT CBGetTextAreaHeight(HWND hwnd, LPHEADCOMBO lphc)
Definition: combo.c:213
static void COMBO_KillFocus(LPHEADCOMBO lphc)
Definition: combo.c:1203
BOOL WINAPI RedrawWindow(_In_opt_ HWND, _In_opt_ LPCRECT, _In_opt_ HRGN, _In_ UINT)
#define LB_SETLOCALE
Definition: winuser.h:2028
#define max(a, b)
Definition: svc.c:63
static void CBPaintButton(LPHEADCOMBO lphc, HDC hdc, RECT rectButton)
Definition: combo.c:637
BOOL WINAPI InflateRect(_Inout_ LPRECT, _In_ int, _In_ int)
Definition: tftpd.h:59
#define CB_GETLBTEXTLEN
Definition: winuser.h:1914
#define LB_CARETON
Definition: undocuser.h:50
#define TRUE
Definition: types.h:120
#define DLGC_WANTCHARS
Definition: winuser.h:2572
#define COLOR_HIGHLIGHT
Definition: winuser.h:916
static void COMBO_Font(LPHEADCOMBO lphc, HFONT hFont, BOOL bRedraw)
Definition: combo.c:1590
#define LB_DIR
Definition: winuser.h:1994
#define FNID_COMBOBOX
Definition: ntuser.h:829
#define DLGC_WANTMESSAGE
Definition: winuser.h:2567
#define LB_SETCARETINDEX
Definition: winuser.h:2021
BOOL WINAPI GetTextMetricsW(_In_ HDC, _Out_ LPTEXTMETRICW)
Definition: text.c:221
#define MK_SHIFT
Definition: winuser.h:2323
#define CB_GETDROPPEDSTATE
Definition: winuser.h:1906
LPCSTR pText
Definition: txtscale.cpp:79
#define LB_FINDSTRINGEXACT
Definition: winuser.h:1996
int WINAPI SelectClipRgn(_In_ HDC, _In_opt_ HRGN)
#define WM_GETDLGCODE
Definition: winuser.h:1671
#define ODT_COMBOBOX
Definition: winuser.h:2493
int WINAPI MapWindowPoints(_In_opt_ HWND hWndFrom, _In_opt_ HWND hWndTo, _Inout_updates_(cPoints) LPPOINT lpPoints, _In_ UINT cPoints)
#define WM_CHAR
Definition: winuser.h:1693
#define WM_LBUTTONDOWN
Definition: winuser.h:1752
#define LB_SETHORIZONTALEXTENT
Definition: winuser.h:2025
#define WM_CUT
Definition: winuser.h:1822
#define error(str)
Definition: mkdosfs.c:1605
#define WM_IME_CHAR
Definition: winuser.h:1810
#define LB_ADDSTRING
Definition: winuser.h:1992
BOOL WINAPI IsWindow(_In_opt_ HWND)
#define LB_GETHORIZONTALEXTENT
Definition: winuser.h:2001
static void CBCalcPlacement(HWND hwnd, LPHEADCOMBO lphc, LPRECT lprEdit, LPRECT lprButton, LPRECT lprLB)
Definition: combo.c:339
HDC WINAPI GetDC(_In_opt_ HWND)
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define CB_SETDROPPEDWIDTH
Definition: winuser.h:1923
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
INT editHeight
Definition: comctl32.h:149
#define CB_SETHORIZONTALEXTENT
Definition: winuser.h:1926
#define pt(x, y)
Definition: drawing.c:79
#define CB_GETLBTEXT
Definition: winuser.h:1913
#define SW_HIDE
Definition: winuser.h:762
HWND WINAPI SetParent(_In_ HWND, _In_opt_ HWND)
LRESULT WINAPI SendMessageA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define WM_MOUSEWHEEL
Definition: treelist.c:96
#define LB_GETITEMDATA
Definition: winuser.h:2002
#define CB_GETITEMDATA
Definition: winuser.h:1911
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define LBS_HASSTRINGS
Definition: pedump.c:684
#define WM_CTLCOLORSTATIC
Definition: winuser.h:1748
static void CBPaintBorder(HWND hwnd, const HEADCOMBO *lphc, HDC hdc)
Definition: combo.c:782
UINT wState
Definition: comctl32.h:141
#define WM_GETTEXT
Definition: winuser.h:1600
#define WARN(fmt,...)
Definition: debug.h:111
LPWSTR WINAPI CharLowerW(_Inout_ LPWSTR)
static LRESULT COMBO_Create(HWND hwnd, LPHEADCOMBO lphc, HWND hwndParent, LONG style, BOOL unicode)
Definition: combo.c:464
BOOL WINAPI DrawFocusRect(_In_ HDC, _In_ LPCRECT)
#define LBN_SETFOCUS
Definition: winuser.h:2037
static HDC
Definition: imagelist.c:92
#define DFCS_INACTIVE
Definition: winuser.h:502
#define WM_SETREDRAW
Definition: winuser.h:1598
static LRESULT COMBO_GetTextW(LPHEADCOMBO lphc, INT count, LPWSTR buf)
Definition: combo.c:1396
BOOL WINAPI UpdateWindow(_In_ HWND)
HWND hWnd
Definition: settings.c:17
ULONG_PTR itemData
Definition: winuser.h:3046
LONG top
Definition: windef.h:292
HWND hWndEdit
Definition: comctl32.h:139
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
#define ODS_FOCUS
Definition: winuser.h:2503
#define WM_PASTE
Definition: winuser.h:1824
#define ES_COMBO
Definition: edit.c:29
#define LBS_SORT
Definition: pedump.c:679
RECT droppedRect
Definition: comctl32.h:145
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
#define CS_HREDRAW
Definition: winuser.h:648
#define GWL_EXSTYLE
Definition: winuser.h:845
#define HWND_TOPMOST
Definition: winuser.h:1194
#define ID_CB_LISTBOX
Definition: combo.c:79
HWND WINAPI SetFocus(_In_opt_ HWND)
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
#define LBS_COMBOBOX
Definition: winuser.h:324
#define CB_GETTYPE(lphc)
Definition: combo.c:53
RECT buttonRect
Definition: comctl32.h:144
BOOL WINAPI SetWindowTextW(_In_ HWND, _In_opt_ LPCWSTR)
INT droppedIndex
Definition: comctl32.h:146
BOOL WINAPI DrawFrameControl(_In_ HDC, _Inout_ LPRECT, _In_ UINT, _In_ UINT)
UINT_PTR WPARAM
Definition: windef.h:207
static void CBPaintText(LPHEADCOMBO lphc, HDC hdc, RECT rectEdit)
Definition: combo.c:659
#define CBS_AUTOHSCROLL
Definition: winuser.h:281
#define VK_DOWN
Definition: winuser.h:2181
#define WS_CHILD
Definition: pedump.c:617
static HBRUSH COMBO_PrepareColors(LPHEADCOMBO lphc, HDC hDC)
Definition: combo.c:812
#define GetWindowLongPtrW
Definition: winuser.h:4698
LONG left
Definition: windef.h:291
#define SWP_NOZORDER
Definition: winuser.h:1232
#define CB_SETLOCALE
Definition: winuser.h:1929
#define FNID_DESTROY
Definition: ntuser.h:859
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
static UINT CBitWidth
Definition: combo.c:62
BOOL WINAPI EndPaint(_In_ HWND, _In_ const PAINTSTRUCT *)
#define CB_NOTIFY(lphc, code)
Definition: combo.c:43
#define CB_HASSTRINGS(lphc)
Definition: combo.c:49
#define CBS_OEMCONVERT
Definition: winuser.h:288
#define WM_CBLOSTTEXTFOCUS
Definition: undocuser.h:49
#define VK_ESCAPE
Definition: winuser.h:2168
char * LPSTR
Definition: xmlstorage.h:182
BOOL WINAPI InvertRect(_In_ HDC, _In_ LPCRECT)
#define WM_CLEAR
Definition: winuser.h:1825
LONG right
Definition: windef.h:293
static void COMBO_LButtonDown(LPHEADCOMBO lphc, LPARAM lParam)
Definition: combo.c:1685
#define WM_NCCREATE
Definition: winuser.h:1665
BOOL WINAPI DestroyWindow(_In_ HWND)
#define LBN_SELCHANGE
Definition: winuser.h:2036
#define WS_EX_TOOLWINDOW
Definition: winuser.h:404
#define COLOR_WINDOW
Definition: winuser.h:908
BOOL NTAPI NtUserInvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase)
Definition: painting.c:2532
HRGN set_control_clipping(HDC hdc, const RECT *rect)
Definition: button.c:239
int32_t INT
Definition: typedefs.h:56
static LRESULT COMBO_SetItemHeight(LPHEADCOMBO lphc, INT index, INT height)
Definition: combo.c:1627
#define VK_RETURN
Definition: winuser.h:2155
#define CB_GETCURSEL
Definition: winuser.h:1904
DWORD WINAPI GetSysColor(_In_ int)
& rect
Definition: startmenu.cpp:1413
WPARAM wParam
Definition: combotst.c:138
#define LB_SELECTSTRING
Definition: winuser.h:2017
#define CBS_OWNERDRAWVARIABLE
Definition: winuser.h:290
HFONT hFont
Definition: main.c:53
#define WM_ENABLE
Definition: winuser.h:1597
LPWSTR WINAPI CharUpperW(_Inout_ LPWSTR)
#define WM_PRINTCLIENT
Definition: richedit.h:70
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
static void COMBO_Size(LPHEADCOMBO lphc)
Definition: combo.c:1538
#define lstrcpynW
Definition: compat.h:397
const char * SPY_GetMsgName(UINT msg, HWND hWnd)
Definition: spy.c:2218
#define CB_SETITEMHEIGHT
Definition: winuser.h:1928
#define LB_SETITEMHEIGHT
Definition: winuser.h:2027
LPSTR WINAPI CharLowerA(_Inout_ LPSTR)
#define EM_GETSEL
Definition: winuser.h:1958
#define CB_GETEDITSEL
Definition: winuser.h:1908
LPSTR WINAPI CharUpperA(_Inout_ LPSTR)
COLORREF WINAPI SetBkColor(_In_ HDC, _In_ COLORREF)
Definition: dc.c:975
struct tagCREATESTRUCTA * LPCREATESTRUCTA
LONG UIState
Definition: window.c:3242
HBRUSH FASTCALL GetControlColor(PWND pwndParent, PWND pwnd, HDC hdc, UINT CtlMsg)
Definition: misc.c:145
#define BF_RECT
Definition: winuser.h:462
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:93
#define CB_INITSTORAGE
Definition: winuser.h:1917
#define DFCS_PUSHED
Definition: winuser.h:503
#define LB_RESETCONTENT
Definition: winuser.h:2016
#define LBN_SELCANCEL
Definition: winuser.h:2035
#define EN_KILLFOCUS
Definition: winuser.h:1986
#define EN_SETFOCUS
Definition: winuser.h:1988
#define CB_GETDROPPEDWIDTH
Definition: winuser.h:1907
#define VK_UP
Definition: winuser.h:2179
#define ETO_OPAQUE
Definition: wingdi.h:646
#define LB_ERR
Definition: winuser.h:2386
#define WM_COPY
Definition: winuser.h:1823
DWORD fnid
Definition: ntuser.h:673
static UINT msg
Definition: combo.c:716
INT fixedOwnerDrawHeight
Definition: comctl32.h:147
#define LBS_NOINTEGRALHEIGHT
Definition: pedump.c:686
unsigned int BOOL
Definition: ntddk_ex.h:94
#define CBN_SELENDOK
Definition: winuser.h:1942
long LONG
Definition: pedump.c:60
#define WM_DELETEITEM
Definition: winuser.h:1629
#define CB_SHOWDROPDOWN
Definition: winuser.h:1931
HDC WINAPI BeginPaint(_In_ HWND, _Out_ LPPAINTSTRUCT)
BOOL WINAPI DrawEdge(_In_ HDC, _Inout_ LPRECT, _In_ UINT, _In_ UINT)
static LRESULT COMBO_NCCreate(HWND hwnd, LONG style)
Definition: combo.c:146
#define CBN_KILLFOCUS
Definition: winuser.h:1939
BOOL WINAPI GetComboBoxInfo(HWND hwndCombo, PCOMBOBOXINFO pcbi)
Definition: combo.c:2313
HWND WINAPI GetCapture(void)
Definition: message.c:2879
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define FIXME(fmt,...)
Definition: debug.h:110
#define CBS_SIMPLE
Definition: winuser.h:291
static TAGREF LPCWSTR LPDWORD LPVOID lpBuffer
Definition: db.cpp:173
#define ok(value,...)
#define STATE_SYSTEM_PRESSED
Definition: winuser.h:2818
#define VK_F4
Definition: winuser.h:2212
unsigned int idx
Definition: utils.c:41
BOOL WINAPI IsRectEmpty(_In_ LPCRECT)
#define CB_ADDSTRING
Definition: winuser.h:1897
int nItems
Definition: appswitch.c:56
const WCHAR * str
#define ES_UPPERCASE
Definition: pedump.c:668
#define CB_INSERTSTRING
Definition: winuser.h:1918
#define CBN_DBLCLK
Definition: winuser.h:1934
WINE_DEFAULT_DEBUG_CHANNEL(combo)
#define CB_GETCOMBOBOXINFO
Definition: winuser.h:1902
smooth NULL
Definition: ftsmooth.c:416
#define WM_GETFONT
Definition: winuser.h:1633
#define EN_ERRSPACE
Definition: winuser.h:1984
static HWND hwndParent
Definition: cryptui.c:300
#define WM_KEYDOWN
Definition: winuser.h:1691
LONG_PTR LPARAM
Definition: windef.h:208
#define CBS_DROPDOWNLIST
Definition: winuser.h:284
BOOL WINAPI IsWindowEnabled(_In_ HWND)
#define CB_LIMITTEXT
Definition: winuser.h:1919
#define ETO_CLIPPED
Definition: wingdi.h:647
GLuint index
Definition: glext.h:6031
const char * LPCSTR
Definition: xmlstorage.h:183
#define LB_GETTEXTLEN
Definition: winuser.h:2011
#define COLOR_HIGHLIGHTTEXT
Definition: winuser.h:917
#define LB_GETCOUNT
Definition: winuser.h:1999
#define WM_SETTEXT
Definition: winuser.h:1599
#define CB_RESETCONTENT
Definition: winuser.h:1920
#define CBS_HASSTRINGS
Definition: winuser.h:285
RECT textRect
Definition: comctl32.h:143
#define CB_ERR
Definition: winuser.h:2389
#define LB_INITSTORAGE
Definition: winuser.h:2013
const struct builtin_class_descr COMBO_builtin_class
Definition: combo.c:78
static LRESULT COMBO_NCDestroy(LPHEADCOMBO lphc)
Definition: combo.c:185
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 GLint GLint j
Definition: glfuncs.h:250
#define CB_DISABLED(lphc)
Definition: combo.c:47
HWND hWndLBox
Definition: comctl32.h:140
#define CS_VREDRAW
Definition: winuser.h:653
#define ODA_DRAWENTIRE
Definition: winuser.h:2496
#define TRACE(s)
Definition: solgame.cpp:4
#define OBM_COMBO
Definition: winuser.h:1102
static void COMBO_MouseMove(LPHEADCOMBO lphc, WPARAM wParam, LPARAM lParam)
Definition: combo.c:1763
#define WM_KILLFOCUS
Definition: winuser.h:1596
GLsizeiptr size
Definition: glext.h:5919
#define CB_GETDROPPEDCONTROLRECT
Definition: winuser.h:1905
#define GetProcessHeap()
Definition: compat.h:395
#define CBN_EDITCHANGE
Definition: winuser.h:1936
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
DWORD stateButton
Definition: winuser.h:3654
static LRESULT COMBO_SelectString(LPHEADCOMBO lphc, INT start, LPARAM pText, BOOL unicode)
Definition: combo.c:1666
#define LB_SETTOPINDEX
Definition: winuser.h:2031
__wchar_t WCHAR
Definition: xmlstorage.h:180
static HBITMAP hComboBmp
Definition: combo.c:61
static void CBGetDroppedControlRect(LPHEADCOMBO lphc, LPRECT lpRect)
Definition: combo.c:449
#define WM_SIZE
Definition: winuser.h:1593
#define ODS_DISABLED
Definition: winuser.h:2501
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
BOOL WINAPI GetMonitorInfoW(_In_ HMONITOR, _Inout_ LPMONITORINFO)
#define SWP_NOACTIVATE
Definition: winuser.h:1227
#define RDW_ERASE
Definition: winuser.h:1197
#define WM_NCDESTROY
Definition: winuser.h:1666
#define WINAPI
Definition: msvc.h:8
static void CBRepaintButton(LPHEADCOMBO lphc)
Definition: combo.c:1172
#define EM_SETSEL
Definition: winuser.h:1979
const char * wine_dbgstr_rect(const RECT *rect)
BOOL WINAPI InvalidateRect(_In_opt_ HWND, _In_opt_ LPCRECT, _In_ BOOL)
#define LBN_ERRSPACE
Definition: winuser.h:2033
int WINAPI GetSystemMetrics(_In_ int)
unsigned long DWORD
Definition: ntddk_ex.h:95
#define WM_MEASUREITEM
Definition: winuser.h:1628
#define LB_CARETOFF
Definition: undocuser.h:51
BOOL WINAPI UnionRect(_Out_ LPRECT, _In_ LPCRECT, _In_ LPCRECT)
HFONT hFont
Definition: comctl32.h:142
#define LB_SETITEMDATA
Definition: winuser.h:2026
#define LBN_DBLCLK
Definition: winuser.h:2032
#define CBN_SELENDCANCEL
Definition: winuser.h:1941
LRESULT WINAPI ComboWndProc_common(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, BOOL unicode)
Definition: combo.c:1834
#define ES_NOHIDESEL
Definition: pedump.c:673
#define WS_HSCROLL
Definition: pedump.c:628
#define WM_PAINT
Definition: winuser.h:1602
#define CB_GETHORIZONTALEXTENT
Definition: winuser.h:1910
BOOL NTAPI NtUserGetComboBoxInfo(HWND hWnd, PCOMBOBOXINFO pcbi)
Definition: window.c:3258
int ret
INT droppedWidth
Definition: comctl32.h:148
#define KEYDATA_ALT
Definition: combo.c:44
#define ISWIN31
Definition: combo.c:56
#define COLOR_GRAYTEXT
Definition: winuser.h:922
#define index(s, c)
Definition: various.h:29
#define LB_GETTEXT
Definition: winuser.h:2010
#define CBN_ERRSPACE
Definition: winuser.h:1938
PWND FASTCALL ValidateHwnd(HWND hwnd)
Definition: misc.c:369
static void CBDropDown(LPHEADCOMBO lphc)
Definition: combo.c:994
HWND WINAPI CreateWindowExW(_In_ DWORD dwExStyle, _In_opt_ LPCWSTR lpClassName, _In_opt_ LPCWSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
HDC hdc
Definition: main.c:9
struct HEADCOMBO * LPHEADCOMBO
#define CB_SELECTSTRING
Definition: winuser.h:1921
#define CB_OWNERDRAWN(lphc)
Definition: combo.c:48
static LRESULT COMBO_GetTextA(LPHEADCOMBO lphc, INT count, LPSTR buf)
Definition: combo.c:1446
#define LB_GETLOCALE
Definition: winuser.h:2006
ULONG_PTR itemData
Definition: winuser.h:3588
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
#define WS_EX_TOPMOST
Definition: pedump.c:647
#define CB_SETCURSEL
Definition: winuser.h:1922
#define CS_DBLCLKS
Definition: winuser.h:646
Definition: time.h:76
#define WM_COMMAND
Definition: winuser.h:1716
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_USER
Definition: winuser.h:1856
#define LB_GETITEMHEIGHT
Definition: winuser.h:2003
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
#define CBS_UPPERCASE
Definition: winuser.h:293
static LRESULT COMBO_Command(LPHEADCOMBO lphc, WPARAM wParam, HWND hWnd)
Definition: combo.c:1229
static LRESULT COMBO_Paint(LPHEADCOMBO lphc, HDC hParamDC)
Definition: combo.c:860
BOOL WINAPI EnableWindow(_In_ HWND, _In_ BOOL)
static BOOL COMBO_Init(void)
Definition: combo.c:99
#define ERR(fmt,...)
Definition: debug.h:109
#define ID_CB_EDIT
Definition: combo.c:80
#define GWL_STYLE
Definition: winuser.h:846
Definition: ntuser.h:657
COLORREF WINAPI SetTextColor(_In_ HDC, _In_ COLORREF)
Definition: text.c:886
static HDC hDC
Definition: 3dtext.c:33
#define CB_OKAY
Definition: winuser.h:2388
int WINAPI GetObjectW(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
#define CBN_DROPDOWN
Definition: winuser.h:1935
BOOL WINAPI SetRect(_Out_ LPRECT, _In_ int, _In_ int, _In_ int, _In_ int)
HWND WINAPI SetCapture(_In_ HWND hWnd)
static LRESULT COMBO_ItemOp(LPHEADCOMBO lphc, UINT msg, LPARAM lParam)
Definition: combo.c:1348
#define WM_COMPAREITEM
Definition: winuser.h:1637
#define LB_FINDSTRING
Definition: winuser.h:1995
static void CBForceDummyResize(LPHEADCOMBO lphc)
Definition: combo.c:308
#define WS_BORDER
Definition: pedump.c:625
#define LBS_NOTIFY
Definition: pedump.c:678
#define WS_EX_NOPARENTNOTIFY
Definition: pedump.c:646
BOOL COMBO_FlipListbox(LPHEADCOMBO lphc, BOOL ok, BOOL bRedrawButton)
Definition: combo.c:1117
#define WS_EX_CLIENTEDGE
Definition: winuser.h:384
int WINAPI GetWindowTextW(HWND hWnd, LPWSTR lpString, int nMaxCount)
Definition: window.c:1378
static void COMBO_LButtonUp(LPHEADCOMBO lphc)
Definition: combo.c:1730
HWND self
Definition: comctl32.h:136
BOOL WINAPI DeleteDC(_In_ HDC)
#define CB_DIR
Definition: winuser.h:1899
#define CB_SETEDITSEL
Definition: winuser.h:1924
static LRESULT COMBO_GetComboBoxInfo(const HEADCOMBO *lphc, COMBOBOXINFO *pcbi)
Definition: combo.c:1797
HBITMAP WINAPI LoadBitmapW(_In_opt_ HINSTANCE, _In_ LPCWSTR)
Definition: cursoricon.c:2132
#define CBS_LOWERCASE
Definition: winuser.h:286
#define LBS_DISABLENOSCROLL
Definition: pedump.c:690
GLuint start
Definition: gl.h:1545
DWORD cbSize
Definition: winuser.h:3726
#define WM_CTLCOLOREDIT
Definition: winuser.h:1743
#define CBS_DROPDOWN
Definition: winuser.h:283
#define LB_GETTOPINDEX
Definition: winuser.h:2012
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define WM_LBUTTONUP
Definition: winuser.h:1753
Definition: bl.h:1331
struct tagCREATESTRUCTW * LPCREATESTRUCTW
#define COMBO_XBORDERSIZE()
Definition: combo.c:69
#define CB_SETEXTENDEDUI
Definition: winuser.h:1925
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define CB_GETLOCALE
Definition: winuser.h:1915
#define DFCS_SCROLLCOMBOBOX
Definition: winuser.h:493
#define HWND_DESKTOP
Definition: winuser.h:1195
#define min(a, b)
Definition: monoChain.cc:55
#define LB_GETCURSEL
Definition: winuser.h:2000
unsigned int UINT
Definition: ndis.h:50
#define WM_MOUSEMOVE
Definition: winuser.h:1751
#define WS_VSCROLL
Definition: pedump.c:627
#define SWP_SHOWWINDOW
Definition: winuser.h:1233
#define lstrcpynA
Definition: compat.h:408
#define SWP_NOREDRAW
Definition: winuser.h:1231
#define SM_CXVSCROLL
Definition: winuser.h:951
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
#define CBN_SELCHANGE
Definition: winuser.h:1940
#define MK_CONTROL
Definition: winuser.h:2324
#define DFC_SCROLL
Definition: winuser.h:475
#define KF_ALTDOWN
Definition: winuser.h:2403
#define WM_SETFONT
Definition: winuser.h:1632
HWND owner
Definition: comctl32.h:137
#define WM_DRAWITEM
Definition: winuser.h:1627
static DWORD *static HFONT(WINAPI *pCreateFontIndirectExA)(const ENUMLOGFONTEXDVA *)
static UINT CBitHeight
Definition: combo.c:62
BOOL WINAPI PtInRect(_In_ LPCRECT, _In_ POINT)
#define RDW_UPDATENOW
Definition: winuser.h:1206
#define IDC_ARROW
Definition: winuser.h:682
#define GWLP_HINSTANCE
Definition: winuser.h:850
BOOL WINAPI ReleaseCapture(void)
Definition: message.c:2888
#define ES_OEMCONVERT
Definition: pedump.c:674
#define ODS_SELECTED
Definition: winuser.h:2499
#define SendMessage
Definition: winuser.h:5709
#define WM_CREATE
Definition: winuser.h:1590
#define COMBO_YBORDERSIZE()
Definition: combo.c:70
BOOL WINAPI CopyRect(_Out_ LPRECT, _In_ LPCRECT)
#define CB_GETITEMHEIGHT
Definition: winuser.h:1912
#define WM_SYSKEYDOWN
Definition: winuser.h:1695
static void CBUpdateEdit(LPHEADCOMBO lphc, INT index)
Definition: combo.c:956
HWND WINAPI CreateWindowExA(_In_ DWORD dwExStyle, _In_opt_ LPCSTR lpClassName, _In_opt_ LPCSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
#define CBN_EDITUPDATE
Definition: winuser.h:1937
#define HIWORD(l)
Definition: typedefs.h:246
GLenum GLuint id
Definition: glext.h:5579
HMONITOR WINAPI MonitorFromRect(LPCRECT, DWORD)
LONG bottom
Definition: windef.h:294
BOOL NTAPI NtUserSetWindowFNID(HWND hWnd, WORD fnID)
Definition: window.c:4107
#define EN_UPDATE
Definition: winuser.h:1989
LRESULT WINAPI ComboWndProcW(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
#define SWP_NOMOVE
Definition: winuser.h:1229
BOOL WINAPI GetWindowRect(_In_ HWND, _Out_ LPRECT)
#define EDGE_SUNKEN
Definition: winuser.h:451
BOOL WINAPI SetWindowPos(_In_ HWND, _In_opt_ HWND, _In_ int, _In_ int, _In_ int, _In_ int, _In_ UINT)
#define CB_GETCOUNT
Definition: winuser.h:1903
#define SetWindowLongPtrW
Definition: winuser.h:5215
static HBITMAP
Definition: button.c:44
#define CB_GETEXTENDEDUI
Definition: winuser.h:1909
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
#define WM_ERASEBKGND
Definition: winuser.h:1607
#define WM_SETFOCUS
Definition: winuser.h:1595
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define CB_DELETESTRING
Definition: winuser.h:1898
LONG_PTR LRESULT
Definition: windef.h:209
static INT CBUpdateLBox(LPHEADCOMBO lphc, BOOL bSelect)
Definition: combo.c:922
int WINAPI FillRect(HDC, LPCRECT, HBRUSH)
Arabic default style
Definition: afstyles.h:93
#define LB_DELETESTRING
Definition: winuser.h:1993
#define ES_LEFT
Definition: pedump.c:664
#define WS_VISIBLE
Definition: pedump.c:620
HBRUSH WINAPI GetSysColorBrush(_In_ int)
GLuint64EXT * result
Definition: glext.h:11304
#define CBN_CLOSEUP
Definition: winuser.h:1933
#define CBS_NOINTEGRALHEIGHT
Definition: winuser.h:287
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
#define CB_FINDSTRING
Definition: winuser.h:1900
static const WCHAR empty_stringW[]
Definition: edit.c:166
#define LB_INSERTSTRING
Definition: winuser.h:2014
LPARAM lParam
Definition: combotst.c:139
#define COMBO_EDITBUTTONSPACE()
Definition: combo.c:71
#define ES_AUTOHSCROLL
Definition: pedump.c:672
#define LOWORD(l)
Definition: pedump.c:82
static void CBRollUp(LPHEADCOMBO lphc, BOOL ok, BOOL bButton)
Definition: combo.c:1102
#define HeapFree(x, y, z)
Definition: compat.h:394
#define GWLP_ID
Definition: winuser.h:854
#define DLGC_WANTARROWS
Definition: winuser.h:2564
#define STATE_SYSTEM_INVISIBLE
Definition: winuser.h:2830
#define CS_PARENTDC
Definition: winuser.h:651
LRESULT WINAPI ComboWndProcA(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
static const WCHAR comboboxW[]
Definition: combo.c:77
#define WIN_GetFullHandle(h)
Definition: user_x.h:108
UINT dwStyle
Definition: comctl32.h:138
#define RDW_INVALIDATE
Definition: winuser.h:1200
int WINAPI FrameRect(_In_ HDC, _In_ LPCRECT, _In_ HBRUSH)
static char * strdupA(LPCSTR str)
Definition: combo.c:1815
static void CBResetPos(LPHEADCOMBO lphc, const RECT *rectEdit, const RECT *rectLB, BOOL bRedraw)
Definition: combo.c:1496
#define LBN_KILLFOCUS
Definition: winuser.h:2034
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define CBS_DISABLENOSCROLL
Definition: winuser.h:282
static void COMBO_SetFocus(LPHEADCOMBO lphc)
Definition: combo.c:1181
#define ES_LOWERCASE
Definition: pedump.c:669
signed short INT16
#define EN_CHANGE
Definition: winuser.h:1983
#define CB_FINDSTRINGEXACT
Definition: winuser.h:1901