4 * Copyright 1993 Martin Ayotte
5 * Copyright 1995 Bernd Schmidt
11 #include <sys/types.h>
15 #include "sysmetrics.h"
17 #include "stackframe.h"
29 * Note: Combos are probably implemented in a different way by Windows.
30 * Using a message spy for Windows, you can see some undocumented
31 * messages being passed between ComboBox and ComboLBox.
32 * I hope no programs rely on the implementation of combos.
35 #define CBLMM_EDGE 4 /* distance inside box which is same as moving mouse
36 outside box, to trigger scrolling of CBL */
38 static HBITMAP hComboBit
= 0;
39 static WORD CBitHeight
, CBitWidth
;
41 static int COMBO_Init()
45 dprintf_combo(stddeb
, "COMBO_Init\n");
46 hComboBit
= LoadBitmap(0, MAKEINTRESOURCE(OBM_COMBO
));
47 GetObject(hComboBit
, sizeof(BITMAP
), (LPSTR
)&bm
);
48 CBitHeight
= bm
.bmHeight
;
49 CBitWidth
= bm
.bmWidth
;
53 LPHEADCOMBO
ComboGetStorageHeader(HWND hwnd
)
55 return (LPHEADCOMBO
)GetWindowLong(hwnd
,4);
58 LPHEADLIST
ComboGetListHeader(HWND hwnd
)
60 return (LPHEADLIST
)GetWindowLong(hwnd
,0);
63 int CreateComboStruct(HWND hwnd
, LONG style
)
67 lphc
= (LPHEADCOMBO
)xmalloc(sizeof(HEADCOMBO
));
68 SetWindowLong(hwnd
,4,(LONG
)lphc
);
73 lphc
->dwStyle
= style
;
74 lphc
->DropDownVisible
= FALSE
;
78 void ComboUpdateWindow(HWND hwnd
, LPHEADLIST lphl
, LPHEADCOMBO lphc
, BOOL repaint
)
80 SetScrollRange(lphc
->hWndLBox
, SB_VERT
, 0, ListMaxFirstVisible(lphl
), TRUE
);
81 if (repaint
&& lphl
->bRedrawFlag
) {
82 InvalidateRect(hwnd
, NULL
, TRUE
);
86 /***********************************************************************
89 static LRESULT
CBNCCreate(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
91 CREATESTRUCT
*createStruct
;
93 if (!hComboBit
) COMBO_Init();
95 createStruct
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
96 createStruct
->style
&= ~(WS_VSCROLL
| WS_HSCROLL
);
97 SetWindowLong(hwnd
, GWL_STYLE
, createStruct
->style
);
99 dprintf_combo(stddeb
,"ComboBox WM_NCCREATE!\n");
100 return DefWindowProc(hwnd
, WM_NCCREATE
, wParam
, lParam
);
104 /***********************************************************************
107 static LRESULT
CBCreate(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
112 LONG cstyle
= GetWindowLong(hwnd
,GWL_STYLE
);
114 char className
[] = "COMBOLBOX"; /* Hack so that class names are > 0x10000 */
115 char editName
[] = "EDIT";
117 /* translate combo into listbox styles */
118 if (cstyle
& CBS_OWNERDRAWFIXED
) style
|= LBS_OWNERDRAWFIXED
;
119 if (cstyle
& CBS_OWNERDRAWVARIABLE
) style
|= LBS_OWNERDRAWVARIABLE
;
120 if (cstyle
& CBS_SORT
) style
|= LBS_SORT
;
121 if (cstyle
& CBS_HASSTRINGS
) style
|= LBS_HASSTRINGS
;
123 CreateListBoxStruct(hwnd
, ODT_COMBOBOX
, style
, GetParent(hwnd
));
124 CreateComboStruct(hwnd
,cstyle
);
125 lphl
= ComboGetListHeader(hwnd
);
126 lphc
= ComboGetStorageHeader(hwnd
);
128 GetClientRect(hwnd
,&rect
);
129 GetWindowRect(hwnd
,&lboxrect
);
130 /* FIXME: combos with edit controls are broken. */
132 case CBS_SIMPLE
: /* edit control, list always visible */
133 dprintf_combo(stddeb
,"CBS_SIMPLE\n");
134 SetRectEmpty(&lphc
->RectButton
);
135 lphc
->LBoxTop
= lphl
->StdItemHeight
;
136 lphc
->hWndEdit
= CreateWindow(MAKE_SEGPTR(editName
), (SEGPTR
)0,
137 WS_CHILD
| WS_CLIPCHILDREN
| WS_VISIBLE
| SS_LEFT
,
138 0, 0, rect
.right
, lphl
->StdItemHeight
,
139 hwnd
, (HMENU
)1, WIN_GetWindowInstance(hwnd
), 0L);
141 case CBS_DROPDOWN
: /* edit control, dropdown listbox */
142 dprintf_combo(stddeb
,"CBS_DROPDOWN\n");
143 lphc
->RectButton
= rect
;
144 lphc
->RectButton
.left
= lphc
->RectButton
.right
- 6 - CBitWidth
;
145 lphc
->RectButton
.bottom
= lphc
->RectButton
.top
+ lphl
->StdItemHeight
;
146 lphc
->LBoxTop
= lphl
->StdItemHeight
;
147 SetWindowPos(hwnd
, 0, 0, 0, rect
.right
- rect
.left
+ 2*SYSMETRICS_CXBORDER
,
148 lphl
->StdItemHeight
+ 2*SYSMETRICS_CYBORDER
,
149 SWP_NOMOVE
| SWP_NOZORDER
);
150 lphc
->hWndEdit
= CreateWindow(MAKE_SEGPTR(editName
), (SEGPTR
)0,
151 WS_CHILD
| WS_CLIPCHILDREN
| WS_VISIBLE
| SS_LEFT
,
152 0, 0, lphc
->RectButton
.left
, lphl
->StdItemHeight
,
153 hwnd
, (HMENU
)1, WIN_GetWindowInstance(hwnd
), 0L);
155 case CBS_DROPDOWNLIST
: /* static control, dropdown listbox */
156 dprintf_combo(stddeb
,"CBS_DROPDOWNLIST\n");
157 lphc
->RectButton
= rect
;
158 lphc
->RectButton
.left
= lphc
->RectButton
.right
- 6 - CBitWidth
;
159 lphc
->RectButton
.bottom
= lphc
->RectButton
.top
+ lphl
->StdItemHeight
;
160 lphc
->LBoxTop
= lphl
->StdItemHeight
;
161 SetWindowPos(hwnd
, 0, 0, 0, rect
.right
- rect
.left
+ 2*SYSMETRICS_CXBORDER
,
162 lphl
->StdItemHeight
+ 2*SYSMETRICS_CYBORDER
,
163 SWP_NOMOVE
| SWP_NOZORDER
);
166 lboxrect
.top
+= lphc
->LBoxTop
;
167 /* FIXME: WinSight says these should be CHILD windows with the TOPMOST flag
168 * set. Wine doesn't support TOPMOST, and simply setting the WS_CHILD
169 * flag doesn't work. */
170 lphc
->hWndLBox
= CreateWindow(MAKE_SEGPTR(className
), (SEGPTR
)0,
171 WS_POPUP
| WS_BORDER
| WS_VSCROLL
,
172 lboxrect
.left
, lboxrect
.top
,
173 lboxrect
.right
- lboxrect
.left
,
174 lboxrect
.bottom
- lboxrect
.top
,
175 0, 0, WIN_GetWindowInstance(hwnd
),
177 ShowWindow(lphc
->hWndLBox
, SW_HIDE
);
178 dprintf_combo(stddeb
,"Combo Creation LBox="NPFMT
"!\n", lphc
->hWndLBox
);
182 /***********************************************************************
185 static LRESULT
CBDestroy(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
187 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
189 ListBoxResetContent(lphl
);
190 DestroyListBoxStruct(lphl
);
191 dprintf_combo(stddeb
,"Combo WM_DESTROY %p !\n", lphl
);
195 /***********************************************************************
198 static LRESULT
CBPaint(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
200 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
201 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
210 hdc
= BeginPaint(hwnd
, &ps
);
212 if (hComboBit
!= 0) {
213 GRAPH_DrawReliefRect(hdc
, &lphc
->RectButton
, 2, 2, FALSE
);
214 GRAPH_DrawBitmap(hdc
, hComboBit
,
215 lphc
->RectButton
.left
+ 3,lphc
->RectButton
.top
+ 2,
216 0, 0, CBitWidth
, CBitHeight
);
218 if (!IsWindowVisible(hwnd
) || !lphl
->bRedrawFlag
219 || (lphc
->dwStyle
& 3) != CBS_DROPDOWNLIST
)
221 /* we don't want to draw an entry when there is an edit control */
226 hOldFont
= SelectObject(hdc
, lphl
->hFont
);
229 hBrush
= (HBRUSH
) SendMessage(lphl
->hParent
, WM_CTLCOLORLISTBOX
, (WPARAM
)hdc
,
232 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLOR
, hdc
,
233 MAKELONG(hwnd
, CTLCOLOR_LISTBOX
));
235 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
237 GetClientRect(hwnd
, &rect
);
238 rect
.right
-= (lphc
->RectButton
.right
- lphc
->RectButton
.left
);
239 FillRect(hdc
, &rect
, hBrush
);
241 lpls
= ListBoxGetItem(lphl
,lphl
->ItemFocused
);
243 height
= lpls
->mis
.itemHeight
;
244 rect
.bottom
= rect
.top
+ height
;
246 if (lphl
->OwnerDrawn
) {
247 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &rect
, ODA_DRAWENTIRE
, 0);
249 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &rect
, ODA_DRAWENTIRE
, 0);
251 if (GetFocus() == hwnd
)
252 ListBoxDrawItem (hwnd
,lphl
, hdc
, lpls
, &rect
, ODA_FOCUS
, ODS_FOCUS
);
254 SelectObject(hdc
,hOldFont
);
259 /***********************************************************************
262 static LRESULT
CBGetDlgCode(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
264 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
267 /***********************************************************************
270 static LRESULT
CBLButtonDown(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
272 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
273 SendMessage(hwnd
,CB_SHOWDROPDOWN
,!lphc
->DropDownVisible
,0);
277 /***********************************************************************
280 static LRESULT
CBKeyDown(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
282 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
283 WORD newFocused
= lphl
->ItemFocused
;
290 newFocused
= lphl
->ItemsCount
- 1;
293 if (newFocused
> 0) newFocused
--;
302 if (newFocused
>= lphl
->ItemsCount
)
303 newFocused
= lphl
->ItemsCount
- 1;
305 ListBoxSetCurSel(lphl
, newFocused
);
306 ListBoxSendNotification(lphl
, CBN_SELCHANGE
);
308 lphl
->ItemFocused
= newFocused
;
309 ListBoxScrollToFocus(lphl
);
310 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
311 InvalidateRect(hwnd
, NULL
, TRUE
);
316 /***********************************************************************
319 static LRESULT
CBChar(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
321 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
324 newFocused
= ListBoxFindNextMatch(lphl
, wParam
);
325 if (newFocused
== (WORD
)LB_ERR
) return 0;
327 if (newFocused
>= lphl
->ItemsCount
)
328 newFocused
= lphl
->ItemsCount
- 1;
330 ListBoxSetCurSel(lphl
, newFocused
);
331 ListBoxSendNotification(lphl
, CBN_SELCHANGE
);
332 lphl
->ItemFocused
= newFocused
;
333 ListBoxScrollToFocus(lphl
);
335 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
336 InvalidateRect(hwnd
, NULL
, TRUE
);
341 /***********************************************************************
344 static LRESULT
CBKillFocus(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
349 /***********************************************************************
352 static LRESULT
CBSetFocus(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
357 /***********************************************************************
360 static LRESULT
CBResetContent(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
362 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
363 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
365 ListBoxResetContent(lphl
);
366 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
370 /***********************************************************************
373 static LRESULT
CBDir(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
376 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
377 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
379 wRet
= ListBoxDirectory(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
380 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
384 /***********************************************************************
387 static LRESULT
CBInsertString(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
390 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
391 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
393 if (lphl
->HasStrings
)
394 wRet
= ListBoxInsertString(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
396 wRet
= ListBoxInsertString(lphl
, wParam
, (LPSTR
)lParam
);
398 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
402 /***********************************************************************
405 static LRESULT
CBAddString(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
408 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
409 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
411 if (lphl
->HasStrings
)
412 wRet
= ListBoxAddString(lphl
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
414 wRet
= ListBoxAddString(lphl
, (LPSTR
)lParam
);
416 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
420 /***********************************************************************
423 static LRESULT
CBDeleteString(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
425 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
426 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
427 LONG lRet
= ListBoxDeleteString(lphl
,wParam
);
429 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
433 /***********************************************************************
436 static LRESULT
CBSelectString(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
438 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
441 wRet
= ListBoxFindString(lphl
, wParam
, (SEGPTR
)lParam
);
443 /* XXX add functionality here */
448 /***********************************************************************
451 static LRESULT
CBFindString(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
453 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
454 return ListBoxFindString(lphl
, wParam
, (SEGPTR
)lParam
);
457 /***********************************************************************
460 static LRESULT
CBGetCount(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
462 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
463 return lphl
->ItemsCount
;
466 /***********************************************************************
469 static LRESULT
CBSetCurSel(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
471 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
474 wRet
= ListBoxSetCurSel(lphl
, wParam
);
476 dprintf_combo(stddeb
,"CBSetCurSel: hwnd "NPFMT
" wp %x lp %lx wRet %d\n",
477 hwnd
,wParam
,lParam
,wRet
);
478 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
479 InvalidateRect(hwnd
, NULL
, TRUE
);
484 /***********************************************************************
487 static LRESULT
CBGetCurSel(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
489 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
490 return lphl
->ItemFocused
;
493 /***********************************************************************
496 static LRESULT
CBGetItemHeight(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
498 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
499 LPLISTSTRUCT lpls
= ListBoxGetItem (lphl
, wParam
);
501 if (lpls
== NULL
) return LB_ERR
;
502 return lpls
->mis
.itemHeight
;
505 /***********************************************************************
508 static LRESULT
CBSetItemHeight(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
510 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
511 return ListBoxSetItemHeight(lphl
, wParam
, lParam
);
514 /***********************************************************************
517 static LRESULT
CBSetRedraw(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
519 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
520 lphl
->bRedrawFlag
= wParam
;
524 /***********************************************************************
527 static LRESULT
CBSetFont(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
529 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
532 lphl
->hFont
= GetStockObject(SYSTEM_FONT
);
534 lphl
->hFont
= (HFONT
)wParam
;
539 /***********************************************************************
542 static LRESULT
CBGetLBTextLen(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
544 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
545 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
,wParam
);
547 if (lpls
== NULL
|| !lphl
->HasStrings
) return LB_ERR
;
548 return strlen(lpls
->itemText
);
551 /***********************************************************************
554 static LRESULT
CBGetLBText(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
556 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
557 return ListBoxGetText(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
560 /***********************************************************************
563 static LRESULT
CBGetItemData(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
565 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
566 return ListBoxGetItemData(lphl
, wParam
);
569 /***********************************************************************
572 static LRESULT
CBSetItemData(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
574 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
575 return ListBoxSetItemData(lphl
, wParam
, lParam
);
578 /***********************************************************************
581 static LRESULT
CBShowDropDown(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
583 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
586 if ((lphc
->dwStyle
& 3) == CBS_SIMPLE
) return LB_ERR
;
589 if (wParam
!= lphc
->DropDownVisible
) {
590 lphc
->DropDownVisible
= wParam
;
591 GetWindowRect(hwnd
,&rect
);
592 SetWindowPos(lphc
->hWndLBox
, 0, rect
.left
, rect
.top
+lphc
->LBoxTop
, 0, 0,
593 SWP_NOSIZE
| (wParam
? SWP_SHOWWINDOW
: SWP_HIDEWINDOW
));
594 if (!wParam
) SetFocus(hwnd
);
600 /***********************************************************************
603 LRESULT
ComboBoxWndProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
606 case WM_NCCREATE
: return CBNCCreate(hwnd
, wParam
, lParam
);
607 case WM_CREATE
: return CBCreate(hwnd
, wParam
, lParam
);
608 case WM_DESTROY
: return CBDestroy(hwnd
, wParam
, lParam
);
609 case WM_GETDLGCODE
: return CBGetDlgCode(hwnd
, wParam
, lParam
);
610 case WM_KEYDOWN
: return CBKeyDown(hwnd
, wParam
, lParam
);
611 case WM_CHAR
: return CBChar(hwnd
, wParam
, lParam
);
612 case WM_SETFONT
: return CBSetFont(hwnd
, wParam
, lParam
);
613 case WM_SETREDRAW
: return CBSetRedraw(hwnd
, wParam
, lParam
);
614 case WM_PAINT
: return CBPaint(hwnd
, wParam
, lParam
);
615 case WM_LBUTTONDOWN
: return CBLButtonDown(hwnd
, wParam
, lParam
);
616 case WM_SETFOCUS
: return CBSetFocus(hwnd
, wParam
, lParam
);
617 case WM_KILLFOCUS
: return CBKillFocus(hwnd
, wParam
, lParam
);
618 case CB_RESETCONTENT
: return CBResetContent(hwnd
, wParam
, lParam
);
619 case CB_DIR
: return CBDir(hwnd
, wParam
, lParam
);
620 case CB_ADDSTRING
: return CBAddString(hwnd
, wParam
, lParam
);
621 case CB_INSERTSTRING
: return CBInsertString(hwnd
, wParam
, lParam
);
622 case CB_DELETESTRING
: return CBDeleteString(hwnd
, wParam
, lParam
);
623 case CB_FINDSTRING
: return CBFindString(hwnd
, wParam
, lParam
);
624 case CB_GETCOUNT
: return CBGetCount(hwnd
, wParam
, lParam
);
625 case CB_GETCURSEL
: return CBGetCurSel(hwnd
, wParam
, lParam
);
626 case CB_GETITEMDATA
: return CBGetItemData(hwnd
, wParam
, lParam
);
627 case CB_GETITEMHEIGHT
: return CBGetItemHeight(hwnd
, wParam
, lParam
);
628 case CB_GETLBTEXT
: return CBGetLBText(hwnd
, wParam
, lParam
);
629 case CB_GETLBTEXTLEN
: return CBGetLBTextLen(hwnd
, wParam
, lParam
);
630 case CB_SELECTSTRING
: return CBSelectString(hwnd
, wParam
, lParam
);
631 case CB_SETITEMDATA
: return CBSetItemData(hwnd
, wParam
, lParam
);
632 case CB_SETCURSEL
: return CBSetCurSel(hwnd
, wParam
, lParam
);
633 case CB_SETITEMHEIGHT
: return CBSetItemHeight(hwnd
, wParam
, lParam
);
634 case CB_SHOWDROPDOWN
: return CBShowDropDown(hwnd
, wParam
, lParam
);
636 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
639 /*--------------------------------------------------------------------*/
640 /* ComboLBox code starts here */
642 HWND
CLBoxGetCombo(HWND hwnd
)
645 return (HWND
)GetWindowLong(hwnd
,0);
647 return (HWND
)GetWindowWord(hwnd
,0);
651 LPHEADLIST
CLBoxGetListHeader(HWND hwnd
)
653 return ComboGetListHeader(CLBoxGetCombo(hwnd
));
656 /***********************************************************************
659 static LRESULT
CBLCreate( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
661 CREATESTRUCT
*createStruct
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
663 SetWindowLong(hwnd
,0,(LONG
)createStruct
->lpCreateParams
);
665 SetWindowWord(hwnd
,0,LOWORD(createStruct
->lpCreateParams
));
670 /***********************************************************************
673 static LRESULT
CBLGetDlgCode( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
675 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
678 /***********************************************************************
681 static LRESULT
CBLKeyDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
683 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
684 WORD newFocused
= lphl
->ItemFocused
;
691 newFocused
= lphl
->ItemsCount
- 1;
694 if (newFocused
> 0) newFocused
--;
700 if (newFocused
> lphl
->ItemsVisible
) {
701 newFocused
-= lphl
->ItemsVisible
;
707 newFocused
+= lphl
->ItemsVisible
;
713 if (newFocused
>= lphl
->ItemsCount
)
714 newFocused
= lphl
->ItemsCount
- 1;
716 ListBoxSetCurSel(lphl
, newFocused
);
717 ListBoxSendNotification(lphl
, CBN_SELCHANGE
);
719 lphl
->ItemFocused
= newFocused
;
720 ListBoxScrollToFocus(lphl
);
721 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
722 InvalidateRect(hwnd
, NULL
, TRUE
);
726 /***********************************************************************
729 static LRESULT
CBLChar( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
734 /***********************************************************************
737 static LRESULT
CBLPaint( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
739 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
744 HWND combohwnd
= CLBoxGetCombo(hwnd
);
750 hdc
= BeginPaint( hwnd
, &ps
);
752 if (!IsWindowVisible(hwnd
) || !lphl
->bRedrawFlag
) {
757 hOldFont
= SelectObject(hdc
, lphl
->hFont
);
759 hBrush
= (HBRUSH
) SendMessage(lphl
->hParent
, WM_CTLCOLORLISTBOX
, (WPARAM
)hdc
,
762 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLOR
, hdc
,
763 MAKELONG(hwnd
, CTLCOLOR_LISTBOX
));
766 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
768 GetClientRect(hwnd
, &rect
);
769 FillRect(hdc
, &rect
, hBrush
);
771 lpls
= lphl
->lpFirst
;
773 lphl
->ItemsVisible
= 0;
774 for(i
= 0; i
< lphl
->ItemsCount
; i
++) {
775 if (lpls
== NULL
) break;
777 if (i
>= lphl
->FirstVisible
) {
778 height
= lpls
->mis
.itemHeight
;
780 if (top
> rect
.bottom
) break;
781 lpls
->itemRect
.top
= top
;
782 lpls
->itemRect
.bottom
= top
+ height
;
783 lpls
->itemRect
.left
= rect
.left
;
784 lpls
->itemRect
.right
= rect
.right
;
786 dprintf_listbox(stddeb
,"drawing item: %ld %d %ld %d %d\n",(LONG
)rect
.left
,top
,(LONG
)rect
.right
,top
+height
,lpls
->itemState
);
787 if (lphl
->OwnerDrawn
) {
788 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
, 0);
790 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_SELECT
, ODS_SELECTED
);
792 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
,
795 if ((lphl
->ItemFocused
== i
) && GetFocus() == hwnd
)
796 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_FOCUS
, ODS_FOCUS
);
799 lphl
->ItemsVisible
++;
804 SetScrollRange(hwnd
, SB_VERT
, 0, ListMaxFirstVisible(lphl
), TRUE
);
805 SelectObject(hdc
,hOldFont
);
806 EndPaint( hwnd
, &ps
);
811 /***********************************************************************
814 static LRESULT
CBLKillFocus( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
816 /* SendMessage(CLBoxGetCombo(hwnd),CB_SHOWDROPDOWN,0,0);*/
820 /***********************************************************************
823 static LRESULT
CBLActivate( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
825 if (wParam
== WA_INACTIVE
)
826 SendMessage(CLBoxGetCombo(hwnd
),CB_SHOWDROPDOWN
,0,0);
830 /***********************************************************************
833 static LRESULT
CBLLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
835 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
842 lphl
->PrevFocused
= lphl
->ItemFocused
;
844 y
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
848 ListBoxSetCurSel(lphl
, y
);
849 ListBoxGetItemRect(lphl
, y
, &rectsel
);
851 InvalidateRect(hwnd
, NULL
, TRUE
);
855 /***********************************************************************
858 static LRESULT
CBLLButtonUp( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
860 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
862 if (GetCapture() == hwnd
) ReleaseCapture();
866 fprintf(stdnimp
,"CBLLButtonUp: CLBoxGetListHeader returned NULL!\n");
868 else if (lphl
->PrevFocused
!= lphl
->ItemFocused
)
870 SendMessage(CLBoxGetCombo(hwnd
),CB_SETCURSEL
,lphl
->ItemFocused
,0);
871 ListBoxSendNotification(lphl
, CBN_SELCHANGE
);
874 SendMessage(CLBoxGetCombo(hwnd
),CB_SHOWDROPDOWN
,0,0);
879 /***********************************************************************
882 static LRESULT
CBLMouseMove( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
884 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
890 wRet
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
891 ListBoxGetItemRect(lphl
, wRet
, &rectsel
);
892 GetClientRect(hwnd
, &rect
);
894 dprintf_combo(stddeb
,"CBLMouseMove: hwnd "NPFMT
" wp %x lp %lx y %d if %d wret %d %d,%d-%d,%d\n",
895 hwnd
,wParam
,lParam
,y
,lphl
->ItemFocused
,wRet
,rectsel
.left
,rectsel
.top
,rectsel
.right
,rectsel
.bottom
);
897 if ((wParam
& MK_LBUTTON
) != 0) {
898 if (y
< CBLMM_EDGE
) {
899 if (lphl
->FirstVisible
> 0) {
900 lphl
->FirstVisible
--;
901 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
902 ListBoxSetCurSel(lphl
, wRet
);
903 InvalidateRect(hwnd
, NULL
, TRUE
);
907 else if (y
>= (rect
.bottom
-CBLMM_EDGE
)) {
908 if (lphl
->FirstVisible
< ListMaxFirstVisible(lphl
)) {
909 lphl
->FirstVisible
++;
910 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
911 ListBoxSetCurSel(lphl
, wRet
);
912 InvalidateRect(hwnd
, NULL
, TRUE
);
917 if ((short) wRet
== lphl
->ItemFocused
) return 0;
918 ListBoxSetCurSel(lphl
, wRet
);
919 InvalidateRect(hwnd
, NULL
, TRUE
);
926 /***********************************************************************
929 static LRESULT
CBLVScroll( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
931 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
934 y
= lphl
->FirstVisible
;
938 if (lphl
->FirstVisible
> 0)
939 lphl
->FirstVisible
--;
943 lphl
->FirstVisible
++;
947 if (lphl
->FirstVisible
> lphl
->ItemsVisible
) {
948 lphl
->FirstVisible
-= lphl
->ItemsVisible
;
950 lphl
->FirstVisible
= 0;
955 lphl
->FirstVisible
+= lphl
->ItemsVisible
;
959 lphl
->FirstVisible
= LOWORD(lParam
);
963 if (lphl
->FirstVisible
> ListMaxFirstVisible(lphl
))
964 lphl
->FirstVisible
= ListMaxFirstVisible(lphl
);
966 if (y
!= lphl
->FirstVisible
) {
967 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
968 InvalidateRect(hwnd
, NULL
, TRUE
);
974 /***********************************************************************
977 LRESULT
ComboLBoxWndProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
980 case WM_CREATE
: return CBLCreate(hwnd
, wParam
, lParam
);
981 case WM_GETDLGCODE
: return CBLGetDlgCode(hwnd
, wParam
, lParam
);
982 case WM_KEYDOWN
: return CBLKeyDown(hwnd
, wParam
, lParam
);
983 case WM_CHAR
: return CBLChar(hwnd
, wParam
, lParam
);
984 case WM_PAINT
: return CBLPaint(hwnd
, wParam
, lParam
);
985 case WM_KILLFOCUS
: return CBLKillFocus(hwnd
, wParam
, lParam
);
986 case WM_ACTIVATE
: return CBLActivate(hwnd
, wParam
, lParam
);
987 case WM_LBUTTONDOWN
: return CBLLButtonDown(hwnd
, wParam
, lParam
);
988 case WM_LBUTTONUP
: return CBLLButtonUp(hwnd
, wParam
, lParam
);
989 case WM_MOUSEMOVE
: return CBLMouseMove(hwnd
, wParam
, lParam
);
990 case WM_VSCROLL
: return CBLVScroll(hwnd
, wParam
, lParam
);
992 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
995 /************************************************************************
996 * DlgDirSelectComboBox [USER.194]
998 BOOL
DlgDirSelectComboBox(HWND hDlg
, LPSTR lpStr
, INT nIDLBox
)
1000 fprintf(stdnimp
,"DlgDirSelectComboBox("NPFMT
", '%s', %d) \n",
1001 hDlg
, lpStr
, nIDLBox
);
1006 /************************************************************************
1007 * DlgDirListComboBox [USER.195]
1009 INT
DlgDirListComboBox( HWND hDlg
, SEGPTR path
, INT idCBox
,
1010 INT idStatic
, UINT wType
)
1014 dprintf_combo( stddeb
,"DlgDirListComboBox("NPFMT
",%08lx,%d,%d,%04X) \n",
1015 hDlg
, (DWORD
)path
, idCBox
, idStatic
, wType
);
1019 SendDlgItemMessage( hDlg
, idCBox
, CB_RESETCONTENT
, 0, 0 );
1020 ret
= (SendDlgItemMessage( hDlg
, idCBox
, CB_DIR
, wType
, path
) >= 0);
1025 int drive
= DRIVE_GetCurrentDrive();
1026 strcpy( temp
, "A:\\" );
1028 lstrcpyn( temp
+3, DRIVE_GetDosCwd(drive
), 253 );
1029 SendDlgItemMessage( hDlg
, idStatic
, WM_SETTEXT
,
1030 0, (LPARAM
)MAKE_SEGPTR(temp
) );