4 * Copyright 1993 Martin Ayotte
5 * Copyright 1995 Bernd Schmidt
11 #include <sys/types.h>
15 #include "sysmetrics.h"
17 #include "stackframe.h"
27 * Note: Combos are probably implemented in a different way by Windows.
28 * Using a message spy for Windows, you can see some undocumented
29 * messages being passed between ComboBox and ComboLBox.
30 * I hope no programs rely on the implementation of combos.
33 static HBITMAP hComboBit
= 0;
34 static WORD CBitHeight
, CBitWidth
;
36 static int COMBO_Init()
40 dprintf_combo(stddeb
, "COMBO_Init\n");
41 hComboBit
= LoadBitmap(0, MAKEINTRESOURCE(OBM_COMBO
));
42 GetObject(hComboBit
, sizeof(BITMAP
), (LPSTR
)&bm
);
43 CBitHeight
= bm
.bmHeight
;
44 CBitWidth
= bm
.bmWidth
;
48 LPHEADCOMBO
ComboGetStorageHeader(HWND hwnd
)
50 return (LPHEADCOMBO
)GetWindowLong(hwnd
,4);
53 LPHEADLIST
ComboGetListHeader(HWND hwnd
)
55 return (LPHEADLIST
)GetWindowLong(hwnd
,0);
58 int CreateComboStruct(HWND hwnd
, LONG style
)
62 lphc
= (LPHEADCOMBO
)malloc(sizeof(HEADCOMBO
));
63 SetWindowLong(hwnd
,4,(LONG
)lphc
);
68 lphc
->dwStyle
= style
;
69 lphc
->DropDownVisible
= FALSE
;
73 void ComboUpdateWindow(HWND hwnd
, LPHEADLIST lphl
, LPHEADCOMBO lphc
, BOOL repaint
)
75 SetScrollRange(lphc
->hWndLBox
, SB_VERT
, 0, ListMaxFirstVisible(lphl
), TRUE
);
76 if (repaint
&& lphl
->bRedrawFlag
) {
77 InvalidateRect(hwnd
, NULL
, TRUE
);
81 /***********************************************************************
84 static LONG
CBNCCreate(HWND hwnd
, WORD wParam
, LONG lParam
)
86 CREATESTRUCT
*createStruct
;
88 if (!hComboBit
) COMBO_Init();
90 createStruct
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
91 createStruct
->style
&= ~(WS_VSCROLL
| WS_HSCROLL
);
92 SetWindowLong(hwnd
, GWL_STYLE
, createStruct
->style
);
94 dprintf_combo(stddeb
,"ComboBox WM_NCCREATE!\n");
95 return DefWindowProc(hwnd
, WM_NCCREATE
, wParam
, lParam
);
99 /***********************************************************************
102 static LONG
CBCreate(HWND hwnd
, WORD wParam
, LONG lParam
)
107 LONG cstyle
= GetWindowLong(hwnd
,GWL_STYLE
);
109 char className
[] = "COMBOLBOX"; /* Hack so that class names are > 0x10000 */
110 char editName
[] = "EDIT";
112 /* translate combo into listbox styles */
113 if (cstyle
& CBS_OWNERDRAWFIXED
) style
|= LBS_OWNERDRAWFIXED
;
114 if (cstyle
& CBS_OWNERDRAWVARIABLE
) style
|= LBS_OWNERDRAWVARIABLE
;
115 if (cstyle
& CBS_SORT
) style
|= LBS_SORT
;
116 if (cstyle
& CBS_HASSTRINGS
) style
|= LBS_HASSTRINGS
;
118 CreateListBoxStruct(hwnd
, ODT_COMBOBOX
, style
, GetParent(hwnd
));
119 CreateComboStruct(hwnd
,cstyle
);
120 lphl
= ComboGetListHeader(hwnd
);
121 lphc
= ComboGetStorageHeader(hwnd
);
123 GetClientRect(hwnd
,&rect
);
124 GetWindowRect(hwnd
,&lboxrect
);
125 /* FIXME: combos with edit controls are broken. */
127 case CBS_SIMPLE
: /* edit control, list always visible */
128 dprintf_combo(stddeb
,"CBS_SIMPLE\n");
129 SetRectEmpty(&lphc
->RectButton
);
130 lphc
->LBoxTop
= lphl
->StdItemHeight
;
131 lphc
->hWndEdit
= CreateWindow(MAKE_SEGPTR(editName
), (SEGPTR
)0,
132 WS_CHILD
| WS_CLIPCHILDREN
| WS_VISIBLE
| SS_LEFT
,
133 0, 0, rect
.right
, lphl
->StdItemHeight
,
134 hwnd
, (HMENU
)1, WIN_GetWindowInstance(hwnd
), 0L);
136 case CBS_DROPDOWN
: /* edit control, dropdown listbox */
137 dprintf_combo(stddeb
,"CBS_DROPDOWN\n");
138 lphc
->RectButton
= rect
;
139 lphc
->RectButton
.left
= lphc
->RectButton
.right
- 6 - CBitWidth
;
140 lphc
->RectButton
.bottom
= lphc
->RectButton
.top
+ lphl
->StdItemHeight
;
141 lphc
->LBoxTop
= lphl
->StdItemHeight
;
142 SetWindowPos(hwnd
, 0, 0, 0, rect
.right
- rect
.left
+ 2*SYSMETRICS_CXBORDER
,
143 lphl
->StdItemHeight
+ 2*SYSMETRICS_CYBORDER
,
144 SWP_NOMOVE
| SWP_NOZORDER
);
145 lphc
->hWndEdit
= CreateWindow(MAKE_SEGPTR(editName
), (SEGPTR
)0,
146 WS_CHILD
| WS_CLIPCHILDREN
| WS_VISIBLE
| SS_LEFT
,
147 0, 0, lphc
->RectButton
.left
, lphl
->StdItemHeight
,
148 hwnd
, (HMENU
)1, WIN_GetWindowInstance(hwnd
), 0L);
150 case CBS_DROPDOWNLIST
: /* static control, downdown listbox */
151 dprintf_combo(stddeb
,"CBS_DROPDOWNLIST\n");
152 lphc
->RectButton
= rect
;
153 lphc
->RectButton
.left
= lphc
->RectButton
.right
- 6 - CBitWidth
;
154 lphc
->RectButton
.bottom
= lphc
->RectButton
.top
+ lphl
->StdItemHeight
;
155 lphc
->LBoxTop
= lphl
->StdItemHeight
;
156 SetWindowPos(hwnd
, 0, 0, 0, rect
.right
- rect
.left
+ 2*SYSMETRICS_CXBORDER
,
157 lphl
->StdItemHeight
+ 2*SYSMETRICS_CYBORDER
,
158 SWP_NOMOVE
| SWP_NOZORDER
);
161 lboxrect
.top
+= lphc
->LBoxTop
;
162 /* FIXME: WinSight says these should be CHILD windows with the TOPMOST flag
163 * set. Wine doesn't support TOPMOST, and simply setting the WS_CHILD
164 * flag doesn't work. */
165 lphc
->hWndLBox
= CreateWindow(MAKE_SEGPTR(className
), (SEGPTR
)0,
166 WS_POPUP
| WS_BORDER
| WS_VSCROLL
,
167 lboxrect
.left
, lboxrect
.top
,
168 lboxrect
.right
- lboxrect
.left
,
169 lboxrect
.bottom
- lboxrect
.top
,
170 0, 0, WIN_GetWindowInstance(hwnd
),
172 ShowWindow(lphc
->hWndLBox
, SW_HIDE
);
173 dprintf_combo(stddeb
,"Combo Creation LBox="NPFMT
"!\n", lphc
->hWndLBox
);
177 /***********************************************************************
180 static LONG
CBDestroy(HWND hwnd
, WORD wParam
, LONG lParam
)
182 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
184 ListBoxResetContent(lphl
);
185 DestroyListBoxStruct(lphl
);
186 dprintf_combo(stddeb
,"Combo WM_DESTROY %p !\n", lphl
);
190 /***********************************************************************
193 static LONG
CBPaint(HWND hwnd
, WORD wParam
, LONG lParam
)
195 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
196 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
205 hdc
= BeginPaint(hwnd
, &ps
);
207 if (hComboBit
!= 0) {
208 GRAPH_DrawReliefRect(hdc
, &lphc
->RectButton
, 2, 2, FALSE
);
209 GRAPH_DrawBitmap(hdc
, hComboBit
,
210 lphc
->RectButton
.left
+ 3,lphc
->RectButton
.top
+ 2,
211 0, 0, CBitWidth
, CBitHeight
);
213 if (!IsWindowVisible(hwnd
) || !lphl
->bRedrawFlag
214 || (lphc
->dwStyle
& 3) != CBS_DROPDOWNLIST
)
216 /* we don't want to draw an entry when there is an edit control */
221 hOldFont
= SelectObject(hdc
, lphl
->hFont
);
224 hBrush
= (HBRUSH
) SendMessage(lphl
->hParent
, WM_CTLCOLORLISTBOX
, (WPARAM
)hdc
,
227 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLOR
, hdc
,
228 MAKELONG(hwnd
, CTLCOLOR_LISTBOX
));
230 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
232 GetClientRect(hwnd
, &rect
);
233 rect
.right
-= (lphc
->RectButton
.right
- lphc
->RectButton
.left
);
234 FillRect(hdc
, &rect
, hBrush
);
236 lpls
= ListBoxGetItem(lphl
,lphl
->ItemFocused
);
238 height
= lpls
->mis
.itemHeight
;
239 rect
.bottom
= rect
.top
+ height
;
241 if (lphl
->OwnerDrawn
) {
242 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &rect
, ODA_DRAWENTIRE
, 0);
244 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &rect
, ODA_DRAWENTIRE
, 0);
246 if (GetFocus() == hwnd
)
247 ListBoxDrawItem (hwnd
,lphl
, hdc
, lpls
, &rect
, ODA_FOCUS
, ODS_FOCUS
);
249 SelectObject(hdc
,hOldFont
);
254 /***********************************************************************
257 static LONG
CBGetDlgCode(HWND hwnd
, WORD wParam
, LONG lParam
)
259 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
262 /***********************************************************************
265 static LONG
CBLButtonDown(HWND hwnd
, WORD wParam
, LONG lParam
)
267 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
268 SendMessage(hwnd
,CB_SHOWDROPDOWN
,!lphc
->DropDownVisible
,0);
272 /***********************************************************************
275 static LONG
CBKeyDown(HWND hwnd
, WORD wParam
, LONG 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
, hwnd
, 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 LONG
CBChar(HWND hwnd
, WORD wParam
, LONG 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
, hwnd
, 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 LONG
CBKillFocus(HWND hwnd
, WORD wParam
, LONG lParam
)
344 /***********************************************************************
347 static LONG
CBSetFocus(HWND hwnd
, WORD wParam
, LONG lParam
)
352 /***********************************************************************
355 static LONG
CBResetContent(HWND hwnd
, WORD wParam
, LONG lParam
)
357 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
358 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
360 ListBoxResetContent(lphl
);
361 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
365 /***********************************************************************
368 static LONG
CBDir(HWND hwnd
, WORD wParam
, LONG 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 LONG
CBInsertString(HWND hwnd
, WORD wParam
, LONG 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 LONG
CBAddString(HWND hwnd
, WORD wParam
, LONG 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 LONG
CBDeleteString(HWND hwnd
, WORD wParam
, LONG 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 LONG
CBSelectString(HWND hwnd
, WORD wParam
, LONG lParam
)
433 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
436 wRet
= ListBoxFindString(lphl
, wParam
, lParam
);
438 /* XXX add functionality here */
443 /***********************************************************************
446 static LONG
CBFindString(HWND hwnd
, WORD wParam
, LONG lParam
)
448 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
449 return ListBoxFindString(lphl
, wParam
, lParam
);
452 /***********************************************************************
455 static LONG
CBGetCount(HWND hwnd
, WORD wParam
, LONG lParam
)
457 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
458 return lphl
->ItemsCount
;
461 /***********************************************************************
464 static LONG
CBSetCurSel(HWND hwnd
, WORD wParam
, LONG lParam
)
466 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
469 wRet
= ListBoxSetCurSel(lphl
, wParam
);
471 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
472 InvalidateRect(hwnd
, NULL
, TRUE
);
477 /***********************************************************************
480 static LONG
CBGetCurSel(HWND hwnd
, WORD wParam
, LONG lParam
)
482 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
483 return lphl
->ItemFocused
;
486 /***********************************************************************
489 static LONG
CBGetItemHeight(HWND hwnd
, WORD wParam
, LONG lParam
)
491 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
492 LPLISTSTRUCT lpls
= ListBoxGetItem (lphl
, wParam
);
494 if (lpls
== NULL
) return LB_ERR
;
495 return lpls
->mis
.itemHeight
;
498 /***********************************************************************
501 static LONG
CBSetItemHeight(HWND hwnd
, WORD wParam
, LONG lParam
)
503 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
504 return ListBoxSetItemHeight(lphl
, wParam
, lParam
);
507 /***********************************************************************
510 static LONG
CBSetRedraw(HWND hwnd
, WORD wParam
, LONG lParam
)
512 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
513 lphl
->bRedrawFlag
= wParam
;
517 /***********************************************************************
520 static LONG
CBSetFont(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
522 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
525 lphl
->hFont
= GetStockObject(SYSTEM_FONT
);
527 lphl
->hFont
= (HFONT
)wParam
;
532 /***********************************************************************
535 static LONG
CBGetLBTextLen(HWND hwnd
, WORD wParam
, LONG lParam
)
537 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
538 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
,wParam
);
540 if (lpls
== NULL
|| !lphl
->HasStrings
) return LB_ERR
;
541 return strlen(lpls
->itemText
);
544 /***********************************************************************
547 static LONG
CBGetLBText(HWND hwnd
, WORD wParam
, LONG lParam
)
549 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
550 return ListBoxGetText(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
553 /***********************************************************************
556 static LONG
CBGetItemData(HWND hwnd
, WORD wParam
, LONG lParam
)
558 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
559 return ListBoxGetItemData(lphl
, wParam
);
562 /***********************************************************************
565 static LONG
CBSetItemData(HWND hwnd
, WORD wParam
, LONG lParam
)
567 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
568 return ListBoxSetItemData(lphl
, wParam
, lParam
);
571 /***********************************************************************
574 static LONG
CBShowDropDown(HWND hwnd
, WORD wParam
, LONG lParam
)
576 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
579 if (lphc
->dwStyle
& 3 == CBS_SIMPLE
) return LB_ERR
;
582 if (wParam
!= lphc
->DropDownVisible
) {
583 lphc
->DropDownVisible
= wParam
;
584 GetWindowRect(hwnd
,&rect
);
585 SetWindowPos(lphc
->hWndLBox
, 0, rect
.left
, rect
.top
+lphc
->LBoxTop
, 0, 0,
586 SWP_NOSIZE
| (wParam
? SWP_SHOWWINDOW
: SWP_HIDEWINDOW
));
587 if (!wParam
) SetFocus(hwnd
);
593 /***********************************************************************
596 LRESULT
ComboBoxWndProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
599 case WM_NCCREATE
: return CBNCCreate(hwnd
, wParam
, lParam
);
600 case WM_CREATE
: return CBCreate(hwnd
, wParam
, lParam
);
601 case WM_DESTROY
: return CBDestroy(hwnd
, wParam
, lParam
);
602 case WM_GETDLGCODE
: return CBGetDlgCode(hwnd
, wParam
, lParam
);
603 case WM_KEYDOWN
: return CBKeyDown(hwnd
, wParam
, lParam
);
604 case WM_CHAR
: return CBChar(hwnd
, wParam
, lParam
);
605 case WM_SETFONT
: return CBSetFont(hwnd
, wParam
, lParam
);
606 case WM_SETREDRAW
: return CBSetRedraw(hwnd
, wParam
, lParam
);
607 case WM_PAINT
: return CBPaint(hwnd
, wParam
, lParam
);
608 case WM_LBUTTONDOWN
: return CBLButtonDown(hwnd
, wParam
, lParam
);
609 case WM_SETFOCUS
: return CBSetFocus(hwnd
, wParam
, lParam
);
610 case WM_KILLFOCUS
: return CBKillFocus(hwnd
, wParam
, lParam
);
611 case CB_RESETCONTENT
: return CBResetContent(hwnd
, wParam
, lParam
);
612 case CB_DIR
: return CBDir(hwnd
, wParam
, lParam
);
613 case CB_ADDSTRING
: return CBAddString(hwnd
, wParam
, lParam
);
614 case CB_INSERTSTRING
: return CBInsertString(hwnd
, wParam
, lParam
);
615 case CB_DELETESTRING
: return CBDeleteString(hwnd
, wParam
, lParam
);
616 case CB_FINDSTRING
: return CBFindString(hwnd
, wParam
, lParam
);
617 case CB_GETCOUNT
: return CBGetCount(hwnd
, wParam
, lParam
);
618 case CB_GETCURSEL
: return CBGetCurSel(hwnd
, wParam
, lParam
);
619 case CB_GETITEMDATA
: return CBGetItemData(hwnd
, wParam
, lParam
);
620 case CB_GETITEMHEIGHT
: return CBGetItemHeight(hwnd
, wParam
, lParam
);
621 case CB_GETLBTEXT
: return CBGetLBText(hwnd
, wParam
, lParam
);
622 case CB_GETLBTEXTLEN
: return CBGetLBTextLen(hwnd
, wParam
, lParam
);
623 case CB_SELECTSTRING
: return CBSelectString(hwnd
, wParam
, lParam
);
624 case CB_SETITEMDATA
: return CBSetItemData(hwnd
, wParam
, lParam
);
625 case CB_SETCURSEL
: return CBSetCurSel(hwnd
, wParam
, lParam
);
626 case CB_SETITEMHEIGHT
: return CBSetItemHeight(hwnd
, wParam
, lParam
);
627 case CB_SHOWDROPDOWN
: return CBShowDropDown(hwnd
, wParam
, lParam
);
629 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
632 /*--------------------------------------------------------------------*/
633 /* ComboLBox code starts here */
635 HWND
CLBoxGetCombo(HWND hwnd
)
638 return (HWND
)GetWindowLong(hwnd
,0);
640 return (HWND
)GetWindowWord(hwnd
,0);
644 LPHEADLIST
CLBoxGetListHeader(HWND hwnd
)
646 return ComboGetListHeader(CLBoxGetCombo(hwnd
));
649 /***********************************************************************
652 static LONG
CBLCreate( HWND hwnd
, WORD wParam
, LONG lParam
)
654 CREATESTRUCT
*createStruct
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
655 SetWindowWord(hwnd
,0,LOWORD(createStruct
->lpCreateParams
));
659 /***********************************************************************
662 static LONG
CBLGetDlgCode( HWND hwnd
, WORD wParam
, LONG lParam
)
664 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
667 /***********************************************************************
670 static LONG
CBLKeyDown( HWND hwnd
, WORD wParam
, LONG lParam
)
672 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
673 WORD newFocused
= lphl
->ItemFocused
;
680 newFocused
= lphl
->ItemsCount
- 1;
683 if (newFocused
> 0) newFocused
--;
689 if (newFocused
> lphl
->ItemsVisible
) {
690 newFocused
-= lphl
->ItemsVisible
;
696 newFocused
+= lphl
->ItemsVisible
;
702 if (newFocused
>= lphl
->ItemsCount
)
703 newFocused
= lphl
->ItemsCount
- 1;
705 ListBoxSetCurSel(lphl
, newFocused
);
706 ListBoxSendNotification(lphl
, hwnd
, CBN_SELCHANGE
);
708 lphl
->ItemFocused
= newFocused
;
709 ListBoxScrollToFocus(lphl
);
710 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
711 InvalidateRect(hwnd
, NULL
, TRUE
);
715 /***********************************************************************
718 static LONG
CBLChar( HWND hwnd
, WORD wParam
, LONG lParam
)
723 /***********************************************************************
726 static LONG
CBLPaint( HWND hwnd
, WORD wParam
, LONG lParam
)
728 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
733 HWND combohwnd
= CLBoxGetCombo(hwnd
);
739 hdc
= BeginPaint( hwnd
, &ps
);
741 if (!IsWindowVisible(hwnd
) || !lphl
->bRedrawFlag
) {
746 hOldFont
= SelectObject(hdc
, lphl
->hFont
);
748 hBrush
= (HBRUSH
) SendMessage(lphl
->hParent
, WM_CTLCOLORLISTBOX
, (WPARAM
)hdc
,
751 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLOR
, hdc
,
752 MAKELONG(hwnd
, CTLCOLOR_LISTBOX
));
755 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
757 GetClientRect(hwnd
, &rect
);
758 FillRect(hdc
, &rect
, hBrush
);
760 lpls
= lphl
->lpFirst
;
762 lphl
->ItemsVisible
= 0;
763 for(i
= 0; i
< lphl
->ItemsCount
; i
++) {
764 if (lpls
== NULL
) break;
766 if (i
>= lphl
->FirstVisible
) {
767 height
= lpls
->mis
.itemHeight
;
769 if (top
> rect
.bottom
) break;
770 lpls
->itemRect
.top
= top
;
771 lpls
->itemRect
.bottom
= top
+ height
;
772 lpls
->itemRect
.left
= rect
.left
;
773 lpls
->itemRect
.right
= rect
.right
;
775 dprintf_listbox(stddeb
,"drawing item: %d %d %d %d %d\n",rect
.left
,top
,rect
.right
,top
+height
,lpls
->itemState
);
776 if (lphl
->OwnerDrawn
) {
777 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
, 0);
779 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_SELECT
, ODS_SELECTED
);
781 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
,
784 if ((lphl
->ItemFocused
== i
) && GetFocus() == hwnd
)
785 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_FOCUS
, ODS_FOCUS
);
788 lphl
->ItemsVisible
++;
793 SelectObject(hdc
,hOldFont
);
794 EndPaint( hwnd
, &ps
);
799 /***********************************************************************
802 static LONG
CBLKillFocus( HWND hwnd
, WORD wParam
, LONG lParam
)
804 /* SendMessage(CLBoxGetCombo(hwnd),CB_SHOWDROPDOWN,0,0);*/
808 /***********************************************************************
811 static LONG
CBLActivate( HWND hwnd
, WORD wParam
, LONG lParam
)
813 if (wParam
== WA_INACTIVE
)
814 SendMessage(CLBoxGetCombo(hwnd
),CB_SHOWDROPDOWN
,0,0);
818 /***********************************************************************
821 static LONG
CBLLButtonDown( HWND hwnd
, WORD wParam
, LONG lParam
)
823 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
830 lphl
->PrevFocused
= lphl
->ItemFocused
;
832 y
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
836 ListBoxSetCurSel(lphl
, y
);
837 ListBoxGetItemRect(lphl
, y
, &rectsel
);
839 InvalidateRect(hwnd
, NULL
, TRUE
);
843 /***********************************************************************
846 static LONG
CBLLButtonUp( HWND hwnd
, WORD wParam
, LONG lParam
)
848 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
850 if (GetCapture() == hwnd
) ReleaseCapture();
854 fprintf(stdnimp
,"CBLLButtonUp: CLBoxGetListHeader returned NULL!\n");
856 else if (lphl
->PrevFocused
!= lphl
->ItemFocused
)
858 SendMessage(CLBoxGetCombo(hwnd
),CB_SETCURSEL
,lphl
->ItemFocused
,0);
859 ListBoxSendNotification(lphl
, CLBoxGetCombo(hwnd
), CBN_SELCHANGE
);
862 SendMessage(CLBoxGetCombo(hwnd
),CB_SHOWDROPDOWN
,0,0);
867 /***********************************************************************
870 static LONG
CBLMouseMove( HWND hwnd
, WORD wParam
, LONG lParam
)
872 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
875 RECT rect
, rectsel
; /* XXX Broken */
877 if ((wParam
& MK_LBUTTON
) != 0) {
880 if (lphl
->FirstVisible
> 0) {
881 lphl
->FirstVisible
--;
882 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
883 InvalidateRect(hwnd
, NULL
, TRUE
);
887 GetClientRect(hwnd
, &rect
);
888 if (y
>= rect
.bottom
) {
889 if (lphl
->FirstVisible
< ListMaxFirstVisible(lphl
)) {
890 lphl
->FirstVisible
++;
891 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
892 InvalidateRect(hwnd
, NULL
, TRUE
);
896 if ((y
> 0) && (y
< (rect
.bottom
- 4))) {
897 if ((y
< rectsel
.top
) || (y
> rectsel
.bottom
)) {
898 wRet
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
899 if (wRet
== lphl
->ItemFocused
) return 0;
900 ListBoxSetCurSel(lphl
, wRet
);
901 ListBoxGetItemRect(lphl
, wRet
, &rectsel
);
902 InvalidateRect(hwnd
, NULL
, TRUE
);
910 /***********************************************************************
913 static LONG
CBLVScroll( HWND hwnd
, WORD wParam
, LONG lParam
)
915 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
918 y
= lphl
->FirstVisible
;
922 if (lphl
->FirstVisible
> 0)
923 lphl
->FirstVisible
--;
927 lphl
->FirstVisible
++;
931 if (lphl
->FirstVisible
> lphl
->ItemsVisible
) {
932 lphl
->FirstVisible
-= lphl
->ItemsVisible
;
934 lphl
->FirstVisible
= 0;
939 lphl
->FirstVisible
+= lphl
->ItemsVisible
;
943 lphl
->FirstVisible
= LOWORD(lParam
);
947 if (lphl
->FirstVisible
> ListMaxFirstVisible(lphl
))
948 lphl
->FirstVisible
= ListMaxFirstVisible(lphl
);
950 if (y
!= lphl
->FirstVisible
) {
951 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
952 InvalidateRect(hwnd
, NULL
, TRUE
);
958 /***********************************************************************
961 LRESULT
ComboLBoxWndProc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
964 case WM_CREATE
: return CBLCreate(hwnd
, wParam
, lParam
);
965 case WM_GETDLGCODE
: return CBLGetDlgCode(hwnd
, wParam
, lParam
);
966 case WM_KEYDOWN
: return CBLKeyDown(hwnd
, wParam
, lParam
);
967 case WM_CHAR
: return CBLChar(hwnd
, wParam
, lParam
);
968 case WM_PAINT
: return CBLPaint(hwnd
, wParam
, lParam
);
969 case WM_KILLFOCUS
: return CBLKillFocus(hwnd
, wParam
, lParam
);
970 case WM_ACTIVATE
: return CBLActivate(hwnd
, wParam
, lParam
);
971 case WM_LBUTTONDOWN
: return CBLLButtonDown(hwnd
, wParam
, lParam
);
972 case WM_LBUTTONUP
: return CBLLButtonUp(hwnd
, wParam
, lParam
);
973 case WM_MOUSEMOVE
: return CBLMouseMove(hwnd
, wParam
, lParam
);
974 case WM_VSCROLL
: return CBLVScroll(hwnd
, wParam
, lParam
);
976 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
979 /************************************************************************
980 * DlgDirSelectComboBox [USER.194]
982 BOOL
DlgDirSelectComboBox(HWND hDlg
, LPSTR lpStr
, int nIDLBox
)
984 fprintf(stdnimp
,"DlgDirSelectComboBox("NPFMT
", '%s', %d) \n",
985 hDlg
, lpStr
, nIDLBox
);
990 /************************************************************************
991 * DlgDirListComboBox [USER.195]
993 int DlgDirListComboBox(HWND hDlg
, SEGPTR PathSpec
,
994 int nIDLBox
, int nIDStat
, WORD wType
)
998 LPSTR lpPathSpec
= PTR_SEG_TO_LIN(PathSpec
);
1000 dprintf_combo(stddeb
,"DlgDirListComboBox("NPFMT
", '%s', %d, %d, %04X) \n",
1001 hDlg
, lpPathSpec
, nIDLBox
, nIDStat
, wType
);
1005 hWnd
= GetDlgItem(hDlg
, nIDLBox
);
1006 lphl
= ComboGetListHeader(hWnd
);
1007 lphc
= ComboGetStorageHeader(hWnd
);
1008 ListBoxResetContent(lphl
);
1009 ret
= ListBoxDirectory(lphl
, wType
, lpPathSpec
);
1010 ComboUpdateWindow(hWnd
, lphl
, lphc
, TRUE
);
1018 drive
= DOS_GetDefaultDrive();
1019 hTemp
= USER_HEAP_ALLOC( 256 );
1020 temp
= (char *) USER_HEAP_LIN_ADDR( hTemp
);
1021 strcpy( temp
+3, DOS_GetCurrentDir(drive
) );
1022 if( temp
[3] == '\\' ) {
1023 temp
[1] = 'A'+drive
;
1025 SendDlgItemMessage( hDlg
, nIDStat
, WM_SETTEXT
, 0,
1026 (LPARAM
)(USER_HEAP_SEG_ADDR(hTemp
) + 1) );
1028 temp
[0] = 'A'+drive
;
1031 SendDlgItemMessage( hDlg
, nIDStat
, WM_SETTEXT
, 0,
1032 (LPARAM
)USER_HEAP_SEG_ADDR(hTemp
) );
1034 USER_HEAP_FREE( hTemp
);