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=%04x\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
= SendMessage(lphl
->hParent
, WM_CTLCOLORLISTBOX
, hdc
, hwnd
);
231 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLOR
, hdc
,
232 MAKELONG(hwnd
, CTLCOLOR_LISTBOX
));
234 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
236 GetClientRect(hwnd
, &rect
);
237 rect
.right
-= (lphc
->RectButton
.right
- lphc
->RectButton
.left
);
239 lpls
= ListBoxGetItem(lphl
,lphl
->ItemFocused
);
241 height
= lpls
->mis
.itemHeight
;
242 rect
.bottom
= rect
.top
+ height
;
243 FillRect(hdc
, &rect
, hBrush
);
244 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &rect
, ODA_DRAWENTIRE
, 0);
245 if (GetFocus() == hwnd
)
246 ListBoxDrawItem (hwnd
,lphl
, hdc
, lpls
, &rect
, ODA_FOCUS
, ODS_FOCUS
);
248 else FillRect(hdc
, &rect
, hBrush
);
249 SelectObject(hdc
,hOldFont
);
254 /***********************************************************************
257 static LRESULT
CBGetDlgCode(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
259 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
262 /***********************************************************************
265 static LRESULT
CBLButtonDown(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
267 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
268 SendMessage(hwnd
,CB_SHOWDROPDOWN
,!lphc
->DropDownVisible
,0);
272 /***********************************************************************
275 static LRESULT
CBKeyDown(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
277 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
278 WORD newFocused
= lphl
->ItemFocused
;
285 newFocused
= lphl
->ItemsCount
- 1;
288 if (newFocused
> 0) newFocused
--;
297 if (newFocused
>= lphl
->ItemsCount
)
298 newFocused
= lphl
->ItemsCount
- 1;
300 ListBoxSetCurSel(lphl
, newFocused
);
301 ListBoxSendNotification(lphl
, CBN_SELCHANGE
);
303 lphl
->ItemFocused
= newFocused
;
304 ListBoxScrollToFocus(lphl
);
305 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
306 InvalidateRect(hwnd
, NULL
, TRUE
);
311 /***********************************************************************
314 static LRESULT
CBChar(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
316 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
319 newFocused
= ListBoxFindNextMatch(lphl
, wParam
);
320 if (newFocused
== (WORD
)LB_ERR
) return 0;
322 if (newFocused
>= lphl
->ItemsCount
)
323 newFocused
= lphl
->ItemsCount
- 1;
325 ListBoxSetCurSel(lphl
, newFocused
);
326 ListBoxSendNotification(lphl
, CBN_SELCHANGE
);
327 lphl
->ItemFocused
= newFocused
;
328 ListBoxScrollToFocus(lphl
);
330 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
331 InvalidateRect(hwnd
, NULL
, TRUE
);
336 /***********************************************************************
339 static LRESULT
CBKillFocus(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
344 /***********************************************************************
347 static LRESULT
CBSetFocus(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
352 /***********************************************************************
355 static LRESULT
CBResetContent(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
357 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
358 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
360 ListBoxResetContent(lphl
);
361 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
365 /***********************************************************************
368 static LRESULT
CBDir(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
371 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
372 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
374 wRet
= ListBoxDirectory(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
375 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
379 /***********************************************************************
382 static LRESULT
CBInsertString(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
385 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
386 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
388 if (lphl
->HasStrings
)
389 wRet
= ListBoxInsertString(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
391 wRet
= ListBoxInsertString(lphl
, wParam
, (LPSTR
)lParam
);
393 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
397 /***********************************************************************
400 static LRESULT
CBAddString(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
403 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
404 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
406 if (lphl
->HasStrings
)
407 wRet
= ListBoxAddString(lphl
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
409 wRet
= ListBoxAddString(lphl
, (LPSTR
)lParam
);
411 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
415 /***********************************************************************
418 static LRESULT
CBDeleteString(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
420 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
421 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
422 LONG lRet
= ListBoxDeleteString(lphl
,wParam
);
424 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
428 /***********************************************************************
431 static LRESULT
CBSelectString(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
433 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
436 wRet
= ListBoxFindString(lphl
, wParam
, (SEGPTR
)lParam
);
438 /* XXX add functionality here */
443 /***********************************************************************
446 static LRESULT
CBFindString(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
448 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
449 return ListBoxFindString(lphl
, wParam
, (SEGPTR
)lParam
);
452 /***********************************************************************
455 static LRESULT
CBGetCount(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
457 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
458 return lphl
->ItemsCount
;
461 /***********************************************************************
464 static LRESULT
CBSetCurSel(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
466 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
469 wRet
= ListBoxSetCurSel(lphl
, wParam
);
471 dprintf_combo(stddeb
,"CBSetCurSel: hwnd %04x wp %x lp %lx wRet %d\n",
472 hwnd
,wParam
,lParam
,wRet
);
473 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
474 InvalidateRect(hwnd
, NULL
, TRUE
);
479 /***********************************************************************
482 static LRESULT
CBGetCurSel(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
484 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
485 return lphl
->ItemFocused
;
488 /***********************************************************************
491 static LRESULT
CBGetItemHeight(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
493 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
494 LPLISTSTRUCT lpls
= ListBoxGetItem (lphl
, wParam
);
496 if (lpls
== NULL
) return LB_ERR
;
497 return lpls
->mis
.itemHeight
;
500 /***********************************************************************
503 static LRESULT
CBSetItemHeight(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
505 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
506 return ListBoxSetItemHeight(lphl
, wParam
, lParam
);
509 /***********************************************************************
512 static LRESULT
CBSetRedraw(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
514 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
515 lphl
->bRedrawFlag
= wParam
;
519 /***********************************************************************
522 static LRESULT
CBSetFont(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
524 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
527 lphl
->hFont
= GetStockObject(SYSTEM_FONT
);
529 lphl
->hFont
= (HFONT
)wParam
;
534 /***********************************************************************
537 static LRESULT
CBGetLBTextLen(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
539 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
540 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
,wParam
);
542 if (lpls
== NULL
|| !lphl
->HasStrings
) return LB_ERR
;
543 return strlen(lpls
->itemText
);
546 /***********************************************************************
549 static LRESULT
CBGetLBText(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
551 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
552 return ListBoxGetText(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
555 /***********************************************************************
558 static LRESULT
CBGetItemData(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
560 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
561 return ListBoxGetItemData(lphl
, wParam
);
564 /***********************************************************************
567 static LRESULT
CBSetItemData(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
569 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
570 return ListBoxSetItemData(lphl
, wParam
, lParam
);
573 /***********************************************************************
576 static LRESULT
CBShowDropDown(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
578 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
581 if ((lphc
->dwStyle
& 3) == CBS_SIMPLE
) return LB_ERR
;
584 if (wParam
!= lphc
->DropDownVisible
) {
585 lphc
->DropDownVisible
= wParam
;
586 GetWindowRect(hwnd
,&rect
);
587 SetWindowPos(lphc
->hWndLBox
, 0, rect
.left
, rect
.top
+lphc
->LBoxTop
, 0, 0,
588 SWP_NOSIZE
| (wParam
? SWP_SHOWWINDOW
: SWP_HIDEWINDOW
));
589 if (!wParam
) SetFocus(hwnd
);
595 /***********************************************************************
598 LRESULT
ComboBoxWndProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
601 case WM_NCCREATE
: return CBNCCreate(hwnd
, wParam
, lParam
);
602 case WM_CREATE
: return CBCreate(hwnd
, wParam
, lParam
);
603 case WM_DESTROY
: return CBDestroy(hwnd
, wParam
, lParam
);
604 case WM_GETDLGCODE
: return CBGetDlgCode(hwnd
, wParam
, lParam
);
605 case WM_KEYDOWN
: return CBKeyDown(hwnd
, wParam
, lParam
);
606 case WM_CHAR
: return CBChar(hwnd
, wParam
, lParam
);
607 case WM_SETFONT
: return CBSetFont(hwnd
, wParam
, lParam
);
608 case WM_SETREDRAW
: return CBSetRedraw(hwnd
, wParam
, lParam
);
609 case WM_PAINT
: return CBPaint(hwnd
, wParam
, lParam
);
610 case WM_LBUTTONDOWN
: return CBLButtonDown(hwnd
, wParam
, lParam
);
611 case WM_SETFOCUS
: return CBSetFocus(hwnd
, wParam
, lParam
);
612 case WM_KILLFOCUS
: return CBKillFocus(hwnd
, wParam
, lParam
);
613 case CB_RESETCONTENT
: return CBResetContent(hwnd
, wParam
, lParam
);
614 case CB_DIR
: return CBDir(hwnd
, wParam
, lParam
);
615 case CB_ADDSTRING
: return CBAddString(hwnd
, wParam
, lParam
);
616 case CB_INSERTSTRING
: return CBInsertString(hwnd
, wParam
, lParam
);
617 case CB_DELETESTRING
: return CBDeleteString(hwnd
, wParam
, lParam
);
618 case CB_FINDSTRING
: return CBFindString(hwnd
, wParam
, lParam
);
619 case CB_GETCOUNT
: return CBGetCount(hwnd
, wParam
, lParam
);
620 case CB_GETCURSEL
: return CBGetCurSel(hwnd
, wParam
, lParam
);
621 case CB_GETITEMDATA
: return CBGetItemData(hwnd
, wParam
, lParam
);
622 case CB_GETITEMHEIGHT
: return CBGetItemHeight(hwnd
, wParam
, lParam
);
623 case CB_GETLBTEXT
: return CBGetLBText(hwnd
, wParam
, lParam
);
624 case CB_GETLBTEXTLEN
: return CBGetLBTextLen(hwnd
, wParam
, lParam
);
625 case CB_SELECTSTRING
: return CBSelectString(hwnd
, wParam
, lParam
);
626 case CB_SETITEMDATA
: return CBSetItemData(hwnd
, wParam
, lParam
);
627 case CB_SETCURSEL
: return CBSetCurSel(hwnd
, wParam
, lParam
);
628 case CB_SETITEMHEIGHT
: return CBSetItemHeight(hwnd
, wParam
, lParam
);
629 case CB_SHOWDROPDOWN
: return CBShowDropDown(hwnd
, wParam
, lParam
);
631 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
634 /*--------------------------------------------------------------------*/
635 /* ComboLBox code starts here */
637 HWND
CLBoxGetCombo(HWND hwnd
)
640 return (HWND
)GetWindowLong(hwnd
,0);
642 return (HWND
)GetWindowWord(hwnd
,0);
646 LPHEADLIST
CLBoxGetListHeader(HWND hwnd
)
648 return ComboGetListHeader(CLBoxGetCombo(hwnd
));
651 /***********************************************************************
654 static LRESULT
CBLCreate( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
656 CREATESTRUCT
*createStruct
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
658 SetWindowLong(hwnd
,0,(LONG
)createStruct
->lpCreateParams
);
660 SetWindowWord(hwnd
,0,LOWORD(createStruct
->lpCreateParams
));
665 /***********************************************************************
668 static LRESULT
CBLGetDlgCode( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
670 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
673 /***********************************************************************
676 static LRESULT
CBLKeyDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
678 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
679 WORD newFocused
= lphl
->ItemFocused
;
686 newFocused
= lphl
->ItemsCount
- 1;
689 if (newFocused
> 0) newFocused
--;
695 if (newFocused
> lphl
->ItemsVisible
) {
696 newFocused
-= lphl
->ItemsVisible
;
702 newFocused
+= lphl
->ItemsVisible
;
708 if (newFocused
>= lphl
->ItemsCount
)
709 newFocused
= lphl
->ItemsCount
- 1;
711 ListBoxSetCurSel(lphl
, newFocused
);
712 ListBoxSendNotification(lphl
, CBN_SELCHANGE
);
714 lphl
->ItemFocused
= newFocused
;
715 ListBoxScrollToFocus(lphl
);
716 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
717 InvalidateRect(hwnd
, NULL
, TRUE
);
721 /***********************************************************************
724 static LRESULT
CBLChar( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
729 /***********************************************************************
732 static LRESULT
CBLPaint( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
734 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
739 HWND combohwnd
= CLBoxGetCombo(hwnd
);
745 hdc
= BeginPaint( hwnd
, &ps
);
747 if (!IsWindowVisible(hwnd
) || !lphl
->bRedrawFlag
) {
752 hOldFont
= SelectObject(hdc
, lphl
->hFont
);
754 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLORLISTBOX
, hdc
, hwnd
);
756 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLOR
, hdc
,
757 MAKELONG(hwnd
, CTLCOLOR_LISTBOX
));
760 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
762 GetClientRect(hwnd
, &rect
);
763 FillRect(hdc
, &rect
, hBrush
);
765 lpls
= lphl
->lpFirst
;
767 lphl
->ItemsVisible
= 0;
768 for(i
= 0; i
< lphl
->ItemsCount
; i
++) {
769 if (lpls
== NULL
) break;
771 if (i
>= lphl
->FirstVisible
) {
772 height
= lpls
->mis
.itemHeight
;
773 /* must have enough room to draw entire item */
774 if (top
> (rect
.bottom
-height
+1)) break;
776 lpls
->itemRect
.top
= top
;
777 lpls
->itemRect
.bottom
= top
+ height
;
778 lpls
->itemRect
.left
= rect
.left
;
779 lpls
->itemRect
.right
= rect
.right
;
781 dprintf_listbox(stddeb
,"drawing item: %d %d %d %d %d\n",
782 rect
.left
,top
,rect
.right
,top
+height
,lpls
->itemState
);
783 if (lphl
->OwnerDrawn
) {
784 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
, 0);
786 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_SELECT
, ODS_SELECTED
);
788 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
,
791 if ((lphl
->ItemFocused
== i
) && GetFocus() == hwnd
)
792 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_FOCUS
, ODS_FOCUS
);
795 lphl
->ItemsVisible
++;
800 SetScrollRange(hwnd
, SB_VERT
, 0, ListMaxFirstVisible(lphl
), TRUE
);
801 SelectObject(hdc
,hOldFont
);
802 EndPaint( hwnd
, &ps
);
807 /***********************************************************************
810 static LRESULT
CBLKillFocus( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
812 /* SendMessage(CLBoxGetCombo(hwnd),CB_SHOWDROPDOWN,0,0);*/
816 /***********************************************************************
819 static LRESULT
CBLActivate( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
821 if (wParam
== WA_INACTIVE
)
822 SendMessage(CLBoxGetCombo(hwnd
),CB_SHOWDROPDOWN
,0,0);
826 /***********************************************************************
829 static LRESULT
CBLLButtonDown( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
831 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
838 lphl
->PrevFocused
= lphl
->ItemFocused
;
840 y
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
844 ListBoxSetCurSel(lphl
, y
);
845 ListBoxGetItemRect(lphl
, y
, &rectsel
);
847 InvalidateRect(hwnd
, NULL
, TRUE
);
851 /***********************************************************************
854 static LRESULT
CBLLButtonUp( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
856 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
858 if (GetCapture() == hwnd
) ReleaseCapture();
862 fprintf(stdnimp
,"CBLLButtonUp: CLBoxGetListHeader returned NULL!\n");
864 else if (lphl
->PrevFocused
!= lphl
->ItemFocused
)
866 SendMessage(CLBoxGetCombo(hwnd
),CB_SETCURSEL
,lphl
->ItemFocused
,0);
867 ListBoxSendNotification(lphl
, CBN_SELCHANGE
);
870 SendMessage(CLBoxGetCombo(hwnd
),CB_SHOWDROPDOWN
,0,0);
875 /***********************************************************************
878 static LRESULT
CBLMouseMove( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
880 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
886 wRet
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
887 ListBoxGetItemRect(lphl
, wRet
, &rectsel
);
888 GetClientRect(hwnd
, &rect
);
890 dprintf_combo(stddeb
,"CBLMouseMove: hwnd %04x wp %x lp %lx y %d if %d wret %d %d,%d-%d,%d\n",
891 hwnd
,wParam
,lParam
,y
,lphl
->ItemFocused
,wRet
,rectsel
.left
,rectsel
.top
,rectsel
.right
,rectsel
.bottom
);
893 if ((wParam
& MK_LBUTTON
) != 0) {
894 if (y
< CBLMM_EDGE
) {
895 if (lphl
->FirstVisible
> 0) {
896 lphl
->FirstVisible
--;
897 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
898 ListBoxSetCurSel(lphl
, wRet
);
899 InvalidateRect(hwnd
, NULL
, TRUE
);
903 else if (y
>= (rect
.bottom
-CBLMM_EDGE
)) {
904 if (lphl
->FirstVisible
< ListMaxFirstVisible(lphl
)) {
905 lphl
->FirstVisible
++;
906 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
907 ListBoxSetCurSel(lphl
, wRet
);
908 InvalidateRect(hwnd
, NULL
, TRUE
);
913 if ((short) wRet
== lphl
->ItemFocused
) return 0;
914 ListBoxSetCurSel(lphl
, wRet
);
915 InvalidateRect(hwnd
, NULL
, TRUE
);
922 /***********************************************************************
925 static LRESULT
CBLVScroll( HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
927 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
930 y
= lphl
->FirstVisible
;
934 if (lphl
->FirstVisible
> 0)
935 lphl
->FirstVisible
--;
939 lphl
->FirstVisible
++;
943 if (lphl
->FirstVisible
> lphl
->ItemsVisible
) {
944 lphl
->FirstVisible
-= lphl
->ItemsVisible
;
946 lphl
->FirstVisible
= 0;
951 lphl
->FirstVisible
+= lphl
->ItemsVisible
;
955 lphl
->FirstVisible
= LOWORD(lParam
);
959 if (lphl
->FirstVisible
> ListMaxFirstVisible(lphl
))
960 lphl
->FirstVisible
= ListMaxFirstVisible(lphl
);
962 if (y
!= lphl
->FirstVisible
) {
963 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
964 InvalidateRect(hwnd
, NULL
, TRUE
);
970 /***********************************************************************
973 LRESULT
ComboLBoxWndProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
976 case WM_CREATE
: return CBLCreate(hwnd
, wParam
, lParam
);
977 case WM_GETDLGCODE
: return CBLGetDlgCode(hwnd
, wParam
, lParam
);
978 case WM_KEYDOWN
: return CBLKeyDown(hwnd
, wParam
, lParam
);
979 case WM_CHAR
: return CBLChar(hwnd
, wParam
, lParam
);
980 case WM_PAINT
: return CBLPaint(hwnd
, wParam
, lParam
);
981 case WM_KILLFOCUS
: return CBLKillFocus(hwnd
, wParam
, lParam
);
982 case WM_ACTIVATE
: return CBLActivate(hwnd
, wParam
, lParam
);
983 case WM_LBUTTONDOWN
: return CBLLButtonDown(hwnd
, wParam
, lParam
);
984 case WM_LBUTTONUP
: return CBLLButtonUp(hwnd
, wParam
, lParam
);
985 case WM_MOUSEMOVE
: return CBLMouseMove(hwnd
, wParam
, lParam
);
986 case WM_VSCROLL
: return CBLVScroll(hwnd
, wParam
, lParam
);
988 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
991 /************************************************************************
992 * DlgDirSelectComboBox [USER.194]
994 BOOL
DlgDirSelectComboBox(HWND hDlg
, LPSTR lpStr
, INT nIDLBox
)
996 fprintf(stdnimp
,"DlgDirSelectComboBox(%04x, '%s', %d) \n",
997 hDlg
, lpStr
, nIDLBox
);
1002 /************************************************************************
1003 * DlgDirListComboBox [USER.195]
1005 INT
DlgDirListComboBox( HWND hDlg
, SEGPTR path
, INT idCBox
,
1006 INT idStatic
, UINT wType
)
1010 dprintf_combo( stddeb
,"DlgDirListComboBox(%04x,%08lx,%d,%d,%04X) \n",
1011 hDlg
, (DWORD
)path
, idCBox
, idStatic
, wType
);
1015 SendDlgItemMessage( hDlg
, idCBox
, CB_RESETCONTENT
, 0, 0 );
1016 ret
= (SendDlgItemMessage( hDlg
, idCBox
, CB_DIR
, wType
, path
) >= 0);
1021 int drive
= DRIVE_GetCurrentDrive();
1022 strcpy( temp
, "A:\\" );
1024 lstrcpyn( temp
+3, DRIVE_GetDosCwd(drive
), 253 );
1025 SendDlgItemMessage( hDlg
, idStatic
, WM_SETTEXT
,
1026 0, (LPARAM
)MAKE_SEGPTR(temp
) );