4 * Copyright 1997 Alex Korobka
6 * FIXME: roll up in Netscape 3.01.
13 #include "sysmetrics.h"
25 /* bits in the dwKeyData */
26 #define KEYDATA_ALT 0x2000
27 #define KEYDATA_PREVSTATE 0x4000
30 * Additional combo box definitions
33 #define CB_GETPTR( wnd ) (*(LPHEADCOMBO*)((wnd)->wExtra))
34 #define CB_NOTIFY( lphc, code ) \
35 (SendMessage32A( (lphc)->owner, WM_COMMAND, \
36 MAKEWPARAM((lphc)->self->wIDmenu, (code)), (lphc)->self->hwndSelf))
37 #define CB_GETEDITTEXTLENGTH( lphc ) \
38 (SendMessage32A( (lphc)->hWndEdit, WM_GETTEXTLENGTH, 0, 0 ))
40 static HBITMAP16 hComboBmp
= 0;
41 static UINT16 CBitHeight
, CBitWidth
;
42 static UINT16 CBitOffset
= 8;
44 /***********************************************************************
47 * Load combo button bitmap.
49 static BOOL32
COMBO_Init()
53 if( hComboBmp
) return TRUE
;
54 if( (hDC
= CreateCompatibleDC16(0)) )
57 if( (hComboBmp
= LoadBitmap16(0, MAKEINTRESOURCE(OBM_COMBO
))) )
63 GetObject16( hComboBmp
, sizeof(bm
), &bm
);
64 CBitHeight
= bm
.bmHeight
;
65 CBitWidth
= bm
.bmWidth
;
67 dprintf_combo(stddeb
, "combo bitmap [%i,%i]\n", CBitWidth
, CBitHeight
);
69 hPrevB
= SelectObject16( hDC
, hComboBmp
);
70 SetRect16( &r
, 0, 0, CBitWidth
, CBitHeight
);
71 InvertRect16( hDC
, &r
);
72 SelectObject16( hDC
, hPrevB
);
81 /***********************************************************************
84 static LRESULT
COMBO_NCCreate(WND
* wnd
, LPARAM lParam
)
88 if ( wnd
&& COMBO_Init() &&
89 (lphc
= HeapAlloc(GetProcessHeap(), 0, sizeof(HEADCOMBO
))) )
91 LPCREATESTRUCT32A lpcs
= (CREATESTRUCT32A
*)lParam
;
93 memset( lphc
, 0, sizeof(HEADCOMBO
) );
94 *(LPHEADCOMBO
*)wnd
->wExtra
= lphc
;
96 /* some braindead apps do try to use scrollbar/border flags */
98 lphc
->dwStyle
= (lpcs
->style
& ~(WS_BORDER
| WS_HSCROLL
| WS_VSCROLL
));
99 wnd
->dwStyle
&= ~(WS_BORDER
| WS_HSCROLL
| WS_VSCROLL
);
101 if( !(lpcs
->style
& (CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
)) )
102 lphc
->dwStyle
|= CBS_HASSTRINGS
;
104 dprintf_combo(stddeb
, "COMBO_NCCreate: [0x%08x], style = %08x\n",
105 (UINT32
)lphc
, lphc
->dwStyle
);
107 return (LRESULT
)(UINT32
)wnd
->hwndSelf
;
109 return (LRESULT
)FALSE
;
112 /***********************************************************************
115 static LRESULT
COMBO_NCDestroy( LPHEADCOMBO lphc
)
120 WND
* wnd
= lphc
->self
;
122 dprintf_combo(stddeb
,"Combo [%04x]: freeing storage\n", CB_HWND(lphc
));
124 if( (CB_GETTYPE(lphc
) != CBS_SIMPLE
) && lphc
->hWndLBox
)
125 DestroyWindow32( lphc
->hWndLBox
);
127 HeapFree( GetProcessHeap(), 0, lphc
);
133 /***********************************************************************
136 * Set up component coordinates given valid lphc->RectCombo.
138 static void CBCalcPlacement( LPHEADCOMBO lphc
,
139 LPRECT16 lprEdit
, LPRECT16 lprButton
, LPRECT16 lprLB
)
141 RECT16 rect
= lphc
->RectCombo
;
144 /* get combo height and width */
146 if( lphc
->editHeight
)
147 size
.cy
= (INT16
)lphc
->editHeight
;
150 HDC16 hDC
= GetDC16( lphc
->self
->hwndSelf
);
151 HFONT16 hPrevFont
= (HFONT16
)0;
153 if( lphc
->hFont
) hPrevFont
= SelectObject16( hDC
, lphc
->hFont
);
155 GetTextExtentPoint16( hDC
, "X", 1, &size
);
156 size
.cy
+= size
.cy
/ 4 + 4 * SYSMETRICS_CYBORDER
;
158 if( hPrevFont
) SelectObject16( hDC
, hPrevFont
);
159 ReleaseDC16( lphc
->self
->hwndSelf
, hDC
);
161 size
.cx
= rect
.right
- rect
.left
;
163 if( CB_OWNERDRAWN(lphc
) )
165 UINT16 u
= lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
;
167 if( lphc
->wState
& CBF_MEASUREITEM
) /* first initialization */
169 MEASUREITEMSTRUCT32 mi32
;
171 lphc
->wState
&= ~CBF_MEASUREITEM
;
172 mi32
.CtlType
= ODT_COMBOBOX
;
173 mi32
.CtlID
= lphc
->self
->wIDmenu
;
175 mi32
.itemWidth
= size
.cx
;
176 mi32
.itemHeight
= size
.cy
- 6; /* ownerdrawn cb is taller */
178 SendMessage32A(lphc
->owner
, WM_MEASUREITEM
,
179 (WPARAM32
)mi32
.CtlID
, (LPARAM
)&mi32
);
180 u
= 6 + (UINT16
)mi32
.itemHeight
;
185 /* calculate text and button placement */
187 lprEdit
->left
= lprEdit
->top
= lprButton
->top
= 0;
188 if( CB_GETTYPE(lphc
) == CBS_SIMPLE
) /* no button */
189 lprButton
->left
= lprButton
->right
= lprButton
->bottom
= 0;
192 INT32 i
= size
.cx
- CBitWidth
- 10; /* seems ok */
194 lprButton
->right
= size
.cx
;
195 lprButton
->left
= (INT16
)i
;
196 lprButton
->bottom
= lprButton
->top
+ size
.cy
;
198 if( i
< 0 ) size
.cx
= 0;
199 else size
.cx
= (INT16
)i
;
202 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
)
204 size
.cx
-= CBitOffset
;
205 if( size
.cx
< 0 ) size
.cx
= 0;
208 lprEdit
->right
= size
.cx
; lprEdit
->bottom
= size
.cy
;
210 /* listbox placement */
212 lprLB
->left
= ( CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
) ? 0 : CBitOffset
;
213 lprLB
->top
= lprEdit
->bottom
- SYSMETRICS_CYBORDER
;
214 lprLB
->right
= rect
.right
- rect
.left
;
215 lprLB
->bottom
= rect
.bottom
- rect
.top
;
217 if( lphc
->droppedWidth
> (lprLB
->right
- lprLB
->left
) )
218 lprLB
->right
= lprLB
->left
+ (INT16
)lphc
->droppedWidth
;
220 dprintf_combo(stddeb
,"Combo [%04x]: (%i,%i-%i,%i) placement\n\ttext\t= (%i,%i-%i,%i)\
221 \n\tbutton\t= (%i,%i-%i,%i)\n\tlbox\t= (%i,%i-%i,%i)\n", CB_HWND(lphc
),
222 lphc
->RectCombo
.left
, lphc
->RectCombo
.top
, lphc
->RectCombo
.right
, lphc
->RectCombo
.bottom
,
223 lprEdit
->left
, lprEdit
->top
, lprEdit
->right
, lprEdit
->bottom
,
224 lprButton
->left
, lprButton
->top
, lprButton
->right
, lprButton
->bottom
,
225 lprLB
->left
, lprLB
->top
, lprLB
->right
, lprLB
->bottom
);
229 /***********************************************************************
230 * CBGetDroppedControlRect32
232 static void CBGetDroppedControlRect32( LPHEADCOMBO lphc
, LPRECT32 lpRect
)
234 lpRect
->left
= lphc
->RectCombo
.left
+
235 (lphc
->wState
& CBF_EDIT
) ? CBitOffset
: 0;
236 lpRect
->top
= lphc
->RectCombo
.top
+ lphc
->RectEdit
.bottom
-
238 lpRect
->right
= lphc
->RectCombo
.right
;
239 lpRect
->bottom
= lphc
->RectCombo
.bottom
- SYSMETRICS_CYBORDER
;
242 /***********************************************************************
245 static LRESULT
COMBO_Create( LPHEADCOMBO lphc
, WND
* wnd
, LPARAM lParam
)
247 static char clbName
[] = "ComboLBox";
248 static char editName
[] = "Edit";
250 LPCREATESTRUCT32A lpcs
= (CREATESTRUCT32A
*)lParam
;
252 if( !CB_GETTYPE(lphc
) ) lphc
->dwStyle
|= CBS_SIMPLE
;
253 else if( CB_GETTYPE(lphc
) != CBS_DROPDOWNLIST
) lphc
->wState
|= CBF_EDIT
;
256 lphc
->owner
= lpcs
->hwndParent
;
258 /* M$ IE 3.01 actually creates (and rapidly destroys) an ownerless combobox */
260 if( lphc
->owner
|| !(lpcs
->style
& WS_VISIBLE
) )
263 RECT16 editRect
, btnRect
, lbRect
;
265 GetWindowRect16( wnd
->hwndSelf
, &lphc
->RectCombo
);
267 lphc
->wState
|= CBF_MEASUREITEM
;
268 CBCalcPlacement( lphc
, &editRect
, &btnRect
, &lbRect
);
269 lphc
->RectButton
= btnRect
;
270 lphc
->droppedWidth
= lphc
->editHeight
= 0;
272 /* create listbox popup */
274 lbeStyle
= (LBS_NOTIFY
| WS_BORDER
| WS_CLIPSIBLINGS
) |
275 (lpcs
->style
& (WS_VSCROLL
| CBS_OWNERDRAWFIXED
| CBS_OWNERDRAWVARIABLE
));
277 if( lphc
->dwStyle
& CBS_SORT
)
278 lbeStyle
|= LBS_SORT
;
279 if( lphc
->dwStyle
& CBS_HASSTRINGS
)
280 lbeStyle
|= LBS_HASSTRINGS
;
281 if( lphc
->dwStyle
& CBS_NOINTEGRALHEIGHT
)
282 lbeStyle
|= LBS_NOINTEGRALHEIGHT
;
283 if( lphc
->dwStyle
& CBS_DISABLENOSCROLL
)
284 lbeStyle
|= LBS_DISABLENOSCROLL
;
286 if( CB_GETTYPE(lphc
) == CBS_SIMPLE
) /* child listbox */
287 lbeStyle
|= WS_CHILD
| WS_VISIBLE
;
288 else /* popup listbox */
290 lbeStyle
|= WS_POPUP
;
291 OffsetRect16( &lbRect
, lphc
->RectCombo
.left
, lphc
->RectCombo
.top
);
294 /* Dropdown ComboLBox is not a child window and we cannot pass
295 * ID_CB_LISTBOX directly because it will be treated as a menu handle.
298 lphc
->hWndLBox
= CreateWindowEx32A( 0, clbName
, NULL
, lbeStyle
,
299 lbRect
.left
+ SYSMETRICS_CXBORDER
,
300 lbRect
.top
+ SYSMETRICS_CYBORDER
,
301 lbRect
.right
- lbRect
.left
- 2 * SYSMETRICS_CXBORDER
,
302 lbRect
.bottom
- lbRect
.top
- 2 * SYSMETRICS_CYBORDER
,
303 lphc
->self
->hwndSelf
,
304 (lphc
->dwStyle
& CBS_DROPDOWN
)? (HMENU32
)0 : (HMENU32
)ID_CB_LISTBOX
,
305 lphc
->self
->hInstance
, (LPVOID
)lphc
);
309 lbeStyle
= WS_CHILD
| WS_VISIBLE
| WS_BORDER
| ES_NOHIDESEL
| ES_LEFT
;
310 if( lphc
->wState
& CBF_EDIT
)
312 if( lphc
->dwStyle
& CBS_OEMCONVERT
)
313 lbeStyle
|= ES_OEMCONVERT
;
314 if( lphc
->dwStyle
& CBS_AUTOHSCROLL
)
315 lbeStyle
|= ES_AUTOHSCROLL
;
316 if( lphc
->dwStyle
& CBS_LOWERCASE
)
317 lbeStyle
|= ES_LOWERCASE
;
318 else if( lphc
->dwStyle
& CBS_UPPERCASE
)
319 lbeStyle
|= ES_UPPERCASE
;
320 lphc
->hWndEdit
= CreateWindowEx32A( 0, editName
, NULL
, lbeStyle
,
321 editRect
.left
, editRect
.top
, editRect
.right
- editRect
.left
,
322 editRect
.bottom
- editRect
.top
, lphc
->self
->hwndSelf
,
323 (HMENU32
)ID_CB_EDIT
, lphc
->self
->hInstance
, NULL
);
324 if( !lphc
->hWndEdit
) bEdit
= FALSE
;
329 lphc
->RectEdit
= editRect
;
330 if( CB_GETTYPE(lphc
) != CBS_SIMPLE
)
332 lphc
->wState
|= CBF_NORESIZE
;
333 SetWindowPos32( wnd
->hwndSelf
, 0, 0, 0,
334 lphc
->RectCombo
.right
- lphc
->RectCombo
.left
,
335 lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
,
336 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
337 lphc
->wState
&= ~CBF_NORESIZE
;
339 dprintf_combo(stddeb
,"COMBO_Create: init done\n");
340 return wnd
->hwndSelf
;
342 dprintf_combo(stderr
, "COMBO_Create: edit control failure.\n");
343 } else dprintf_combo(stderr
, "COMBO_Create: listbox failure.\n");
344 } else dprintf_combo(stderr
, "COMBO_Create: no owner for visible combo.\n");
346 /* CreateWindow() will send WM_NCDESTROY to cleanup */
351 /***********************************************************************
354 * Paint combo button (normal, pressed, and disabled states).
356 static void CBPaintButton(LPHEADCOMBO lphc
, HDC16 hdc
)
363 hPrevBrush
= (HBRUSH32
)SelectObject32(hdc
, sysColorObjects
.hbrushBtnFace
);
364 CONV_RECT16TO32( &lphc
->RectButton
, &r
);
366 Rectangle32(hdc
, r
.left
, r
.top
, r
.right
, r
.bottom
);
367 InflateRect32( &r
, -1, -1 );
368 if( (bBool
= lphc
->wState
& CBF_BUTTONDOWN
) )
370 GRAPH_DrawReliefRect(hdc
, &r
, 1, 0, TRUE
);
371 OffsetRect32( &r
, 1, 1 );
372 } else GRAPH_DrawReliefRect(hdc
, &r
, 1, 2, FALSE
);
374 x
= (r
.left
+ r
.right
- CBitWidth
) >> 1;
375 y
= (r
.top
+ r
.bottom
- CBitHeight
) >> 1;
377 InflateRect32( &r
, -3, -3 );
378 if( (bBool
= CB_DISABLED(lphc
)) )
380 GRAPH_SelectClipMask(hdc
, hComboBmp
, x
+ 1, y
+ 1 );
381 FillRect32(hdc
, &r
, (HBRUSH32
)GetStockObject32(WHITE_BRUSH
));
384 GRAPH_SelectClipMask(hdc
, hComboBmp
, x
, y
);
385 FillRect32(hdc
, &r
, (HBRUSH32
)GetStockObject32((bBool
) ? GRAY_BRUSH
: BLACK_BRUSH
));
387 GRAPH_SelectClipMask(hdc
, (HBITMAP32
)0, 0, 0);
388 SelectObject32( hdc
, hPrevBrush
);
391 /***********************************************************************
394 * Paint CBS_DROPDOWNLIST text field / update edit control contents.
396 static void CBPaintText(LPHEADCOMBO lphc
, HDC16 hdc
)
401 /* follow Windows combobox that sends a bunch of text
402 * inquiries to its listbox while processing WM_PAINT. */
404 if( (id
= SendMessage32A(lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0) ) != LB_ERR
)
406 size
= SendMessage32A( lphc
->hWndLBox
, LB_GETTEXTLEN32
, id
, 0);
407 if( (pText
= HeapAlloc( GetProcessHeap(), 0, size
+ 1)) )
409 SendMessage32A( lphc
->hWndLBox
, LB_GETTEXT32
, (WPARAM32
)id
, (LPARAM
)pText
);
410 pText
[size
] = '\0'; /* just in case */
414 if( lphc
->wState
& CBF_EDIT
)
416 if( CB_HASSTRINGS(lphc
) ) SetWindowText32A( lphc
->hWndEdit
, pText
);
417 if( lphc
->wState
& CBF_FOCUSED
)
418 SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
, 0, (LPARAM
)(-1));
420 else /* paint text field ourselves */
422 HBRUSH32 hPrevBrush
= 0;
427 if ((hDC
= GetDC32(lphc
->self
->hwndSelf
)))
429 HBRUSH32 hBrush
= SendMessage32A( lphc
->owner
,
431 hDC
, lphc
->self
->hwndSelf
);
432 hPrevBrush
= SelectObject32( hDC
,
433 (hBrush
) ? hBrush
: GetStockObject32(WHITE_BRUSH
) );
440 HFONT32 hPrevFont
= (lphc
->hFont
) ? SelectObject32(hDC
, lphc
->hFont
) : 0;
442 PatBlt32( hDC
, (rect
.left
= lphc
->RectEdit
.left
+ SYSMETRICS_CXBORDER
),
443 (rect
.top
= lphc
->RectEdit
.top
+ SYSMETRICS_CYBORDER
),
444 (rect
.right
= lphc
->RectEdit
.right
- SYSMETRICS_CXBORDER
),
445 (rect
.bottom
= lphc
->RectEdit
.bottom
- SYSMETRICS_CYBORDER
) - 1, PATCOPY
);
446 InflateRect32( &rect
, -1, -1 );
448 if( lphc
->wState
& CBF_FOCUSED
&&
449 !(lphc
->wState
& CBF_DROPPED
) )
453 FillRect32( hDC
, &rect
, sysColorObjects
.hbrushHighlight
);
454 SetBkColor32( hDC
, GetSysColor32( COLOR_HIGHLIGHT
) );
455 SetTextColor32( hDC
, GetSysColor32( COLOR_HIGHLIGHTTEXT
) );
456 itemState
= ODS_SELECTED
| ODS_FOCUS
;
457 } else itemState
= 0;
459 if( CB_OWNERDRAWN(lphc
) )
461 DRAWITEMSTRUCT32 dis
;
463 if( lphc
->self
->dwStyle
& WS_DISABLED
) itemState
|= ODS_DISABLED
;
465 dis
.CtlType
= ODT_COMBOBOX
;
466 dis
.CtlID
= lphc
->self
->wIDmenu
;
467 dis
.hwndItem
= lphc
->self
->hwndSelf
;
468 dis
.itemAction
= ODA_DRAWENTIRE
;
470 dis
.itemState
= itemState
;
473 dis
.itemData
= SendMessage32A( lphc
->hWndLBox
, LB_GETITEMDATA32
,
475 SendMessage32A( lphc
->owner
, WM_DRAWITEM
,
476 lphc
->self
->wIDmenu
, (LPARAM
)&dis
);
480 ExtTextOut32A( hDC
, rect
.left
+ 1, rect
.top
+ 1,
481 ETO_OPAQUE
| ETO_CLIPPED
, &rect
,
482 (pText
) ? pText
: "" , size
, NULL
);
483 if(lphc
->wState
& CBF_FOCUSED
&& !(lphc
->wState
& CBF_DROPPED
))
484 DrawFocusRect32( hDC
, &rect
);
487 if( hPrevFont
) SelectObject32(hDC
, hPrevFont
);
490 if( hPrevBrush
) SelectObject32( hDC
, hPrevBrush
);
491 ReleaseDC32( lphc
->self
->hwndSelf
, hDC
);
495 HeapFree( GetProcessHeap(), 0, pText
);
498 /***********************************************************************
501 static LRESULT
COMBO_Paint(LPHEADCOMBO lphc
, HDC16 hParamDC
)
506 hDC
= (hParamDC
) ? hParamDC
507 : BeginPaint16( lphc
->self
->hwndSelf
, &ps
);
508 if( hDC
&& !(lphc
->self
->flags
& WIN_NO_REDRAW
) )
510 HBRUSH32 hPrevBrush
, hBkgBrush
;
512 hBkgBrush
= SendMessage32A( lphc
->owner
, WM_CTLCOLORLISTBOX
,
513 hDC
, lphc
->self
->hwndSelf
);
514 if( !hBkgBrush
) hBkgBrush
= GetStockObject32(WHITE_BRUSH
);
516 hPrevBrush
= SelectObject32( hDC
, hBkgBrush
);
517 if( !IsRectEmpty16(&lphc
->RectButton
) )
519 /* paint everything to the right of the text field */
521 PatBlt32( hDC
, lphc
->RectEdit
.right
, lphc
->RectEdit
.top
,
522 lphc
->RectButton
.right
- lphc
->RectEdit
.right
,
523 lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
, PATCOPY
);
524 CBPaintButton( lphc
, hDC
);
527 if( !(lphc
->wState
& CBF_EDIT
) )
529 /* paint text field */
531 GRAPH_DrawRectangle( hDC
, lphc
->RectEdit
.left
, lphc
->RectEdit
.top
,
532 lphc
->RectEdit
.right
- lphc
->RectEdit
.left
,
533 lphc
->RectButton
.bottom
- lphc
->RectButton
.top
,
534 sysColorObjects
.hpenWindowFrame
);
535 CBPaintText( lphc
, hDC
);
537 if( hPrevBrush
) SelectObject32( hDC
, hPrevBrush
);
539 if( !hParamDC
) EndPaint16(lphc
->self
->hwndSelf
, &ps
);
543 /***********************************************************************
546 * Select listbox entry according to the contents of the edit control.
548 static INT32
CBUpdateLBox( LPHEADCOMBO lphc
)
550 INT32 length
, idx
, ret
;
554 length
= CB_GETEDITTEXTLENGTH( lphc
);
557 pText
= (LPSTR
) HeapAlloc( GetProcessHeap(), 0, length
+ 1);
559 dprintf_combo(stddeb
,"\tCBUpdateLBox: edit text length %i\n", length
);
563 if( length
) GetWindowText32A( lphc
->hWndEdit
, pText
, length
+ 1);
564 else pText
[0] = '\0';
565 idx
= SendMessage32A( lphc
->hWndLBox
, LB_FINDSTRING32
,
566 (WPARAM32
)(-1), (LPARAM
)pText
);
567 if( idx
== LB_ERR
) idx
= 0; /* select first item */
569 HeapFree( GetProcessHeap(), 0, pText
);
574 SendMessage32A( lphc
->hWndLBox
, LB_SETCURSEL32
, (WPARAM32
)idx
, 0 );
578 SendMessage32A( lphc
->hWndLBox
, LB_SETTOPINDEX32
, (WPARAM32
)idx
, 0 );
579 /* probably superfluous but Windows sends this too */
580 SendMessage32A( lphc
->hWndLBox
, LB_SETCARETINDEX32
, (WPARAM32
)idx
, 0 );
585 /***********************************************************************
588 * Copy a listbox entry to the edit control.
590 static void CBUpdateEdit( LPHEADCOMBO lphc
, INT32 index
)
595 dprintf_combo(stddeb
,"\tCBUpdateEdit: %i\n", index
);
599 length
= CB_GETEDITTEXTLENGTH( lphc
);
602 if( (pText
= (LPSTR
) HeapAlloc( GetProcessHeap(), 0, length
+ 1)) )
604 GetWindowText32A( lphc
->hWndEdit
, pText
, length
+ 1 );
605 index
= SendMessage32A( lphc
->hWndLBox
, LB_FINDSTRING32
,
606 (WPARAM32
)(-1), (LPARAM
)pText
);
607 HeapFree( GetProcessHeap(), 0, pText
);
612 if( index
>= 0 ) /* got an entry */
614 length
= SendMessage32A( lphc
->hWndLBox
, LB_GETTEXTLEN32
, (WPARAM32
)index
, 0);
617 if( (pText
= (LPSTR
) HeapAlloc( GetProcessHeap(), 0, length
+ 1)) )
619 SendMessage32A( lphc
->hWndLBox
, LB_GETTEXT32
,
620 (WPARAM32
)index
, (LPARAM
)pText
);
621 SendMessage32A( lphc
->hWndEdit
, WM_SETTEXT
, 0, (LPARAM
)pText
);
622 SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
, 0, (LPARAM
)(-1) );
623 HeapFree( GetProcessHeap(), 0, pText
);
629 /***********************************************************************
632 * Show listbox popup.
634 static void CBDropDown( LPHEADCOMBO lphc
)
638 LPRECT16 pRect
= NULL
;
640 dprintf_combo(stddeb
,"Combo [%04x]: drop down\n", CB_HWND(lphc
));
642 CB_NOTIFY( lphc
, CBN_DROPDOWN
);
646 lphc
->wState
|= CBF_DROPPED
;
647 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
)
649 index
= CBUpdateLBox( lphc
);
650 if( !(lphc
->wState
& CBF_CAPTURE
) ) CBUpdateEdit( lphc
, index
);
654 index
= SendMessage32A( lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0 );
655 if( index
== LB_ERR
) index
= 0;
656 SendMessage32A( lphc
->hWndLBox
, LB_SETTOPINDEX32
, (WPARAM32
)index
, 0 );
657 SendMessage32A( lphc
->hWndLBox
, LB_CARETON32
, 0, 0 );
658 pRect
= &lphc
->RectEdit
;
661 /* now set popup position */
663 GetWindowRect16( lphc
->self
->hwndSelf
, &rect
);
665 rect
.top
+= lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
- SYSMETRICS_CYBORDER
;
666 rect
.bottom
= rect
.top
+ lphc
->RectCombo
.bottom
-
667 lphc
->RectCombo
.top
- SYSMETRICS_CYBORDER
;
668 rect
.right
= rect
.left
+ lphc
->RectCombo
.right
- lphc
->RectCombo
.left
;
669 rect
.left
+= ( CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
) ? 0 : CBitOffset
;
671 SetWindowPos32( lphc
->hWndLBox
, HWND_TOP
, rect
.left
, rect
.top
,
672 rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
673 SWP_NOACTIVATE
| SWP_NOSIZE
);
675 RedrawWindow16( lphc
->self
->hwndSelf
, pRect
, 0, RDW_INVALIDATE
|
676 RDW_ERASE
| RDW_UPDATENOW
| RDW_NOCHILDREN
);
677 ShowWindow32( lphc
->hWndLBox
, SW_SHOWNA
);
680 /***********************************************************************
683 * Hide listbox popup.
685 static void CBRollUp( LPHEADCOMBO lphc
, BOOL32 ok
, BOOL32 bButton
)
687 HWND32 hWnd
= lphc
->self
->hwndSelf
;
689 CB_NOTIFY( lphc
, (ok
) ? CBN_SELENDOK
: CBN_SELENDCANCEL
);
691 if( IsWindow32( hWnd
) && CB_GETTYPE(lphc
) != CBS_SIMPLE
)
694 dprintf_combo(stddeb
,"Combo [%04x]: roll up [%i]\n", CB_HWND(lphc
), (INT32
)ok
);
696 /* always send WM_LBUTTONUP? */
697 SendMessage32A( lphc
->hWndLBox
, WM_LBUTTONUP
, 0, (LPARAM
)(-1) );
699 if( lphc
->wState
& CBF_DROPPED
)
703 lphc
->wState
&= ~CBF_DROPPED
;
704 ShowWindow32( lphc
->hWndLBox
, SW_HIDE
);
706 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
)
708 INT32 index
= SendMessage32A( lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0 );
709 CBUpdateEdit( lphc
, index
);
710 rect
= lphc
->RectButton
;
715 UnionRect16( &rect
, &lphc
->RectButton
,
718 rect
= lphc
->RectEdit
;
723 RedrawWindow16( hWnd
, &rect
, 0, RDW_INVALIDATE
|
724 RDW_ERASE
| RDW_UPDATENOW
| RDW_NOCHILDREN
);
725 CB_NOTIFY( lphc
, CBN_CLOSEUP
);
730 /***********************************************************************
733 * Used by the ComboLBox to show/hide itself in response to VK_F4, etc...
735 BOOL32
COMBO_FlipListbox( LPHEADCOMBO lphc
, BOOL32 bRedrawButton
)
737 if( lphc
->wState
& CBF_DROPPED
)
739 CBRollUp( lphc
, TRUE
, bRedrawButton
);
747 /***********************************************************************
750 * Edit control helper.
752 HWND32
COMBO_GetLBWindow( WND
* pWnd
)
754 LPHEADCOMBO lphc
= CB_GETPTR(pWnd
);
755 if( lphc
) return lphc
->hWndLBox
;
760 /***********************************************************************
763 static void CBRepaintButton( LPHEADCOMBO lphc
)
765 HDC32 hDC
= GetDC32( lphc
->self
->hwndSelf
);
769 CBPaintButton( lphc
, (HDC16
)hDC
);
770 ReleaseDC32( lphc
->self
->hwndSelf
, hDC
);
774 /***********************************************************************
777 static void COMBO_SetFocus( LPHEADCOMBO lphc
)
779 if( !(lphc
->wState
& CBF_FOCUSED
) )
781 if( CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
)
782 SendMessage32A( lphc
->hWndLBox
, LB_CARETON32
, 0, 0 );
784 if( lphc
->wState
& CBF_EDIT
)
785 SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
, 0, (LPARAM
)(-1) );
786 lphc
->wState
|= CBF_FOCUSED
;
787 if( !(lphc
->wState
& CBF_EDIT
) ) CBPaintText( lphc
, 0 );
789 CB_NOTIFY( lphc
, CBN_SETFOCUS
);
793 /***********************************************************************
796 static void COMBO_KillFocus( LPHEADCOMBO lphc
)
798 HWND32 hWnd
= lphc
->self
->hwndSelf
;
800 if( lphc
->wState
& CBF_FOCUSED
)
802 SendMessage32A( hWnd
, WM_LBUTTONUP
, 0, (LPARAM
)(-1) );
804 CBRollUp( lphc
, FALSE
, TRUE
);
805 if( IsWindow32( hWnd
) )
807 if( CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
)
808 SendMessage32A( lphc
->hWndLBox
, LB_CARETOFF32
, 0, 0 );
810 lphc
->wState
&= ~CBF_FOCUSED
;
813 if( lphc
->wState
& CBF_EDIT
)
814 SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
, (WPARAM32
)(-1), 0 );
815 else CBPaintText( lphc
, 0 );
817 CB_NOTIFY( lphc
, CBN_KILLFOCUS
);
822 /***********************************************************************
825 static LRESULT
COMBO_Command( LPHEADCOMBO lphc
, WPARAM32 wParam
, HWND32 hWnd
)
827 if( lphc
->wState
& CBF_EDIT
&& lphc
->hWndEdit
== hWnd
)
829 /* ">> 8" makes gcc generate jump-table instead of cmp ladder */
831 switch( HIWORD(wParam
) >> 8 )
833 case (EN_SETFOCUS
>> 8):
835 dprintf_combo(stddeb
,"Combo [%04x]: edit [%04x] got focus\n",
836 CB_HWND(lphc
), (HWND16
)lphc
->hWndEdit
);
838 if( !(lphc
->wState
& CBF_FOCUSED
) ) COMBO_SetFocus( lphc
);
841 case (EN_KILLFOCUS
>> 8):
843 dprintf_combo(stddeb
,"Combo [%04x]: edit [%04x] lost focus\n",
844 CB_HWND(lphc
), (HWND16
)lphc
->hWndEdit
);
846 /* NOTE: it seems that Windows' edit control sends an
847 * undocumented message WM_USER + 0x1B instead of this
848 * notification (only when it happens to be a part of
849 * the combo). ?? - AK.
852 COMBO_KillFocus( lphc
);
856 case (EN_CHANGE
>> 8):
857 CB_NOTIFY( lphc
, CBN_EDITCHANGE
);
858 CBUpdateLBox( lphc
);
861 case (EN_UPDATE
>> 8):
862 CB_NOTIFY( lphc
, CBN_EDITUPDATE
);
865 case (EN_ERRSPACE
>> 8):
866 CB_NOTIFY( lphc
, CBN_ERRSPACE
);
869 else if( lphc
->hWndLBox
== hWnd
)
871 switch( HIWORD(wParam
) )
874 CB_NOTIFY( lphc
, CBN_ERRSPACE
);
878 CB_NOTIFY( lphc
, CBN_DBLCLK
);
884 dprintf_combo(stddeb
,"Combo [%04x]: lbox selection change [%04x]\n",
885 CB_HWND(lphc
), lphc
->wState
);
887 /* do not roll up if selection is being tracked
888 * by arrowkeys in the dropdown listbox */
890 if( (lphc
->wState
& CBF_DROPPED
) && !(lphc
->wState
& CBF_NOROLLUP
) )
891 CBRollUp( lphc
, (HIWORD(wParam
) == LBN_SELCHANGE
), TRUE
);
892 else lphc
->wState
&= ~CBF_NOROLLUP
;
894 CB_NOTIFY( lphc
, CBN_SELCHANGE
);
895 CBPaintText( lphc
, 0 );
900 /* nothing to do here since ComboLBox always resets the focus to its
901 * combo/edit counterpart */
907 /***********************************************************************
910 * Fixup an ownerdrawn item operation and pass it up to the combobox owner.
912 static LRESULT
COMBO_ItemOp32( LPHEADCOMBO lphc
, UINT32 msg
,
913 WPARAM32 wParam
, LPARAM lParam
)
915 HWND32 hWnd
= lphc
->self
->hwndSelf
;
917 dprintf_combo(stddeb
,"Combo [%04x]: ownerdraw op %04x\n",
918 CB_HWND(lphc
), (UINT16
)msg
);
920 #define lpIS ((LPDELETEITEMSTRUCT32)lParam)
922 /* two first items are the same in all 4 structs */
923 lpIS
->CtlType
= ODT_COMBOBOX
;
924 lpIS
->CtlID
= lphc
->self
->wIDmenu
;
926 switch( msg
) /* patch window handle */
929 lpIS
->hwndItem
= hWnd
;
933 #define lpIS ((LPDRAWITEMSTRUCT32)lParam)
934 lpIS
->hwndItem
= hWnd
;
938 #define lpIS ((LPCOMPAREITEMSTRUCT32)lParam)
939 lpIS
->hwndItem
= hWnd
;
944 return SendMessage32A( lphc
->owner
, msg
, lphc
->self
->wIDmenu
, lParam
);
947 /***********************************************************************
950 static LRESULT
COMBO_GetText( LPHEADCOMBO lphc
, UINT32 N
, LPSTR lpText
)
954 if( lphc
->wState
& CBF_EDIT
)
955 return SendMessage32A( lphc
->hWndEdit
, WM_GETTEXT
,
956 (WPARAM32
)N
, (LPARAM
)lpText
);
958 /* get it from the listbox */
960 idx
= SendMessage32A( lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0 );
964 INT32 length
= SendMessage32A( lphc
->hWndLBox
, LB_GETTEXTLEN32
,
967 /* 'length' is without the terminating character */
969 lpBuffer
= (LPSTR
) HeapAlloc( GetProcessHeap(), 0, length
+ 1 );
975 INT32 n
= SendMessage32A( lphc
->hWndLBox
, LB_GETTEXT32
,
976 (WPARAM32
)idx
, (LPARAM
)lpText
);
978 /* truncate if buffer is too short */
982 if( n
!= LB_ERR
) memcpy( lpText
, lpBuffer
, (N
>n
) ? n
+1 : N
-1 );
983 lpText
[N
- 1] = '\0';
984 HeapFree( GetProcessHeap(), 0, lpBuffer
);
993 /***********************************************************************
996 * This function sets window positions according to the updated
997 * component placement struct.
999 static void CBResetPos( LPHEADCOMBO lphc
, LPRECT16 lbRect
, BOOL32 bRedraw
)
1001 BOOL32 bDrop
= (CB_GETTYPE(lphc
) != CBS_SIMPLE
);
1003 /* NOTE: logs sometimes have WM_LBUTTONUP before a cascade of
1004 * sizing messages */
1006 if( lphc
->wState
& CBF_EDIT
)
1007 SetWindowPos32( lphc
->hWndEdit
, 0, lphc
->RectEdit
.left
, lphc
->RectEdit
.top
,
1008 lphc
->RectEdit
.right
- lphc
->RectEdit
.left
,
1009 lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
,
1010 SWP_NOZORDER
| SWP_NOACTIVATE
| ((bDrop
) ? SWP_NOREDRAW
: 0) );
1013 OffsetRect16( lbRect
, lphc
->RectCombo
.left
, lphc
->RectCombo
.top
);
1015 lbRect
->right
-= lbRect
->left
; /* convert to width */
1016 lbRect
->bottom
-= lbRect
->top
;
1017 SetWindowPos32( lphc
->hWndLBox
, 0, lbRect
->left
, lbRect
->top
,
1018 lbRect
->right
, lbRect
->bottom
,
1019 SWP_NOACTIVATE
| SWP_NOZORDER
| ((bDrop
) ? SWP_NOREDRAW
: 0) );
1023 if( lphc
->wState
& CBF_DROPPED
)
1025 lphc
->wState
&= ~CBF_DROPPED
;
1026 ShowWindow32( lphc
->hWndLBox
, SW_HIDE
);
1029 lphc
->wState
|= CBF_NORESIZE
;
1030 SetWindowPos32( lphc
->self
->hwndSelf
, 0, 0, 0,
1031 lphc
->RectCombo
.right
- lphc
->RectCombo
.left
,
1032 lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
,
1033 SWP_NOMOVE
| SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_NOREDRAW
);
1034 lphc
->wState
&= ~CBF_NORESIZE
;
1036 RedrawWindow32( lphc
->self
->hwndSelf
, NULL
, 0,
1037 RDW_INVALIDATE
| RDW_ERASE
| RDW_UPDATENOW
);
1042 /***********************************************************************
1045 static void COMBO_Size( LPHEADCOMBO lphc
)
1050 GetWindowRect16( lphc
->self
->hwndSelf
, &rect
);
1051 w
= rect
.right
- rect
.left
; h
= rect
.bottom
- rect
.top
;
1053 dprintf_combo(stddeb
,"COMBO_Size: w = %i, h = %i\n", w
, h
);
1055 /* CreateWindow() may send a bogus WM_SIZE, ignore it */
1057 if( w
== (lphc
->RectCombo
.right
- lphc
->RectCombo
.left
) )
1058 if( (CB_GETTYPE(lphc
) == CBS_SIMPLE
) &&
1059 (h
== (lphc
->RectCombo
.bottom
- lphc
->RectCombo
.top
)) )
1061 else if( (lphc
->dwStyle
& CBS_DROPDOWN
) &&
1062 (h
== (lphc
->RectEdit
.bottom
- lphc
->RectEdit
.top
)) )
1065 lphc
->RectCombo
= rect
;
1066 CBCalcPlacement( lphc
, &lphc
->RectEdit
, &lphc
->RectButton
, &rect
);
1067 CBResetPos( lphc
, &rect
, TRUE
);
1071 /***********************************************************************
1074 static void COMBO_Font( LPHEADCOMBO lphc
, HFONT16 hFont
, BOOL32 bRedraw
)
1078 lphc
->hFont
= hFont
;
1080 if( lphc
->wState
& CBF_EDIT
)
1081 SendMessage32A( lphc
->hWndEdit
, WM_SETFONT
, (WPARAM32
)hFont
, bRedraw
);
1082 SendMessage32A( lphc
->hWndLBox
, WM_SETFONT
, (WPARAM32
)hFont
, bRedraw
);
1084 GetWindowRect16( lphc
->self
->hwndSelf
, &rect
);
1085 OffsetRect16( &lphc
->RectCombo
, rect
.left
- lphc
->RectCombo
.left
,
1086 rect
.top
- lphc
->RectCombo
.top
);
1087 CBCalcPlacement( lphc
, &lphc
->RectEdit
,
1088 &lphc
->RectButton
, &rect
);
1089 CBResetPos( lphc
, &rect
, bRedraw
);
1093 /***********************************************************************
1094 * COMBO_SetItemHeight
1096 static LRESULT
COMBO_SetItemHeight( LPHEADCOMBO lphc
, INT32 index
, INT32 height
)
1098 LRESULT lRet
= CB_ERR
;
1100 if( index
== -1 ) /* set text field height */
1102 if( height
< 32768 )
1106 lphc
->editHeight
= height
;
1107 GetWindowRect16( lphc
->self
->hwndSelf
, &rect
);
1108 OffsetRect16( &lphc
->RectCombo
, rect
.left
- lphc
->RectCombo
.left
,
1109 rect
.top
- lphc
->RectCombo
.top
);
1110 CBCalcPlacement( lphc
, &lphc
->RectEdit
,
1111 &lphc
->RectButton
, &rect
);
1112 CBResetPos( lphc
, &rect
, TRUE
);
1116 else if ( CB_OWNERDRAWN(lphc
) ) /* set listbox item height */
1117 lRet
= SendMessage32A( lphc
->hWndLBox
, LB_SETITEMHEIGHT32
,
1118 (WPARAM32
)index
, (LPARAM
)height
);
1122 /***********************************************************************
1123 * COMBO_SelectString
1125 static LRESULT
COMBO_SelectString( LPHEADCOMBO lphc
, INT32 start
, LPCSTR pText
)
1127 INT32 index
= SendMessage32A( lphc
->hWndLBox
, CB_SELECTSTRING32
,
1128 (WPARAM32
)start
, (LPARAM
)pText
);
1130 if( lphc
->wState
& CBF_EDIT
)
1131 CBUpdateEdit( lphc
, index
);
1133 CBPaintText( lphc
, 0 );
1134 return (LRESULT
)index
;
1137 /***********************************************************************
1140 static void COMBO_LButtonDown( LPHEADCOMBO lphc
, LPARAM lParam
)
1142 BOOL32 bButton
= PtInRect16(&lphc
->RectButton
, MAKEPOINT16(lParam
));
1143 HWND32 hWnd
= lphc
->self
->hwndSelf
;
1145 if( (CB_GETTYPE(lphc
) == CBS_DROPDOWNLIST
) ||
1146 (bButton
&& (CB_GETTYPE(lphc
) == CBS_DROPDOWN
)) )
1148 lphc
->wState
|= CBF_BUTTONDOWN
;
1149 if( lphc
->wState
& CBF_DROPPED
)
1151 /* got a click to cancel selection */
1153 CBRollUp( lphc
, TRUE
, FALSE
);
1154 if( !IsWindow32( hWnd
) ) return;
1156 if( lphc
->wState
& CBF_CAPTURE
)
1158 lphc
->wState
&= ~CBF_CAPTURE
;
1161 lphc
->wState
&= ~CBF_BUTTONDOWN
;
1165 /* drop down the listbox and start tracking */
1167 lphc
->wState
|= CBF_CAPTURE
;
1169 SetCapture32( hWnd
);
1171 if( bButton
) CBRepaintButton( lphc
);
1175 /***********************************************************************
1178 * Release capture and stop tracking if needed.
1180 static void COMBO_LButtonUp( LPHEADCOMBO lphc
, LPARAM lParam
)
1182 if( lphc
->wState
& CBF_CAPTURE
)
1184 lphc
->wState
&= ~CBF_CAPTURE
;
1185 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
)
1187 INT32 index
= CBUpdateLBox( lphc
);
1188 CBUpdateEdit( lphc
, index
);
1193 if( lphc
->wState
& CBF_BUTTONDOWN
)
1195 lphc
->wState
&= ~CBF_BUTTONDOWN
;
1196 CBRepaintButton( lphc
);
1200 /***********************************************************************
1203 * Two things to do - track combo button and release capture when
1204 * pointer goes into the listbox.
1206 static void COMBO_MouseMove( LPHEADCOMBO lphc
, WPARAM32 wParam
, LPARAM lParam
)
1210 if( lphc
->wState
& CBF_BUTTONDOWN
)
1212 BOOL32 bButton
= PtInRect16(&lphc
->RectButton
, MAKEPOINT16(lParam
));
1216 lphc
->wState
&= ~CBF_BUTTONDOWN
;
1217 CBRepaintButton( lphc
);
1221 GetClientRect16( lphc
->hWndLBox
, &lbRect
);
1222 MapWindowPoints16( lphc
->self
->hwndSelf
,
1223 lphc
->hWndLBox
, (LPPOINT16
)&lParam
, 1 );
1224 if( PtInRect16(&lbRect
, MAKEPOINT16(lParam
)) )
1226 lphc
->wState
&= ~CBF_CAPTURE
;
1228 if( CB_GETTYPE(lphc
) == CBS_DROPDOWN
) CBUpdateLBox( lphc
);
1230 /* hand over pointer tracking */
1231 SendMessage32A( lphc
->hWndLBox
, WM_LBUTTONDOWN
, wParam
, lParam
);
1236 /***********************************************************************
1239 * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/ctrl/src/combobox_15.htm
1241 LRESULT
ComboWndProc(HWND32 hwnd
, UINT32 message
, WPARAM32 wParam
, LPARAM lParam
)
1243 WND
* pWnd
= WIN_FindWndPtr(hwnd
);
1247 LPHEADCOMBO lphc
= CB_GETPTR(pWnd
);
1249 dprintf_combo( stddeb
, "Combo [%04x]: msg %s wp %08x lp %08lx\n",
1250 pWnd
->hwndSelf
, SPY_GetMsgName(message
), wParam
, lParam
);
1252 if( lphc
|| message
== WM_NCCREATE
)
1256 /* System messages */
1259 return COMBO_NCCreate(pWnd
, lParam
);
1262 COMBO_NCDestroy(lphc
);
1266 return COMBO_Create(lphc
, pWnd
, lParam
);
1269 /* wParam may contain a valid HDC! */
1270 return COMBO_Paint(lphc
, (HDC16
)wParam
);
1276 return (LRESULT
)(DLGC_WANTARROWS
| DLGC_WANTCHARS
);
1279 if( lphc
->hWndLBox
&&
1280 !(lphc
->wState
& CBF_NORESIZE
) ) COMBO_Size( lphc
);
1284 COMBO_Font( lphc
, (HFONT16
)wParam
, (BOOL32
)lParam
);
1288 return (LRESULT
)lphc
->hFont
;
1291 if( lphc
->wState
& CBF_EDIT
)
1292 SetFocus32( lphc
->hWndEdit
);
1294 COMBO_SetFocus( lphc
);
1298 #define hwndFocus ((HWND16)wParam)
1300 (hwndFocus
!= lphc
->hWndEdit
&& hwndFocus
!= lphc
->hWndLBox
))
1301 COMBO_KillFocus( lphc
);
1306 return COMBO_Command( lphc
, wParam
, (HWND32
)lParam
);
1309 return COMBO_GetText( lphc
, (UINT32
)wParam
, (LPSTR
)lParam
);
1312 case WM_GETTEXTLENGTH
:
1317 if( lphc
->wState
& CBF_EDIT
)
1318 return SendMessage32A( lphc
->hWndEdit
, message
, wParam
, lParam
);
1323 case WM_COMPAREITEM
:
1324 case WM_MEASUREITEM
:
1325 return COMBO_ItemOp32( lphc
, message
, wParam
, lParam
);
1328 if( lphc
->wState
& CBF_EDIT
)
1329 EnableWindow32( lphc
->hWndEdit
, (BOOL32
)wParam
);
1330 EnableWindow32( lphc
->hWndLBox
, (BOOL32
)wParam
);
1334 if( lphc
->wState
& CBF_EDIT
)
1335 SendMessage32A( lphc
->hWndEdit
, message
, wParam
, lParam
);
1336 SendMessage32A( lphc
->hWndLBox
, message
, wParam
, lParam
);
1340 if( KEYDATA_ALT
& HIWORD(lParam
) )
1341 if( wParam
== VK_UP
|| wParam
== VK_DOWN
)
1342 COMBO_FlipListbox( lphc
, TRUE
);
1347 if( lphc
->wState
& CBF_EDIT
)
1348 return SendMessage32A( lphc
->hWndEdit
, message
, wParam
, lParam
);
1350 return SendMessage32A( lphc
->hWndLBox
, message
, wParam
, lParam
);
1352 case WM_LBUTTONDOWN
:
1353 if( !(lphc
->wState
& CBF_FOCUSED
) ) SetFocus32( lphc
->self
->hwndSelf
);
1354 if( lphc
->wState
& CBF_FOCUSED
) COMBO_LButtonDown( lphc
, lParam
);
1358 COMBO_LButtonUp( lphc
, lParam
);
1362 if( lphc
->wState
& CBF_CAPTURE
)
1363 COMBO_MouseMove( lphc
, wParam
, lParam
);
1366 /* Combo messages */
1368 case CB_ADDSTRING16
:
1369 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1370 case CB_ADDSTRING32
:
1371 return SendMessage32A( lphc
->hWndLBox
, LB_ADDSTRING32
, 0, lParam
);
1373 case CB_INSERTSTRING16
:
1374 wParam
= (INT32
)(INT16
)wParam
;
1375 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1376 case CB_INSERTSTRING32
:
1377 return SendMessage32A( lphc
->hWndLBox
, LB_INSERTSTRING32
, wParam
, lParam
);
1379 case CB_DELETESTRING16
:
1380 case CB_DELETESTRING32
:
1381 return SendMessage32A( lphc
->hWndLBox
, LB_DELETESTRING32
, wParam
, 0);
1383 case CB_SELECTSTRING16
:
1384 wParam
= (INT32
)(INT16
)wParam
;
1385 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1386 case CB_SELECTSTRING32
:
1387 return COMBO_SelectString( lphc
, (INT32
)wParam
, (LPSTR
)lParam
);
1389 case CB_FINDSTRING16
:
1390 wParam
= (INT32
)(INT16
)wParam
;
1391 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1392 case CB_FINDSTRING32
:
1393 return SendMessage32A( lphc
->hWndLBox
, LB_FINDSTRING32
, wParam
, lParam
);
1395 case CB_FINDSTRINGEXACT16
:
1396 wParam
= (INT32
)(INT16
)wParam
;
1397 if( CB_HASSTRINGS(lphc
) ) lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1398 case CB_FINDSTRINGEXACT32
:
1399 return SendMessage32A( lphc
->hWndLBox
, LB_FINDSTRINGEXACT32
,
1401 case CB_SETITEMHEIGHT16
:
1402 wParam
= (INT32
)(INT16
)wParam
;
1403 case CB_SETITEMHEIGHT32
:
1404 return COMBO_SetItemHeight( lphc
, (INT32
)wParam
, (INT32
)lParam
);
1406 case CB_RESETCONTENT16
:
1407 case CB_RESETCONTENT32
:
1408 SendMessage32A( lphc
->hWndLBox
, LB_RESETCONTENT32
, 0, 0 );
1409 CBPaintText( lphc
, 0 );
1412 case CB_INITSTORAGE32
:
1413 return SendMessage32A( lphc
->hWndLBox
, LB_INITSTORAGE32
, wParam
, lParam
);
1415 case CB_GETHORIZONTALEXTENT32
:
1416 return SendMessage32A( lphc
->hWndLBox
, LB_GETHORIZONTALEXTENT32
, 0, 0);
1418 case CB_SETHORIZONTALEXTENT32
:
1419 return SendMessage32A( lphc
->hWndLBox
, LB_SETHORIZONTALEXTENT32
, wParam
, 0);
1421 case CB_GETTOPINDEX32
:
1422 return SendMessage32A( lphc
->hWndLBox
, LB_GETTOPINDEX32
, 0, 0);
1424 case CB_GETLOCALE32
:
1425 return SendMessage32A( lphc
->hWndLBox
, LB_GETLOCALE32
, 0, 0);
1427 case CB_SETLOCALE32
:
1428 return SendMessage32A( lphc
->hWndLBox
, LB_SETLOCALE32
, wParam
, 0);
1430 case CB_GETDROPPEDWIDTH32
:
1431 if( lphc
->droppedWidth
)
1432 return lphc
->droppedWidth
;
1433 return lphc
->RectCombo
.right
- lphc
->RectCombo
.left
-
1434 (lphc
->wState
& CBF_EDIT
) ? CBitOffset
: 0;
1436 case CB_SETDROPPEDWIDTH32
:
1437 if( (CB_GETTYPE(lphc
) != CBS_SIMPLE
) &&
1438 (INT32
)wParam
< 32768 ) lphc
->droppedWidth
= (INT32
)wParam
;
1441 case CB_GETDROPPEDCONTROLRECT16
:
1442 lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1446 CBGetDroppedControlRect32( lphc
, &r
);
1447 CONV_RECT32TO16( &r
, (LPRECT16
)lParam
);
1451 case CB_GETDROPPEDCONTROLRECT32
:
1452 if( lParam
) CBGetDroppedControlRect32(lphc
, (LPRECT32
)lParam
);
1455 case CB_GETDROPPEDSTATE16
:
1456 case CB_GETDROPPEDSTATE32
:
1457 return (lphc
->wState
& CBF_DROPPED
) ? TRUE
: FALSE
;
1460 lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1463 return COMBO_Directory( lphc
, (UINT32
)wParam
,
1464 (LPSTR
)lParam
, (message
== CB_DIR32
));
1465 case CB_SHOWDROPDOWN16
:
1466 case CB_SHOWDROPDOWN32
:
1467 if( CB_GETTYPE(lphc
) != CBS_SIMPLE
)
1470 if( !(lphc
->wState
& CBF_DROPPED
) )
1474 if( lphc
->wState
& CBF_DROPPED
)
1475 CBRollUp( lphc
, FALSE
, TRUE
);
1480 return SendMessage32A( lphc
->hWndLBox
, LB_GETCOUNT32
, 0, 0);
1482 case CB_GETCURSEL16
:
1483 case CB_GETCURSEL32
:
1484 return SendMessage32A( lphc
->hWndLBox
, LB_GETCURSEL32
, 0, 0);
1486 case CB_SETCURSEL16
:
1487 wParam
= (INT32
)(INT16
)wParam
;
1488 case CB_SETCURSEL32
:
1489 return SendMessage32A( lphc
->hWndLBox
, LB_SETCURSEL32
, wParam
, 0);
1491 case CB_GETLBTEXT16
:
1492 wParam
= (INT32
)(INT16
)wParam
;
1493 lParam
= (LPARAM
)PTR_SEG_TO_LIN(lParam
);
1494 case CB_GETLBTEXT32
:
1495 return SendMessage32A( lphc
->hWndLBox
, LB_GETTEXT32
, wParam
, lParam
);
1497 case CB_GETLBTEXTLEN16
:
1498 wParam
= (INT32
)(INT16
)wParam
;
1499 case CB_GETLBTEXTLEN32
:
1500 return SendMessage32A( lphc
->hWndLBox
, LB_GETTEXTLEN32
, wParam
, 0);
1502 case CB_GETITEMDATA16
:
1503 wParam
= (INT32
)(INT16
)wParam
;
1504 case CB_GETITEMDATA32
:
1505 return SendMessage32A( lphc
->hWndLBox
, LB_GETITEMDATA32
, wParam
, 0);
1507 case CB_SETITEMDATA16
:
1508 wParam
= (INT32
)(INT16
)wParam
;
1509 case CB_SETITEMDATA32
:
1510 return SendMessage32A( lphc
->hWndLBox
, LB_SETITEMDATA32
, wParam
, lParam
);
1512 case CB_GETEDITSEL16
:
1513 wParam
= lParam
= 0; /* just in case */
1514 case CB_GETEDITSEL32
:
1515 if( lphc
->wState
& CBF_EDIT
)
1519 return SendMessage32A( lphc
->hWndEdit
, EM_GETSEL32
,
1520 (wParam
) ? wParam
: (WPARAM32
)&a
,
1521 (lParam
) ? lParam
: (LPARAM
)&b
);
1525 case CB_SETEDITSEL16
:
1526 case CB_SETEDITSEL32
:
1527 if( lphc
->wState
& CBF_EDIT
)
1528 return SendMessage32A( lphc
->hWndEdit
, EM_SETSEL32
,
1529 (INT32
)(INT16
)LOWORD(lParam
), (INT32
)(INT16
)HIWORD(lParam
) );
1532 case CB_SETEXTENDEDUI16
:
1533 case CB_SETEXTENDEDUI32
:
1534 if( CB_GETTYPE(lphc
) == CBS_SIMPLE
) return CB_ERR
;
1537 lphc
->wState
|= CBF_EUI
;
1538 else lphc
->wState
&= ~CBF_EUI
;
1541 case CB_GETEXTENDEDUI16
:
1542 case CB_GETEXTENDEDUI32
:
1543 return (lphc
->wState
& CBF_EUI
) ? TRUE
: FALSE
;
1545 case (WM_USER
+ 0x1B):
1546 dprintf_combo(stddeb
,"Combo [%04x]: undocumented msg!\n", (HWND16
)hwnd
);
1548 return DefWindowProc32A(hwnd
, message
, wParam
, lParam
);