4 * Copyright 1997 Alex Korobka
6 * FIXME: roll up in Netscape 3.01.
12 #include "sysmetrics.h"
22 /* bits in the dwKeyData */
23 #define KEYDATA_ALT 0x2000
24 #define KEYDATA_PREVSTATE 0x4000
27 * Additional combo box definitions
30 #define CB_GETPTR( wnd ) (*(LPHEADCOMBO*)((wnd)->wExtra))
31 #define CB_NOTIFY( lphc, code ) \
32 (SendMessage32A( (lphc)->owner, WM_COMMAND, \
33 MAKEWPARAM((lphc)->self->wIDmenu, (code)), (lphc)->self->hwndSelf))
34 #define CB_GETEDITTEXTLENGTH( lphc ) \
35 (SendMessage32A( (lphc)->hWndEdit, WM_GETTEXTLENGTH, 0, 0 ))
37 static HBITMAP32 hComboBmp
= 0;
38 static UINT32 CBitHeight
, CBitWidth
;
39 static UINT32 CBitOffset
= 8;
41 /***********************************************************************
44 * Load combo button bitmap.
46 static BOOL32
COMBO_Init()
50 if( hComboBmp
) return TRUE
;
51 if( (hDC
= CreateCompatibleDC32(0)) )
54 if( (hComboBmp
= LoadBitmap32A(0, MAKEINTRESOURCE32A(OBM_COMBO
))) )
60 GetObject32A( hComboBmp
, sizeof(bm
), &bm
);
61 CBitHeight
= bm
.bmHeight
;
62 CBitWidth
= bm
.bmWidth
;
64 TRACE(combo
, "combo bitmap [%i,%i]\n", CBitWidth
, CBitHeight
);
66 hPrevB
= SelectObject16( hDC
, hComboBmp
);
67 SetRect32( &r
, 0, 0, CBitWidth
, CBitHeight
);
68 InvertRect32( hDC
, &r
);
69 SelectObject32( hDC
, hPrevB
);
78 /***********************************************************************
81 static LRESULT
COMBO_NCCreate(WND
* wnd
, LPARAM lParam
)
85 if ( wnd
&& COMBO_Init() &&
86 (lphc
= HeapAlloc(GetProcessHeap(), 0, sizeof(HEADCOMBO
))) )
88 LPCREATESTRUCT32A lpcs
= (CREATESTRUCT32A
*)lParam
;
90 memset( lphc
, 0, sizeof(HEADCOMBO
) );
91 *(LPHEADCOMBO
*)wnd
->wExtra
= lphc
;
93 /* some braindead apps do try to use scrollbar/border flags */
95 lphc
->dwStyle
= (lpcs
->style
& ~(WS_BORDER
| WS_HSCROLL
| WS_VSCROLL
));
96 wnd
->dwStyle
&= ~(WS_BORDER
| WS_HSCROLL
| WS_VSCROLL
);
98 if( !(lpcs
->style
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) )
99 lphc
->dwStyle
|= CBS_HASSTRINGS
;
100 if( !(wnd
->dwExStyle
& WS_EX_NOPARENTNOTIFY
) )
101 lphc
->wState
|= CBF_NOTIFY
;
103 TRACE(combo
, "[0x%08x], style = %08x\n",
104 (UINT32
)lphc
, lphc
->dwStyle
);
106 return (LRESULT
)(UINT32
)wnd
->hwndSelf
;
108 return (LRESULT
)FALSE
;
111 /***********************************************************************
114 static LRESULT
COMBO_NCDestroy( LPHEADCOMBO lphc
)
119 WND
* wnd
= lphc
->self
;
121 TRACE(combo
,"[%04x]: freeing storage\n", CB_HWND(lphc
));
123 if( (CB_GETTYPE(lphc
) != CBS_SIMPLE
) && lphc
->hWndLBox
)
124 DestroyWindow32( lphc
->hWndLBox
);
126 HeapFree( GetProcessHeap(), 0, lphc
);
133 /***********************************************************************
136 * Set up component coordinates given valid lphc->RectCombo.
138 static void CBCalcPlacement( LPHEADCOMBO lphc
, LPRECT32 lprEdit
,
139 LPRECT32 lprButton
, LPRECT32 lprLB
)
141 RECT32 rect
= lphc
->RectCombo
;
144 /* get combo height and width */
146 size
.cx
= rect
.right
- rect
.left
;
148 if( CB_OWNERDRAWN(lphc
) )
150 UINT32 u
= lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
;
152 if( lphc
->wState
& CBF_MEASUREITEM
) /* first initialization */
154 MEASUREITEMSTRUCT32 mi32
;
156 lphc
->wState
&= ~CBF_MEASUREITEM
;
157 mi32
.CtlType
= ODT_COMBOBOX
;
158 mi32
.CtlID
= lphc
->self
->wIDmenu
;
160 mi32
.itemWidth
= size
.cx
;
161 mi32
.itemHeight
= u
- 6; /* ownerdrawn cb is taller */
163 SendMessage32A(lphc
->owner
, WM_MEASUREITEM
,
164 (WPARAM32
)mi32
.CtlID
, (LPARAM
)&mi32
);
165 u
= 6 + (UINT16
)mi32
.itemHeight
;
169 else if( lphc
->editHeight
) /* explicitly set height */
170 size
.cy
= lphc
->editHeight
;
173 HDC32 hDC
= GetDC32( lphc
->self
->hwndSelf
);
174 HFONT32 hPrevFont
= 0;
177 if( lphc
->hFont
) hPrevFont
= SelectObject32( hDC
, lphc
->hFont
);
179 GetTextExtentPoint32A( hDC
, "0", 1, &font_size
);
181 size
.cy
= font_size
.cy
+ font_size
.cy
/ 4 + 4 * SYSMETRICS_CYBORDER
;
183 if( hPrevFont
) SelectObject32( hDC
, hPrevFont
);
184 ReleaseDC32( lphc
->self
->hwndSelf
, hDC
);
188 /* calculate text and button placement */
190 lprEdit
->left
= lprEdit
->top
= lprButton
->top
= 0;
191 if( CB_GETTYPE(lphc
) == CBS_SIMPLE
) /* no button */
192 lprButton
->left
= lprButton
->right
= lprButton
->bottom
= 0;
195 INT32 i
= size
.cx
- CBitWidth
- 10; /* seems ok */
197 lprButton
->right
= size
.cx
;
198 lprButton
->left
= (INT16
)i
;
199 lprButton
->bottom
= lprButton
->top
+ size
.cy
;
201 if( i
< 0 ) size
.cx
= 0;
205 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
)
207 size
.cx
-= CBitOffset
;
208 if( size
.cx
< 0 ) size
.cx
= 0;
211 lprEdit
->right
= size
.cx
; lprEdit
->bottom
= size
.cy
;
213 /* listbox placement */
215 lprLB
->left
= ( CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
) ? 0 : CBitOffset
;
216 lprLB
->top
= lprEdit
->bottom
- SYSMETRICS_CYBORDER
;
217 lprLB
->right
= rect
.right
- rect
.left
;
218 lprLB
->bottom
= rect
.bottom
- rect
.top
;
220 if( lphc
->droppedWidth
> (lprLB
->right
- lprLB
->left
) )
221 lprLB
->right
= lprLB
->left
+ lphc
->droppedWidth
;
223 TRACE(combo
,"[%04x]: (%i,%i-%i,%i) placement\n",
224 CB_HWND(lphc
), lphc
->RectCombo
.left
, lphc
->RectCombo
.top
,
225 lphc
->RectCombo
.right
, lphc
->RectCombo
.bottom
);
227 TRACE(combo
,"\ttext\t= (%i,%i-%i,%i)\n",
228 lprEdit
->left
, lprEdit
->top
, lprEdit
->right
, lprEdit
->bottom
);
230 TRACE(combo
,"\tbutton\t= (%i,%i-%i,%i)\n",
231 lprButton
->left
, lprButton
->top
, lprButton
->right
, lprButton
->bottom
);
233 TRACE(combo
,"\tlbox\t= (%i,%i-%i,%i)\n",
234 lprLB
->left
, lprLB
->top
, lprLB
->right
, lprLB
->bottom
);
237 /***********************************************************************
238 * CBGetDroppedControlRect32
240 static void CBGetDroppedControlRect32( LPHEADCOMBO lphc
, LPRECT32 lpRect
)
242 lpRect
->left
= lphc
->RectCombo
.left
+
243 (lphc
->wState
& CBF_EDIT
) ? CBitOffset
: 0;
244 lpRect
->top
= lphc
->RectCombo
.top
+ lphc
->RectEdit
.bottom
-
246 lpRect
->right
= lphc
->RectCombo
.right
;
247 lpRect
->bottom
= lphc
->RectCombo
.bottom
- SYSMETRICS_CYBORDER
;
250 /***********************************************************************
253 static LRESULT
COMBO_Create( LPHEADCOMBO lphc
, WND
* wnd
, LPARAM lParam
)
255 static char clbName
[] = "ComboLBox";
256 static char editName
[] = "Edit";
258 LPCREATESTRUCT32A lpcs
= (CREATESTRUCT32A
*)lParam
;
260 if( !CB_GETTYPE(lphc
) ) lphc
->dwStyle
|= CBS_SIMPLE
;
261 else if( CB_GETTYPE(lphc
) != CBS_DROPDOWNLIST
) lphc
->wState
|= CBF_EDIT
;
264 lphc
->owner
= lpcs
->hwndParent
;
266 /* M$ IE 3.01 actually creates (and rapidly destroys) an ownerless combobox */
268 if( lphc
->owner
|| !(lpcs
->style
& WS_VISIBLE
) )
271 RECT32 editRect
, btnRect
, lbRect
;
273 GetWindowRect32( wnd
->hwndSelf
, &lphc
->RectCombo
);
275 lphc
->wState
|= CBF_MEASUREITEM
;
276 CBCalcPlacement( lphc
, &editRect
, &btnRect
, &lbRect
);
277 lphc
->RectButton
= btnRect
;
278 lphc
->droppedWidth
= lphc
->editHeight
= 0;
280 /* create listbox popup */
282 lbeStyle
= (LBS_NOTIFY
| WS_BORDER
| WS_CLIPSIBLINGS
) |
283 (lpcs
->style
& (WS_VSCROLL
| CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
));
285 if( lphc
->dwStyle
& CBS_SORT
)
286 lbeStyle
|= LBS_SORT
;
287 if( lphc
->dwStyle
& CBS_HASSTRINGS
)
288 lbeStyle
|= LBS_HASSTRINGS
;
289 if( lphc
->dwStyle
& CBS_NOINTEGRALHEIGHT
)
290 lbeStyle
|= LBS_NOINTEGRALHEIGHT
;
291 if( lphc
->dwStyle
& CBS_DISABLENOSCROLL
)
292 lbeStyle
|= LBS_DISABLENOSCROLL
;
294 if( CB_GETTYPE(lphc
) == CBS_SIMPLE
) /* child listbox */
295 lbeStyle
|= WS_CHILD
| WS_VISIBLE
;
296 else /* popup listbox */
298 lbeStyle
|= WS_POPUP
;
299 OffsetRect32( &lbRect
, lphc
->RectCombo
.left
, lphc
->RectCombo
.top
);
302 /* Dropdown ComboLBox is not a child window and we cannot pass
303 * ID_CB_LISTBOX directly because it will be treated as a menu handle.
306 lphc
->hWndLBox
= CreateWindowEx32A( 0, clbName
, NULL
, lbeStyle
,
307 lbRect
.left
+ SYSMETRICS_CXBORDER
,
308 lbRect
.top
+ SYSMETRICS_CYBORDER
,
309 lbRect
.right
- lbRect
.left
- 2 * SYSMETRICS_CXBORDER
,
310 lbRect
.bottom
- lbRect
.top
- 2 * SYSMETRICS_CYBORDER
,
311 lphc
->self
->hwndSelf
,
312 (lphc
->dwStyle
& CBS_DROPDOWN
)? (HMENU32
)0 : (HMENU32
)ID_CB_LISTBOX
,
313 lphc
->self
->hInstance
, (LPVOID
)lphc
);
317 lbeStyle
= WS_CHILD
| WS_VISIBLE
| WS_BORDER
| ES_NOHIDESEL
| ES_LEFT
;
318 if( lphc
->wState
& CBF_EDIT
)
320 if( lphc
->dwStyle
& CBS_OEMCONVERT
)
321 lbeStyle
|= ES_OEMCONVERT
;
322 if( lphc
->dwStyle
& CBS_AUTOHSCROLL
)
323 lbeStyle
|= ES_AUTOHSCROLL
;
324 if( lphc
->dwStyle
& CBS_LOWERCASE
)
325 lbeStyle
|= ES_LOWERCASE
;
326 else if( lphc
->dwStyle
& CBS_UPPERCASE
)
327 lbeStyle
|= ES_UPPERCASE
;
328 lphc
->hWndEdit
= CreateWindowEx32A( 0, editName
, NULL
, lbeStyle
,
329 editRect
.left
, editRect
.top
, editRect
.right
- editRect
.left
,
330 editRect
.bottom
- editRect
.top
, lphc
->self
->hwndSelf
,
331 (HMENU32
)ID_CB_EDIT
, lphc
->self
->hInstance
, NULL
);
332 if( !lphc
->hWndEdit
) bEdit
= FALSE
;
337 lphc
->RectEdit
= editRect
;
338 if( CB_GETTYPE(lphc
) != CBS_SIMPLE
)
340 lphc
->wState
|= CBF_NORESIZE
;
341 SetWindowPos32( wnd
->hwndSelf
, 0, 0, 0,
342 lphc
->RectCombo
.right
- lphc
->RectCombo
.left
,
343 lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
,
344 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
345 lphc
->wState
&= ~CBF_NORESIZE
;
347 TRACE(combo
,"init done\n");
348 return wnd
->hwndSelf
;
350 ERR(combo
, "edit control failure.\n");
351 } else ERR(combo
, "listbox failure.\n");
352 } else ERR(combo
, "no owner for visible combo.\n");
354 /* CreateWindow() will send WM_NCDESTROY to cleanup */
359 /***********************************************************************
362 * Paint combo button (normal, pressed, and disabled states).
364 static void CBPaintButton(LPHEADCOMBO lphc
, HDC32 hdc
)
371 if( lphc
->wState
& CBF_NOREDRAW
) return;
373 hPrevBrush
= (HBRUSH32
)SelectObject32(hdc
, GetSysColorBrush32(COLOR_BTNFACE
));
374 CONV_RECT16TO32( &lphc
->RectButton
, &r
);
376 Rectangle32(hdc
, r
.left
, r
.top
, r
.right
, r
.bottom
);
377 InflateRect32( &r
, -1, -1 );
378 if( (bBool
= lphc
->wState
& CBF_BUTTONDOWN
) )
380 GRAPH_DrawReliefRect(hdc
, &r
, 1, 0, TRUE
);
381 OffsetRect32( &r
, 1, 1 );
382 } else GRAPH_DrawReliefRect(hdc
, &r
, 1, 2, FALSE
);
384 x
= (r
.left
+ r
.right
- CBitWidth
) >> 1;
385 y
= (r
.top
+ r
.bottom
- CBitHeight
) >> 1;
387 InflateRect32( &r
, -3, -3 );
388 if( (bBool
= CB_DISABLED(lphc
)) )
390 GRAPH_SelectClipMask(hdc
, hComboBmp
, x
+ 1, y
+ 1 );
391 FillRect32(hdc
, &r
, (HBRUSH32
)GetStockObject32(WHITE_BRUSH
));
394 GRAPH_SelectClipMask(hdc
, hComboBmp
, x
, y
);
395 FillRect32(hdc
, &r
, (HBRUSH32
)GetStockObject32((bBool
) ? GRAY_BRUSH
: BLACK_BRUSH
));
397 GRAPH_SelectClipMask(hdc
, (HBITMAP32
)0, 0, 0);
398 SelectObject32( hdc
, hPrevBrush
);
401 /***********************************************************************
404 * Paint CBS_DROPDOWNLIST text field / update edit control contents.
406 static void CBPaintText(LPHEADCOMBO lphc
, HDC32 hdc
)
411 if( lphc
->wState
& CBF_NOREDRAW
) return;
413 /* follow Windows combobox that sends a bunch of text
414 * inquiries to its listbox while processing WM_PAINT. */
416 if( (id
= SendMessage32A(lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0) ) != LB_ERR
)
418 size
= SendMessage32A( lphc
->hWndLBox
, LB_GETTEXTLEN32
, id
, 0);
419 if( (pText
= HeapAlloc( GetProcessHeap(), 0, size
+ 1)) )
421 SendMessage32A( lphc
->hWndLBox
, LB_GETTEXT32
, (WPARAM32
)id
, (LPARAM
)pText
);
422 pText
[size
] = '\0'; /* just in case */
426 if( lphc
->wState
& CBF_EDIT
)
428 if( CB_HASSTRINGS(lphc
) ) SetWindowText32A( lphc
->hWndEdit
, pText
);
429 if( lphc
->wState
& CBF_FOCUSED
)
430 SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
, 0, (LPARAM
)(-1));
432 else /* paint text field ourselves */
434 HBRUSH32 hPrevBrush
= 0;
439 if ((hDC
= GetDC32(lphc
->self
->hwndSelf
)))
441 HBRUSH32 hBrush
= SendMessage32A( lphc
->owner
,
443 hDC
, lphc
->self
->hwndSelf
);
444 hPrevBrush
= SelectObject32( hDC
,
445 (hBrush
) ? hBrush
: GetStockObject32(WHITE_BRUSH
) );
452 HFONT32 hPrevFont
= (lphc
->hFont
) ? SelectObject32(hDC
, lphc
->hFont
) : 0;
454 PatBlt32( hDC
, (rect
.left
= lphc
->RectEdit
.left
+ SYSMETRICS_CXBORDER
),
455 (rect
.top
= lphc
->RectEdit
.top
+ SYSMETRICS_CYBORDER
),
456 (rect
.right
= lphc
->RectEdit
.right
- SYSMETRICS_CXBORDER
),
457 (rect
.bottom
= lphc
->RectEdit
.bottom
- SYSMETRICS_CYBORDER
) - 1, PATCOPY
);
458 InflateRect32( &rect
, -1, -1 );
460 if( lphc
->wState
& CBF_FOCUSED
&&
461 !(lphc
->wState
& CBF_DROPPED
) )
465 FillRect32( hDC
, &rect
, GetSysColorBrush32(COLOR_HIGHLIGHT
) );
466 SetBkColor32( hDC
, GetSysColor32( COLOR_HIGHLIGHT
) );
467 SetTextColor32( hDC
, GetSysColor32( COLOR_HIGHLIGHTTEXT
) );
468 itemState
= ODS_SELECTED
| ODS_FOCUS
;
469 } else itemState
= 0;
471 if( CB_OWNERDRAWN(lphc
) )
473 DRAWITEMSTRUCT32 dis
;
475 if( lphc
->self
->dwStyle
& WS_DISABLED
) itemState
|= ODS_DISABLED
;
477 dis
.CtlType
= ODT_COMBOBOX
;
478 dis
.CtlID
= lphc
->self
->wIDmenu
;
479 dis
.hwndItem
= lphc
->self
->hwndSelf
;
480 dis
.itemAction
= ODA_DRAWENTIRE
;
482 dis
.itemState
= itemState
;
485 dis
.itemData
= SendMessage32A( lphc
->hWndLBox
, LB_GETITEMDATA32
,
487 SendMessage32A( lphc
->owner
, WM_DRAWITEM
,
488 lphc
->self
->wIDmenu
, (LPARAM
)&dis
);
492 ExtTextOut32A( hDC
, rect
.left
+ 1, rect
.top
+ 1,
493 ETO_OPAQUE
| ETO_CLIPPED
, &rect
,
494 (pText
) ? pText
: "" , size
, NULL
);
495 if(lphc
->wState
& CBF_FOCUSED
&& !(lphc
->wState
& CBF_DROPPED
))
496 DrawFocusRect32( hDC
, &rect
);
499 if( hPrevFont
) SelectObject32(hDC
, hPrevFont
);
502 if( hPrevBrush
) SelectObject32( hDC
, hPrevBrush
);
503 ReleaseDC32( lphc
->self
->hwndSelf
, hDC
);
507 HeapFree( GetProcessHeap(), 0, pText
);
510 /***********************************************************************
513 static LRESULT
COMBO_Paint(LPHEADCOMBO lphc
, HDC32 hParamDC
)
518 hDC
= (hParamDC
) ? hParamDC
519 : BeginPaint32( lphc
->self
->hwndSelf
, &ps
);
520 if( hDC
&& !(lphc
->wState
& CBF_NOREDRAW
) )
522 HBRUSH32 hPrevBrush
, hBkgBrush
;
524 hBkgBrush
= SendMessage32A( lphc
->owner
, WM_CTLCOLORLISTBOX
,
525 hDC
, lphc
->self
->hwndSelf
);
526 if( !hBkgBrush
) hBkgBrush
= GetStockObject32(WHITE_BRUSH
);
528 hPrevBrush
= SelectObject32( hDC
, hBkgBrush
);
529 if( !IsRectEmpty32(&lphc
->RectButton
) )
531 /* paint everything to the right of the text field */
533 PatBlt32( hDC
, lphc
->RectEdit
.right
, lphc
->RectEdit
.top
,
534 lphc
->RectButton
.right
- lphc
->RectEdit
.right
,
535 lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
, PATCOPY
);
536 CBPaintButton( lphc
, hDC
);
539 if( !(lphc
->wState
& CBF_EDIT
) )
541 /* paint text field */
543 GRAPH_DrawRectangle( hDC
, lphc
->RectEdit
.left
, lphc
->RectEdit
.top
,
544 lphc
->RectEdit
.right
- lphc
->RectEdit
.left
,
545 lphc
->RectButton
.bottom
- lphc
->RectButton
.top
,
546 GetSysColorPen32(COLOR_WINDOWFRAME
) );
547 CBPaintText( lphc
, hDC
);
549 if( hPrevBrush
) SelectObject32( hDC
, hPrevBrush
);
551 if( !hParamDC
) EndPaint32(lphc
->self
->hwndSelf
, &ps
);
555 /***********************************************************************
558 * Select listbox entry according to the contents of the edit control.
560 static INT32
CBUpdateLBox( LPHEADCOMBO lphc
)
562 INT32 length
, idx
, ret
;
566 length
= CB_GETEDITTEXTLENGTH( lphc
);
569 pText
= (LPSTR
) HeapAlloc( GetProcessHeap(), 0, length
+ 1);
571 TRACE(combo
,"\t edit text length %i\n", length
);
575 if( length
) GetWindowText32A( lphc
->hWndEdit
, pText
, length
+ 1);
576 else pText
[0] = '\0';
577 idx
= SendMessage32A( lphc
->hWndLBox
, LB_FINDSTRING32
,
578 (WPARAM32
)(-1), (LPARAM
)pText
);
579 if( idx
== LB_ERR
) idx
= 0; /* select first item */
581 HeapFree( GetProcessHeap(), 0, pText
);
586 SendMessage32A( lphc
->hWndLBox
, LB_SETCURSEL32
, (WPARAM32
)idx
, 0 );
590 SendMessage32A( lphc
->hWndLBox
, LB_SETTOPINDEX32
, (WPARAM32
)idx
, 0 );
591 /* probably superfluous but Windows sends this too */
592 SendMessage32A( lphc
->hWndLBox
, LB_SETCARETINDEX32
, (WPARAM32
)idx
, 0 );
597 /***********************************************************************
600 * Copy a listbox entry to the edit control.
602 static void CBUpdateEdit( LPHEADCOMBO lphc
, INT32 index
)
607 TRACE(combo
,"\t %i\n", index
);
611 length
= CB_GETEDITTEXTLENGTH( lphc
);
614 if( (pText
= (LPSTR
) HeapAlloc( GetProcessHeap(), 0, length
+ 1)) )
616 GetWindowText32A( lphc
->hWndEdit
, pText
, length
+ 1 );
617 index
= SendMessage32A( lphc
->hWndLBox
, LB_FINDSTRING32
,
618 (WPARAM32
)(-1), (LPARAM
)pText
);
619 HeapFree( GetProcessHeap(), 0, pText
);
624 if( index
>= 0 ) /* got an entry */
626 length
= SendMessage32A( lphc
->hWndLBox
, LB_GETTEXTLEN32
, (WPARAM32
)index
, 0);
629 if( (pText
= (LPSTR
) HeapAlloc( GetProcessHeap(), 0, length
+ 1)) )
631 SendMessage32A( lphc
->hWndLBox
, LB_GETTEXT32
,
632 (WPARAM32
)index
, (LPARAM
)pText
);
633 SendMessage32A( lphc
->hWndEdit
, WM_SETTEXT
, 0, (LPARAM
)pText
);
634 SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
, 0, (LPARAM
)(-1) );
635 HeapFree( GetProcessHeap(), 0, pText
);
641 /***********************************************************************
644 * Show listbox popup.
646 static void CBDropDown( LPHEADCOMBO lphc
)
650 LPRECT32 pRect
= NULL
;
652 TRACE(combo
,"[%04x]: drop down\n", CB_HWND(lphc
));
654 CB_NOTIFY( lphc
, CBN_DROPDOWN
);
658 lphc
->wState
|= CBF_DROPPED
;
659 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
)
661 index
= CBUpdateLBox( lphc
);
662 if( !(lphc
->wState
& CBF_CAPTURE
) ) CBUpdateEdit( lphc
, index
);
666 index
= SendMessage32A( lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0 );
667 if( index
== LB_ERR
) index
= 0;
668 SendMessage32A( lphc
->hWndLBox
, LB_SETTOPINDEX32
, (WPARAM32
)index
, 0 );
669 SendMessage32A( lphc
->hWndLBox
, LB_CARETON32
, 0, 0 );
670 pRect
= &lphc
->RectEdit
;
673 /* now set popup position */
675 GetWindowRect32( lphc
->self
->hwndSelf
, &rect
);
677 rect
.top
+= lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
- SYSMETRICS_CYBORDER
;
678 rect
.bottom
= rect
.top
+ lphc
->RectCombo
.bottom
-
679 lphc
->RectCombo
.top
- SYSMETRICS_CYBORDER
;
680 rect
.right
= rect
.left
+ lphc
->RectCombo
.right
- lphc
->RectCombo
.left
;
681 rect
.left
+= ( CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
) ? 0 : CBitOffset
;
683 SetWindowPos32( lphc
->hWndLBox
, HWND_TOP
, rect
.left
, rect
.top
,
684 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
685 SWP_NOACTIVATE
| SWP_NOSIZE
| SWP_NOREDRAW
);
687 if( !(lphc
->wState
& CBF_NOREDRAW
) )
689 RedrawWindow32( lphc
->self
->hwndSelf
, pRect
, 0, RDW_INVALIDATE
|
690 RDW_ERASE
| RDW_UPDATENOW
| RDW_NOCHILDREN
);
691 ShowWindow32( lphc
->hWndLBox
, SW_SHOWNA
);
694 /***********************************************************************
697 * Hide listbox popup.
699 static void CBRollUp( LPHEADCOMBO lphc
, BOOL32 ok
, BOOL32 bButton
)
701 HWND32 hWnd
= lphc
->self
->hwndSelf
;
703 CB_NOTIFY( lphc
, (ok
) ? CBN_SELENDOK
: CBN_SELENDCANCEL
);
705 if( IsWindow32( hWnd
) && CB_GETTYPE(lphc
) != CBS_SIMPLE
)
708 TRACE(combo
,"[%04x]: roll up [%i]\n", CB_HWND(lphc
), (INT32
)ok
);
710 /* always send WM_LBUTTONUP? */
711 SendMessage32A( lphc
->hWndLBox
, WM_LBUTTONUP
, 0, (LPARAM
)(-1) );
713 if( lphc
->wState
& CBF_DROPPED
)
717 lphc
->wState
&= ~CBF_DROPPED
;
718 ShowWindow32( lphc
->hWndLBox
, SW_HIDE
);
720 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
)
722 INT32 index
= SendMessage32A( lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0 );
723 CBUpdateEdit( lphc
, index
);
724 rect
= lphc
->RectButton
;
729 UnionRect32( &rect
, &lphc
->RectButton
,
732 rect
= lphc
->RectEdit
;
736 if( bButton
&& !(lphc
->wState
& CBF_NOREDRAW
) )
737 RedrawWindow32( hWnd
, &rect
, 0, RDW_INVALIDATE
|
738 RDW_ERASE
| RDW_UPDATENOW
| RDW_NOCHILDREN
);
739 CB_NOTIFY( lphc
, CBN_CLOSEUP
);
744 /***********************************************************************
747 * Used by the ComboLBox to show/hide itself in response to VK_F4, etc...
749 BOOL32
COMBO_FlipListbox( LPHEADCOMBO lphc
, BOOL32 bRedrawButton
)
751 if( lphc
->wState
& CBF_DROPPED
)
753 CBRollUp( lphc
, TRUE
, bRedrawButton
);
761 /***********************************************************************
764 * Edit control helper.
766 HWND32
COMBO_GetLBWindow( WND
* pWnd
)
768 LPHEADCOMBO lphc
= CB_GETPTR(pWnd
);
769 if( lphc
) return lphc
->hWndLBox
;
774 /***********************************************************************
777 static void CBRepaintButton( LPHEADCOMBO lphc
)
779 HDC32 hDC
= GetDC32( lphc
->self
->hwndSelf
);
783 CBPaintButton( lphc
, hDC
);
784 ReleaseDC32( lphc
->self
->hwndSelf
, hDC
);
788 /***********************************************************************
791 static void COMBO_SetFocus( LPHEADCOMBO lphc
)
793 if( !(lphc
->wState
& CBF_FOCUSED
) )
795 if( CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
)
796 SendMessage32A( lphc
->hWndLBox
, LB_CARETON32
, 0, 0 );
798 if( lphc
->wState
& CBF_EDIT
)
799 SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
, 0, (LPARAM
)(-1) );
800 lphc
->wState
|= CBF_FOCUSED
;
801 if( !(lphc
->wState
& CBF_EDIT
) ) CBPaintText( lphc
, 0 );
803 CB_NOTIFY( lphc
, CBN_SETFOCUS
);
807 /***********************************************************************
810 static void COMBO_KillFocus( LPHEADCOMBO lphc
)
812 HWND32 hWnd
= lphc
->self
->hwndSelf
;
814 if( lphc
->wState
& CBF_FOCUSED
)
816 SendMessage32A( hWnd
, WM_LBUTTONUP
, 0, (LPARAM
)(-1) );
818 CBRollUp( lphc
, FALSE
, TRUE
);
819 if( IsWindow32( hWnd
) )
821 if( CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
)
822 SendMessage32A( lphc
->hWndLBox
, LB_CARETOFF32
, 0, 0 );
824 lphc
->wState
&= ~CBF_FOCUSED
;
827 if( lphc
->wState
& CBF_EDIT
)
828 SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
, (WPARAM32
)(-1), 0 );
829 else CBPaintText( lphc
, 0 );
831 CB_NOTIFY( lphc
, CBN_KILLFOCUS
);
836 /***********************************************************************
839 static LRESULT
COMBO_Command( LPHEADCOMBO lphc
, WPARAM32 wParam
, HWND32 hWnd
)
841 if( lphc
->wState
& CBF_EDIT
&& lphc
->hWndEdit
== hWnd
)
843 /* ">> 8" makes gcc generate jump-table instead of cmp ladder */
845 switch( HIWORD(wParam
) >> 8 )
847 case (EN_SETFOCUS
>> 8):
849 TRACE(combo
,"[%04x]: edit [%04x] got focus\n",
850 CB_HWND(lphc
), lphc
->hWndEdit
);
852 if( !(lphc
->wState
& CBF_FOCUSED
) ) COMBO_SetFocus( lphc
);
855 case (EN_KILLFOCUS
>> 8):
857 TRACE(combo
,"[%04x]: edit [%04x] lost focus\n",
858 CB_HWND(lphc
), lphc
->hWndEdit
);
860 /* NOTE: it seems that Windows' edit control sends an
861 * undocumented message WM_USER + 0x1B instead of this
862 * notification (only when it happens to be a part of
863 * the combo). ?? - AK.
866 COMBO_KillFocus( lphc
);
870 case (EN_CHANGE
>> 8):
871 CB_NOTIFY( lphc
, CBN_EDITCHANGE
);
872 CBUpdateLBox( lphc
);
875 case (EN_UPDATE
>> 8):
876 CB_NOTIFY( lphc
, CBN_EDITUPDATE
);
879 case (EN_ERRSPACE
>> 8):
880 CB_NOTIFY( lphc
, CBN_ERRSPACE
);
883 else if( lphc
->hWndLBox
== hWnd
)
885 switch( HIWORD(wParam
) )
888 CB_NOTIFY( lphc
, CBN_ERRSPACE
);
892 CB_NOTIFY( lphc
, CBN_DBLCLK
);
898 TRACE(combo
,"[%04x]: lbox selection change [%04x]\n",
899 CB_HWND(lphc
), lphc
->wState
);
901 /* do not roll up if selection is being tracked
902 * by arrowkeys in the dropdown listbox */
904 if( (lphc
->wState
& CBF_DROPPED
) && !(lphc
->wState
& CBF_NOROLLUP
) )
905 CBRollUp( lphc
, (HIWORD(wParam
) == LBN_SELCHANGE
), TRUE
);
906 else lphc
->wState
&= ~CBF_NOROLLUP
;
908 CB_NOTIFY( lphc
, CBN_SELCHANGE
);
909 CBPaintText( lphc
, 0 );
914 /* nothing to do here since ComboLBox always resets the focus to its
915 * combo/edit counterpart */
922 /***********************************************************************
925 * Fixup an ownerdrawn item operation and pass it up to the combobox owner.
927 static LRESULT
COMBO_ItemOp32( LPHEADCOMBO lphc
, UINT32 msg
,
928 WPARAM32 wParam
, LPARAM lParam
)
930 HWND32 hWnd
= lphc
->self
->hwndSelf
;
932 TRACE(combo
,"[%04x]: ownerdraw op %04x\n", CB_HWND(lphc
), msg
);
934 #define lpIS ((LPDELETEITEMSTRUCT32)lParam)
936 /* two first items are the same in all 4 structs */
937 lpIS
->CtlType
= ODT_COMBOBOX
;
938 lpIS
->CtlID
= lphc
->self
->wIDmenu
;
940 switch( msg
) /* patch window handle */
943 lpIS
->hwndItem
= hWnd
;
947 #define lpIS ((LPDRAWITEMSTRUCT32)lParam)
948 lpIS
->hwndItem
= hWnd
;
952 #define lpIS ((LPCOMPAREITEMSTRUCT32)lParam)
953 lpIS
->hwndItem
= hWnd
;
958 return SendMessage32A( lphc
->owner
, msg
, lphc
->self
->wIDmenu
, lParam
);
961 /***********************************************************************
964 static LRESULT
COMBO_GetText( LPHEADCOMBO lphc
, UINT32 N
, LPSTR lpText
)
966 if( lphc
->wState
& CBF_EDIT
)
967 return SendMessage32A( lphc
->hWndEdit
, WM_GETTEXT
,
968 (WPARAM32
)N
, (LPARAM
)lpText
);
970 /* get it from the listbox */
974 INT32 idx
= SendMessage32A( lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0 );
978 INT32 length
= SendMessage32A( lphc
->hWndLBox
, LB_GETTEXTLEN32
,
981 /* 'length' is without the terminating character */
983 lpBuffer
= (LPSTR
) HeapAlloc( GetProcessHeap(), 0, length
+ 1 );
989 INT32 n
= SendMessage32A( lphc
->hWndLBox
, LB_GETTEXT32
,
990 (WPARAM32
)idx
, (LPARAM
)lpText
);
992 /* truncate if buffer is too short */
996 if( n
!= LB_ERR
) memcpy( lpText
, lpBuffer
, (N
>n
) ? n
+1 : N
-1 );
997 lpText
[N
- 1] = '\0';
998 HeapFree( GetProcessHeap(), 0, lpBuffer
);
1008 /***********************************************************************
1011 * This function sets window positions according to the updated
1012 * component placement struct.
1014 static void CBResetPos( LPHEADCOMBO lphc
, LPRECT32 lbRect
, BOOL32 bRedraw
)
1016 BOOL32 bDrop
= (CB_GETTYPE(lphc
) != CBS_SIMPLE
);
1018 /* NOTE: logs sometimes have WM_LBUTTONUP before a cascade of
1019 * sizing messages */
1021 if( lphc
->wState
& CBF_EDIT
)
1022 SetWindowPos32( lphc
->hWndEdit
, 0, lphc
->RectEdit
.left
, lphc
->RectEdit
.top
,
1023 lphc
->RectEdit
.right
- lphc
->RectEdit
.left
,
1024 lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
,
1025 SWP_NOZORDER
| SWP_NOACTIVATE
| ((bDrop
) ? SWP_NOREDRAW
: 0) );
1028 OffsetRect32( lbRect
, lphc
->RectCombo
.left
, lphc
->RectCombo
.top
);
1030 lbRect
->right
-= lbRect
->left
; /* convert to width */
1031 lbRect
->bottom
-= lbRect
->top
;
1032 SetWindowPos32( lphc
->hWndLBox
, 0, lbRect
->left
, lbRect
->top
,
1033 lbRect
->right
, lbRect
->bottom
,
1034 SWP_NOACTIVATE
| SWP_NOZORDER
| ((bDrop
) ? SWP_NOREDRAW
: 0) );
1038 if( lphc
->wState
& CBF_DROPPED
)
1040 lphc
->wState
&= ~CBF_DROPPED
;
1041 ShowWindow32( lphc
->hWndLBox
, SW_HIDE
);
1044 lphc
->wState
|= CBF_NORESIZE
;
1045 SetWindowPos32( lphc
->self
->hwndSelf
, 0, 0, 0,
1046 lphc
->RectCombo
.right
- lphc
->RectCombo
.left
,
1047 lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
,
1048 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
1049 lphc
->wState
&= ~CBF_NORESIZE
;
1051 if( bRedraw
&& !(lphc
->wState
& CBF_NOREDRAW
) )
1052 RedrawWindow32( lphc
->self
->hwndSelf
, NULL
, 0,
1053 RDW_INVALIDATE
| RDW_ERASE
| RDW_UPDATENOW
);
1058 /***********************************************************************
1061 static void COMBO_Size( LPHEADCOMBO lphc
)
1066 GetWindowRect32( lphc
->self
->hwndSelf
, &rect
);
1067 w
= rect
.right
- rect
.left
; h
= rect
.bottom
- rect
.top
;
1069 TRACE(combo
,"w = %i, h = %i\n", w
, h
);
1071 /* CreateWindow() may send a bogus WM_SIZE, ignore it */
1073 if( w
== (lphc
->RectCombo
.right
- lphc
->RectCombo
.left
) ) {
1074 if( (CB_GETTYPE(lphc
) == CBS_SIMPLE
) &&
1075 (h
== (lphc
->RectCombo
.bottom
- lphc
->RectCombo
.top
)) )
1077 else if( (lphc
->dwStyle
& CBS_DROPDOWN
) &&
1078 (h
== (lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
)) )
1082 lphc
->RectCombo
= rect
;
1083 CBCalcPlacement( lphc
, &lphc
->RectEdit
, &lphc
->RectButton
, &rect
);
1084 CBResetPos( lphc
, &rect
, TRUE
);
1088 /***********************************************************************
1091 static void COMBO_Font( LPHEADCOMBO lphc
, HFONT32 hFont
, BOOL32 bRedraw
)
1095 lphc
->hFont
= hFont
;
1097 if( lphc
->wState
& CBF_EDIT
)
1098 SendMessage32A( lphc
->hWndEdit
, WM_SETFONT
, (WPARAM32
)hFont
, bRedraw
);
1099 SendMessage32A( lphc
->hWndLBox
, WM_SETFONT
, (WPARAM32
)hFont
, bRedraw
);
1101 GetWindowRect32( lphc
->self
->hwndSelf
, &rect
);
1102 OffsetRect32( &lphc
->RectCombo
, rect
.left
- lphc
->RectCombo
.left
,
1103 rect
.top
- lphc
->RectCombo
.top
);
1104 CBCalcPlacement( lphc
, &lphc
->RectEdit
,
1105 &lphc
->RectButton
, &rect
);
1106 CBResetPos( lphc
, &rect
, bRedraw
);
1110 /***********************************************************************
1111 * COMBO_SetItemHeight
1113 static LRESULT
COMBO_SetItemHeight( LPHEADCOMBO lphc
, INT32 index
, INT32 height
)
1115 LRESULT lRet
= CB_ERR
;
1117 if( index
== -1 ) /* set text field height */
1119 if( height
< 32768 )
1123 lphc
->editHeight
= height
;
1124 GetWindowRect32( lphc
->self
->hwndSelf
, &rect
);
1125 OffsetRect32( &lphc
->RectCombo
, rect
.left
- lphc
->RectCombo
.left
,
1126 rect
.top
- lphc
->RectCombo
.top
);
1127 CBCalcPlacement( lphc
, &lphc
->RectEdit
,
1128 &lphc
->RectButton
, &rect
);
1129 CBResetPos( lphc
, &rect
, TRUE
);
1133 else if ( CB_OWNERDRAWN(lphc
) ) /* set listbox item height */
1134 lRet
= SendMessage32A( lphc
->hWndLBox
, LB_SETITEMHEIGHT32
,
1135 (WPARAM32
)index
, (LPARAM
)height
);
1139 /***********************************************************************
1140 * COMBO_SelectString
1142 static LRESULT
COMBO_SelectString( LPHEADCOMBO lphc
, INT32 start
, LPCSTR pText
)
1144 INT32 index
= SendMessage32A( lphc
->hWndLBox
, LB_SELECTSTRING32
,
1145 (WPARAM32
)start
, (LPARAM
)pText
);
1147 if( lphc
->wState
& CBF_EDIT
)
1148 CBUpdateEdit( lphc
, index
);
1150 CBPaintText( lphc
, 0 );
1152 return (LRESULT
)index
;
1155 /***********************************************************************
1158 static void COMBO_LButtonDown( LPHEADCOMBO lphc
, LPARAM lParam
)
1160 POINT32 pt
= { LOWORD(lParam
), HIWORD(lParam
) };
1161 BOOL32 bButton
= PtInRect32(&lphc
->RectButton
, pt
);
1162 HWND32 hWnd
= lphc
->self
->hwndSelf
;
1164 if( (CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
) ||
1165 (bButton
&& (CB_GETTYPE(lphc
) == CBS_DROPDOWN
)) )
1167 lphc
->wState
|= CBF_BUTTONDOWN
;
1168 if( lphc
->wState
& CBF_DROPPED
)
1170 /* got a click to cancel selection */
1172 CBRollUp( lphc
, TRUE
, FALSE
);
1173 if( !IsWindow32( hWnd
) ) return;
1175 if( lphc
->wState
& CBF_CAPTURE
)
1177 lphc
->wState
&= ~CBF_CAPTURE
;
1180 lphc
->wState
&= ~CBF_BUTTONDOWN
;
1184 /* drop down the listbox and start tracking */
1186 lphc
->wState
|= CBF_CAPTURE
;
1188 SetCapture32( hWnd
);
1190 if( bButton
) CBRepaintButton( lphc
);
1194 /***********************************************************************
1197 * Release capture and stop tracking if needed.
1199 static void COMBO_LButtonUp( LPHEADCOMBO lphc
, LPARAM lParam
)
1201 if( lphc
->wState
& CBF_CAPTURE
)
1203 lphc
->wState
&= ~CBF_CAPTURE
;
1204 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
)
1206 INT32 index
= CBUpdateLBox( lphc
);
1207 CBUpdateEdit( lphc
, index
);
1212 if( lphc
->wState
& CBF_BUTTONDOWN
)
1214 lphc
->wState
&= ~CBF_BUTTONDOWN
;
1215 CBRepaintButton( lphc
);
1219 /***********************************************************************
1222 * Two things to do - track combo button and release capture when
1223 * pointer goes into the listbox.
1225 static void COMBO_MouseMove( LPHEADCOMBO lphc
, WPARAM32 wParam
, LPARAM lParam
)
1227 POINT32 pt
= { LOWORD(lParam
), HIWORD(lParam
) };
1230 if( lphc
->wState
& CBF_BUTTONDOWN
)
1232 BOOL32 bButton
= PtInRect32(&lphc
->RectButton
, pt
);
1236 lphc
->wState
&= ~CBF_BUTTONDOWN
;
1237 CBRepaintButton( lphc
);
1241 GetClientRect32( lphc
->hWndLBox
, &lbRect
);
1242 MapWindowPoints32( lphc
->self
->hwndSelf
, lphc
->hWndLBox
, &pt
, 1 );
1243 if( PtInRect32(&lbRect
, pt
) )
1245 lphc
->wState
&= ~CBF_CAPTURE
;
1247 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
) CBUpdateLBox( lphc
);
1249 /* hand over pointer tracking */
1250 SendMessage32A( lphc
->hWndLBox
, WM_LBUTTONDOWN
, wParam
, lParam
);
1255 /***********************************************************************
1258 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/ctrl/src/combobox_15.htm
1260 LRESULT WINAPI
ComboWndProc( HWND32 hwnd
, UINT32 message
,
1261 WPARAM32 wParam
, LPARAM lParam
)
1263 WND
* pWnd
= WIN_FindWndPtr(hwnd
);
1267 LPHEADCOMBO lphc
= CB_GETPTR(pWnd
);
1269 TRACE(combo
, "[%04x]: msg %s wp %08x lp %08lx\n",
1270 pWnd
->hwndSelf
, SPY_GetMsgName(message
), wParam
, lParam
);
1272 if( lphc
|| message
== WM_NCCREATE
)
1276 /* System messages */
1279 return COMBO_NCCreate(pWnd
, lParam
);
1282 COMBO_NCDestroy(lphc
);
1286 return COMBO_Create(lphc
, pWnd
, lParam
);
1289 /* wParam may contain a valid HDC! */
1290 return COMBO_Paint(lphc
, wParam
);
1296 return (LRESULT
)(DLGC_WANTARROWS
| DLGC_WANTCHARS
);
1299 if( lphc
->hWndLBox
&&
1300 !(lphc
->wState
& CBF_NORESIZE
) ) COMBO_Size( lphc
);
1304 COMBO_Font( lphc
, (HFONT16
)wParam
, (BOOL32
)lParam
);
1308 return (LRESULT
)lphc
->hFont
;
1311 if( lphc
->wState
& CBF_EDIT
)
1312 SetFocus32( lphc
->hWndEdit
);
1314 COMBO_SetFocus( lphc
);
1318 #define hwndFocus ((HWND16)wParam)
1320 (hwndFocus
!= lphc
->hWndEdit
&& hwndFocus
!= lphc
->hWndLBox
))
1321 COMBO_KillFocus( lphc
);
1326 return COMBO_Command( lphc
, wParam
, (HWND32
)lParam
);
1329 return COMBO_GetText( lphc
, (UINT32
)wParam
, (LPSTR
)lParam
);
1332 case WM_GETTEXTLENGTH
:
1337 if( lphc
->wState
& CBF_EDIT
)
1338 return SendMessage32A( lphc
->hWndEdit
, message
, wParam
, lParam
);
1343 case WM_COMPAREITEM
:
1344 case WM_MEASUREITEM
:
1345 return COMBO_ItemOp32( lphc
, message
, wParam
, lParam
);
1348 if( lphc
->wState
& CBF_EDIT
)
1349 EnableWindow32( lphc
->hWndEdit
, (BOOL32
)wParam
);
1350 EnableWindow32( lphc
->hWndLBox
, (BOOL32
)wParam
);
1355 lphc
->wState
&= ~CBF_NOREDRAW
;
1357 lphc
->wState
|= CBF_NOREDRAW
;
1359 if( lphc
->wState
& CBF_EDIT
)
1360 SendMessage32A( lphc
->hWndEdit
, message
, wParam
, lParam
);
1361 SendMessage32A( lphc
->hWndLBox
, message
, wParam
, lParam
);
1365 if( KEYDATA_ALT
& HIWORD(lParam
) )
1366 if( wParam
== VK_UP
|| wParam
== VK_DOWN
)
1367 COMBO_FlipListbox( lphc
, TRUE
);
1372 if( lphc
->wState
& CBF_EDIT
)
1373 return SendMessage32A( lphc
->hWndEdit
, message
, wParam
, lParam
);
1375 return SendMessage32A( lphc
->hWndLBox
, message
, wParam
, lParam
);
1377 case WM_LBUTTONDOWN
:
1378 if( !(lphc
->wState
& CBF_FOCUSED
) ) SetFocus32( lphc
->self
->hwndSelf
);
1379 if( lphc
->wState
& CBF_FOCUSED
) COMBO_LButtonDown( lphc
, lParam
);
1383 COMBO_LButtonUp( lphc
, lParam
);
1387 if( lphc
->wState
& CBF_CAPTURE
)
1388 COMBO_MouseMove( lphc
, wParam
, lParam
);
1391 /* Combo messages */
1393 case CB_ADDSTRING16
:
1394 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1395 case CB_ADDSTRING32
:
1396 return SendMessage32A( lphc
->hWndLBox
, LB_ADDSTRING32
, 0, lParam
);
1398 case CB_INSERTSTRING16
:
1399 wParam
= (INT32
)(INT16
)wParam
;
1400 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1401 case CB_INSERTSTRING32
:
1402 return SendMessage32A( lphc
->hWndLBox
, LB_INSERTSTRING32
, wParam
, lParam
);
1404 case CB_DELETESTRING16
:
1405 case CB_DELETESTRING32
:
1406 return SendMessage32A( lphc
->hWndLBox
, LB_DELETESTRING32
, wParam
, 0);
1408 case CB_SELECTSTRING16
:
1409 wParam
= (INT32
)(INT16
)wParam
;
1410 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1411 case CB_SELECTSTRING32
:
1412 return COMBO_SelectString( lphc
, (INT32
)wParam
, (LPSTR
)lParam
);
1414 case CB_FINDSTRING16
:
1415 wParam
= (INT32
)(INT16
)wParam
;
1416 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1417 case CB_FINDSTRING32
:
1418 return SendMessage32A( lphc
->hWndLBox
, LB_FINDSTRING32
, wParam
, lParam
);
1420 case CB_FINDSTRINGEXACT16
:
1421 wParam
= (INT32
)(INT16
)wParam
;
1422 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1423 case CB_FINDSTRINGEXACT32
:
1424 return SendMessage32A( lphc
->hWndLBox
, LB_FINDSTRINGEXACT32
,
1426 case CB_SETITEMHEIGHT16
:
1427 wParam
= (INT32
)(INT16
)wParam
; /* signed integer */
1428 case CB_SETITEMHEIGHT32
:
1429 return COMBO_SetItemHeight( lphc
, (INT32
)wParam
, (INT32
)lParam
);
1431 case CB_GETITEMHEIGHT16
:
1432 wParam
= (INT32
)(INT16
)wParam
;
1433 case CB_GETITEMHEIGHT32
:
1434 if( (INT32
)wParam
>= 0 )
1435 return SendMessage32A( lphc
->hWndLBox
, LB_GETITEMHEIGHT32
, wParam
, 0);
1436 return (lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
);
1438 case CB_RESETCONTENT16
:
1439 case CB_RESETCONTENT32
:
1440 SendMessage32A( lphc
->hWndLBox
, LB_RESETCONTENT32
, 0, 0 );
1441 CBPaintText( lphc
, 0 );
1444 case CB_INITSTORAGE32
:
1445 return SendMessage32A( lphc
->hWndLBox
, LB_INITSTORAGE32
, wParam
, lParam
);
1447 case CB_GETHORIZONTALEXTENT32
:
1448 return SendMessage32A( lphc
->hWndLBox
, LB_GETHORIZONTALEXTENT32
, 0, 0);
1450 case CB_SETHORIZONTALEXTENT32
:
1451 return SendMessage32A( lphc
->hWndLBox
, LB_SETHORIZONTALEXTENT32
, wParam
, 0);
1453 case CB_GETTOPINDEX32
:
1454 return SendMessage32A( lphc
->hWndLBox
, LB_GETTOPINDEX32
, 0, 0);
1456 case CB_GETLOCALE32
:
1457 return SendMessage32A( lphc
->hWndLBox
, LB_GETLOCALE32
, 0, 0);
1459 case CB_SETLOCALE32
:
1460 return SendMessage32A( lphc
->hWndLBox
, LB_SETLOCALE32
, wParam
, 0);
1462 case CB_GETDROPPEDWIDTH32
:
1463 if( lphc
->droppedWidth
)
1464 return lphc
->droppedWidth
;
1465 return lphc
->RectCombo
.right
- lphc
->RectCombo
.left
-
1466 (lphc
->wState
& CBF_EDIT
) ? CBitOffset
: 0;
1468 case CB_SETDROPPEDWIDTH32
:
1469 if( (CB_GETTYPE(lphc
) != CBS_SIMPLE
) &&
1470 (INT32
)wParam
< 32768 ) lphc
->droppedWidth
= (INT32
)wParam
;
1473 case CB_GETDROPPEDCONTROLRECT16
:
1474 lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1478 CBGetDroppedControlRect32( lphc
, &r
);
1479 CONV_RECT32TO16( &r
, (LPRECT16
)lParam
);
1483 case CB_GETDROPPEDCONTROLRECT32
:
1484 if( lParam
) CBGetDroppedControlRect32(lphc
, (LPRECT32
)lParam
);
1487 case CB_GETDROPPEDSTATE16
:
1488 case CB_GETDROPPEDSTATE32
:
1489 return (lphc
->wState
& CBF_DROPPED
) ? TRUE
: FALSE
;
1492 lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1495 return COMBO_Directory( lphc
, (UINT32
)wParam
,
1496 (LPSTR
)lParam
, (message
== CB_DIR32
));
1497 case CB_SHOWDROPDOWN16
:
1498 case CB_SHOWDROPDOWN32
:
1499 if( CB_GETTYPE(lphc
) != CBS_SIMPLE
) {
1501 if( !(lphc
->wState
& CBF_DROPPED
) )
1504 if( lphc
->wState
& CBF_DROPPED
)
1505 CBRollUp( lphc
, FALSE
, TRUE
);
1512 return SendMessage32A( lphc
->hWndLBox
, LB_GETCOUNT32
, 0, 0);
1514 case CB_GETCURSEL16
:
1515 case CB_GETCURSEL32
:
1516 return SendMessage32A( lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0);
1518 case CB_SETCURSEL16
:
1519 wParam
= (INT32
)(INT16
)wParam
;
1520 case CB_SETCURSEL32
:
1521 return SendMessage32A( lphc
->hWndLBox
, LB_SETCURSEL32
, wParam
, 0);
1523 case CB_GETLBTEXT16
:
1524 wParam
= (INT32
)(INT16
)wParam
;
1525 lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1526 case CB_GETLBTEXT32
:
1527 return SendMessage32A( lphc
->hWndLBox
, LB_GETTEXT32
, wParam
, lParam
);
1529 case CB_GETLBTEXTLEN16
:
1530 wParam
= (INT32
)(INT16
)wParam
;
1531 case CB_GETLBTEXTLEN32
:
1532 return SendMessage32A( lphc
->hWndLBox
, LB_GETTEXTLEN32
, wParam
, 0);
1534 case CB_GETITEMDATA16
:
1535 wParam
= (INT32
)(INT16
)wParam
;
1536 case CB_GETITEMDATA32
:
1537 return SendMessage32A( lphc
->hWndLBox
, LB_GETITEMDATA32
, wParam
, 0);
1539 case CB_SETITEMDATA16
:
1540 wParam
= (INT32
)(INT16
)wParam
;
1541 case CB_SETITEMDATA32
:
1542 return SendMessage32A( lphc
->hWndLBox
, LB_SETITEMDATA32
, wParam
, lParam
);
1544 case CB_GETEDITSEL16
:
1545 wParam
= lParam
= 0; /* just in case */
1546 case CB_GETEDITSEL32
:
1547 if( lphc
->wState
& CBF_EDIT
)
1551 return SendMessage32A( lphc
->hWndEdit
, EM_GETSEL32
,
1552 (wParam
) ? wParam
: (WPARAM32
)&a
,
1553 (lParam
) ? lParam
: (LPARAM
)&b
);
1557 case CB_SETEDITSEL16
:
1558 case CB_SETEDITSEL32
:
1559 if( lphc
->wState
& CBF_EDIT
)
1560 return SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
,
1561 (INT32
)(INT16
)LOWORD(lParam
), (INT32
)(INT16
)HIWORD(lParam
) );
1564 case CB_SETEXTENDEDUI16
:
1565 case CB_SETEXTENDEDUI32
:
1566 if( CB_GETTYPE(lphc
) == CBS_SIMPLE
) return CB_ERR
;
1569 lphc
->wState
|= CBF_EUI
;
1570 else lphc
->wState
&= ~CBF_EUI
;
1573 case CB_GETEXTENDEDUI16
:
1574 case CB_GETEXTENDEDUI32
:
1575 return (lphc
->wState
& CBF_EUI
) ? TRUE
: FALSE
;
1577 case (WM_USER
+ 0x1B):
1578 WARN(combo
, "[%04x]: undocumented msg!\n", hwnd
);
1580 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);