4 * Copyright 1993 Martin Ayotte
5 * Copyright 1995 Bernd Schmidt
11 #include <sys/types.h>
15 #include "sysmetrics.h"
26 * Note: Combos are probably implemented in a different way by Windows.
27 * Using a message spy for Windows, you can see some undocumented
28 * messages being passed between ComboBox and ComboLBox.
29 * I hope no programs rely on the implementation of combos.
32 static HBITMAP hComboBit
= 0;
33 static WORD CBitHeight
, CBitWidth
;
35 static int COMBO_Init()
39 dprintf_combo(stddeb
, "COMBO_Init\n");
40 hComboBit
= LoadBitmap(0, MAKEINTRESOURCE(OBM_COMBO
));
41 GetObject(hComboBit
, sizeof(BITMAP
), (LPSTR
)&bm
);
42 CBitHeight
= bm
.bmHeight
;
43 CBitWidth
= bm
.bmWidth
;
47 LPHEADCOMBO
ComboGetStorageHeader(HWND hwnd
)
49 return (LPHEADCOMBO
)GetWindowLong(hwnd
,4);
52 LPHEADLIST
ComboGetListHeader(HWND hwnd
)
54 return (LPHEADLIST
)GetWindowLong(hwnd
,0);
57 int CreateComboStruct(HWND hwnd
, LONG style
)
61 lphc
= (LPHEADCOMBO
)malloc(sizeof(HEADCOMBO
));
62 SetWindowLong(hwnd
,4,(LONG
)lphc
);
67 lphc
->dwStyle
= style
;
68 lphc
->DropDownVisible
= FALSE
;
72 void ComboUpdateWindow(HWND hwnd
, LPHEADLIST lphl
, LPHEADCOMBO lphc
, BOOL repaint
)
74 SetScrollRange(lphc
->hWndLBox
, SB_VERT
, 0, ListMaxFirstVisible(lphl
), TRUE
);
75 if (repaint
&& lphl
->bRedrawFlag
) {
76 InvalidateRect(hwnd
, NULL
, TRUE
);
80 /***********************************************************************
83 static LONG
CBNCCreate(HWND hwnd
, WORD wParam
, LONG lParam
)
85 CREATESTRUCT
*createStruct
;
87 if (!hComboBit
) COMBO_Init();
89 createStruct
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
90 createStruct
->style
&= ~(WS_VSCROLL
| WS_HSCROLL
);
91 SetWindowLong(hwnd
, GWL_STYLE
, createStruct
->style
);
93 dprintf_combo(stddeb
,"ComboBox WM_NCCREATE!\n");
94 return DefWindowProc(hwnd
, WM_NCCREATE
, wParam
, lParam
);
98 /***********************************************************************
101 static LONG
CBCreate(HWND hwnd
, WORD wParam
, LONG lParam
)
106 LONG cstyle
= GetWindowLong(hwnd
,GWL_STYLE
);
108 char className
[] = "COMBOLBOX"; /* Hack so that class names are > 0x10000 */
109 char editName
[] = "EDIT";
111 /* translate combo into listbox styles */
112 if (cstyle
& CBS_OWNERDRAWFIXED
) style
|= LBS_OWNERDRAWFIXED
;
113 if (cstyle
& CBS_OWNERDRAWVARIABLE
) style
|= LBS_OWNERDRAWVARIABLE
;
114 if (cstyle
& CBS_SORT
) style
|= LBS_SORT
;
115 if (cstyle
& CBS_HASSTRINGS
) style
|= LBS_HASSTRINGS
;
117 CreateListBoxStruct(hwnd
, ODT_COMBOBOX
, style
, GetParent(hwnd
));
118 CreateComboStruct(hwnd
,cstyle
);
119 lphl
= ComboGetListHeader(hwnd
);
120 lphc
= ComboGetStorageHeader(hwnd
);
122 GetClientRect(hwnd
,&rect
);
123 GetWindowRect(hwnd
,&lboxrect
);
124 /* FIXME: combos with edit controls are broken. */
126 case CBS_SIMPLE
: /* edit control, list always visible */
127 dprintf_combo(stddeb
,"CBS_SIMPLE\n");
128 SetRectEmpty(&lphc
->RectButton
);
129 lphc
->LBoxTop
= lphl
->StdItemHeight
;
130 lphc
->hWndEdit
= CreateWindow(editName
, "",
131 WS_CHILD
| WS_CLIPCHILDREN
| WS_VISIBLE
| SS_LEFT
,
132 0, 0, rect
.right
, lphl
->StdItemHeight
,
133 hwnd
, 1, GetWindowWord(hwnd
,GWW_HINSTANCE
), 0L);
135 case CBS_DROPDOWN
: /* edit control, dropdown listbox */
136 dprintf_combo(stddeb
,"CBS_DROPDOWN\n");
137 lphc
->RectButton
= rect
;
138 lphc
->RectButton
.left
= lphc
->RectButton
.right
- 6 - CBitWidth
;
139 lphc
->RectButton
.bottom
= lphc
->RectButton
.top
+ lphl
->StdItemHeight
;
140 lphc
->LBoxTop
= lphl
->StdItemHeight
;
141 SetWindowPos(hwnd
, 0, 0, 0, rect
.right
- rect
.left
+ 2*SYSMETRICS_CXBORDER
,
142 lphl
->StdItemHeight
+ 2*SYSMETRICS_CYBORDER
,
143 SWP_NOMOVE
| SWP_NOZORDER
);
144 lphc
->hWndEdit
= CreateWindow(editName
, "",
145 WS_CHILD
| WS_CLIPCHILDREN
| WS_VISIBLE
| SS_LEFT
,
146 0, 0, lphc
->RectButton
.left
, lphl
->StdItemHeight
,
147 hwnd
, 1, GetWindowWord(hwnd
,GWW_HINSTANCE
), 0L);
149 case CBS_DROPDOWNLIST
: /* static control, downdown listbox */
150 dprintf_combo(stddeb
,"CBS_DROPDOWNLIST\n");
151 lphc
->RectButton
= rect
;
152 lphc
->RectButton
.left
= lphc
->RectButton
.right
- 6 - CBitWidth
;
153 lphc
->RectButton
.bottom
= lphc
->RectButton
.top
+ lphl
->StdItemHeight
;
154 lphc
->LBoxTop
= lphl
->StdItemHeight
;
155 SetWindowPos(hwnd
, 0, 0, 0, rect
.right
- rect
.left
+ 2*SYSMETRICS_CXBORDER
,
156 lphl
->StdItemHeight
+ 2*SYSMETRICS_CYBORDER
,
157 SWP_NOMOVE
| SWP_NOZORDER
);
160 lboxrect
.top
+= lphc
->LBoxTop
;
161 /* FIXME: WinSight says these should be CHILD windows with the TOPMOST flag
162 * set. Wine doesn't support TOPMOST, and simply setting the WS_CHILD
163 * flag doesn't work. */
164 lphc
->hWndLBox
= CreateWindow(className
, "",
165 WS_POPUP
| WS_BORDER
| WS_VSCROLL
,
166 lboxrect
.left
, lboxrect
.top
,
167 lboxrect
.right
- lboxrect
.left
,
168 lboxrect
.bottom
- lboxrect
.top
,
169 0, 0, GetWindowWord(hwnd
,GWW_HINSTANCE
),
170 (SEGPTR
)MAKELONG(hwnd
, hwnd
));
171 ShowWindow(lphc
->hWndLBox
, SW_HIDE
);
172 dprintf_combo(stddeb
,"Combo Creation LBox=%X!\n", lphc
->hWndLBox
);
176 /***********************************************************************
179 static LONG
CBDestroy(HWND hwnd
, WORD wParam
, LONG lParam
)
181 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
183 ListBoxResetContent(lphl
);
184 DestroyListBoxStruct(lphl
);
185 dprintf_combo(stddeb
,"Combo WM_DESTROY %p !\n", lphl
);
189 /***********************************************************************
192 static LONG
CBPaint(HWND hwnd
, WORD wParam
, LONG lParam
)
194 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
195 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
204 hdc
= BeginPaint(hwnd
, &ps
);
206 if (hComboBit
!= 0) {
207 GRAPH_DrawReliefRect(hdc
, &lphc
->RectButton
, 2, 2, FALSE
);
208 GRAPH_DrawBitmap(hdc
, hComboBit
,
209 lphc
->RectButton
.left
+ 3,lphc
->RectButton
.top
+ 2,
210 0, 0, CBitWidth
, CBitHeight
);
212 if (!IsWindowVisible(hwnd
) || !lphl
->bRedrawFlag
213 || (lphc
->dwStyle
& 3) != CBS_DROPDOWNLIST
)
215 /* we don't want to draw an entry when there is an edit control */
220 hOldFont
= SelectObject(hdc
, lphl
->hFont
);
222 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLOR
, hdc
,
223 MAKELONG(hwnd
, CTLCOLOR_LISTBOX
));
224 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
226 GetClientRect(hwnd
, &rect
);
227 rect
.right
-= (lphc
->RectButton
.right
- lphc
->RectButton
.left
);
228 FillRect(hdc
, &rect
, hBrush
);
230 lpls
= ListBoxGetItem(lphl
,lphl
->ItemFocused
);
232 height
= lpls
->mis
.itemHeight
;
233 rect
.bottom
= rect
.top
+ height
;
235 if (lphl
->OwnerDrawn
) {
236 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &rect
, ODA_DRAWENTIRE
, 0);
238 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &rect
, ODA_DRAWENTIRE
, 0);
240 if (GetFocus() == hwnd
)
241 ListBoxDrawItem (hwnd
,lphl
, hdc
, lpls
, &rect
, ODA_FOCUS
, ODS_FOCUS
);
243 SelectObject(hdc
,hOldFont
);
248 /***********************************************************************
251 static LONG
CBGetDlgCode(HWND hwnd
, WORD wParam
, LONG lParam
)
253 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
256 /***********************************************************************
259 static LONG
CBLButtonDown(HWND hwnd
, WORD wParam
, LONG lParam
)
261 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
262 SendMessage(hwnd
,CB_SHOWDROPDOWN
,!lphc
->DropDownVisible
,0);
266 /***********************************************************************
269 static LONG
CBKeyDown(HWND hwnd
, WORD wParam
, LONG lParam
)
271 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
272 WORD newFocused
= lphl
->ItemFocused
;
279 newFocused
= lphl
->ItemsCount
- 1;
282 if (newFocused
> 0) newFocused
--;
291 if (newFocused
>= lphl
->ItemsCount
)
292 newFocused
= lphl
->ItemsCount
- 1;
294 ListBoxSetCurSel(lphl
, newFocused
);
295 ListBoxSendNotification(lphl
, hwnd
, CBN_SELCHANGE
);
297 lphl
->ItemFocused
= newFocused
;
298 ListBoxScrollToFocus(lphl
);
299 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
300 InvalidateRect(hwnd
, NULL
, TRUE
);
305 /***********************************************************************
308 static LONG
CBChar(HWND hwnd
, WORD wParam
, LONG lParam
)
310 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
313 newFocused
= ListBoxFindNextMatch(lphl
, wParam
);
314 if (newFocused
== (WORD
)LB_ERR
) return 0;
316 if (newFocused
>= lphl
->ItemsCount
)
317 newFocused
= lphl
->ItemsCount
- 1;
319 ListBoxSetCurSel(lphl
, newFocused
);
320 ListBoxSendNotification(lphl
, hwnd
, CBN_SELCHANGE
);
321 lphl
->ItemFocused
= newFocused
;
322 ListBoxScrollToFocus(lphl
);
324 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
325 InvalidateRect(hwnd
, NULL
, TRUE
);
330 /***********************************************************************
333 static LONG
CBKillFocus(HWND hwnd
, WORD wParam
, LONG lParam
)
338 /***********************************************************************
341 static LONG
CBSetFocus(HWND hwnd
, WORD wParam
, LONG lParam
)
346 /***********************************************************************
349 static LONG
CBResetContent(HWND hwnd
, WORD wParam
, LONG lParam
)
351 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
352 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
354 ListBoxResetContent(lphl
);
355 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
359 /***********************************************************************
362 static LONG
CBDir(HWND hwnd
, WORD wParam
, LONG lParam
)
365 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
366 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
368 wRet
= ListBoxDirectory(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
369 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
373 /***********************************************************************
376 static LONG
CBInsertString(HWND hwnd
, WORD wParam
, LONG lParam
)
379 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
380 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
382 if (lphl
->HasStrings
)
383 wRet
= ListBoxInsertString(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
385 wRet
= ListBoxInsertString(lphl
, wParam
, (LPSTR
)lParam
);
387 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
391 /***********************************************************************
394 static LONG
CBAddString(HWND hwnd
, WORD wParam
, LONG lParam
)
397 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
398 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
400 if (lphl
->HasStrings
)
401 wRet
= ListBoxAddString(lphl
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
403 wRet
= ListBoxAddString(lphl
, (LPSTR
)lParam
);
405 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
409 /***********************************************************************
412 static LONG
CBDeleteString(HWND hwnd
, WORD wParam
, LONG lParam
)
414 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
415 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
416 LONG lRet
= ListBoxDeleteString(lphl
,wParam
);
418 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
422 /***********************************************************************
425 static LONG
CBSelectString(HWND hwnd
, WORD wParam
, LONG lParam
)
427 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
430 wRet
= ListBoxFindString(lphl
, wParam
, lParam
);
432 /* XXX add functionality here */
437 /***********************************************************************
440 static LONG
CBFindString(HWND hwnd
, WORD wParam
, LONG lParam
)
442 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
443 return ListBoxFindString(lphl
, wParam
, lParam
);
446 /***********************************************************************
449 static LONG
CBGetCount(HWND hwnd
, WORD wParam
, LONG lParam
)
451 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
452 return lphl
->ItemsCount
;
455 /***********************************************************************
458 static LONG
CBSetCurSel(HWND hwnd
, WORD wParam
, LONG lParam
)
460 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
463 wRet
= ListBoxSetCurSel(lphl
, wParam
);
465 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
466 InvalidateRect(hwnd
, NULL
, TRUE
);
471 /***********************************************************************
474 static LONG
CBGetCurSel(HWND hwnd
, WORD wParam
, LONG lParam
)
476 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
477 return lphl
->ItemFocused
;
480 /***********************************************************************
483 static LONG
CBGetItemHeight(HWND hwnd
, WORD wParam
, LONG lParam
)
485 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
486 LPLISTSTRUCT lpls
= ListBoxGetItem (lphl
, wParam
);
488 if (lpls
== NULL
) return LB_ERR
;
489 return lpls
->mis
.itemHeight
;
492 /***********************************************************************
495 static LONG
CBSetItemHeight(HWND hwnd
, WORD wParam
, LONG lParam
)
497 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
498 return ListBoxSetItemHeight(lphl
, wParam
, lParam
);
501 /***********************************************************************
504 static LONG
CBSetRedraw(HWND hwnd
, WORD wParam
, LONG lParam
)
506 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
507 lphl
->bRedrawFlag
= wParam
;
511 /***********************************************************************
514 static LONG
CBSetFont(HWND hwnd
, WORD wParam
, LONG lParam
)
516 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
519 lphl
->hFont
= GetStockObject(SYSTEM_FONT
);
521 lphl
->hFont
= wParam
;
526 /***********************************************************************
529 static LONG
CBGetLBTextLen(HWND hwnd
, WORD wParam
, LONG lParam
)
531 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
532 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
,wParam
);
534 if (lpls
== NULL
|| !lphl
->HasStrings
) return LB_ERR
;
535 return strlen(lpls
->itemText
);
538 /***********************************************************************
541 static LONG
CBGetLBText(HWND hwnd
, WORD wParam
, LONG lParam
)
543 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
544 return ListBoxGetText(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
547 /***********************************************************************
550 static LONG
CBGetItemData(HWND hwnd
, WORD wParam
, LONG lParam
)
552 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
553 return ListBoxGetItemData(lphl
, wParam
);
556 /***********************************************************************
559 static LONG
CBSetItemData(HWND hwnd
, WORD wParam
, LONG lParam
)
561 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
562 return ListBoxSetItemData(lphl
, wParam
, lParam
);
565 /***********************************************************************
568 static LONG
CBShowDropDown(HWND hwnd
, WORD wParam
, LONG lParam
)
570 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
573 if (lphc
->dwStyle
& 3 == CBS_SIMPLE
) return LB_ERR
;
576 if (wParam
!= lphc
->DropDownVisible
) {
577 lphc
->DropDownVisible
= wParam
;
578 GetWindowRect(hwnd
,&rect
);
579 SetWindowPos(lphc
->hWndLBox
, 0, rect
.left
, rect
.top
+lphc
->LBoxTop
, 0, 0,
580 SWP_NOSIZE
| (wParam
? SWP_SHOWWINDOW
: SWP_HIDEWINDOW
));
581 if (!wParam
) SetFocus(hwnd
);
587 /***********************************************************************
590 LONG
ComboBoxWndProc(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
593 case WM_NCCREATE
: return CBNCCreate(hwnd
, wParam
, lParam
);
594 case WM_CREATE
: return CBCreate(hwnd
, wParam
, lParam
);
595 case WM_DESTROY
: return CBDestroy(hwnd
, wParam
, lParam
);
596 case WM_GETDLGCODE
: return CBGetDlgCode(hwnd
, wParam
, lParam
);
597 case WM_KEYDOWN
: return CBKeyDown(hwnd
, wParam
, lParam
);
598 case WM_CHAR
: return CBChar(hwnd
, wParam
, lParam
);
599 case WM_SETFONT
: return CBSetFont(hwnd
, wParam
, lParam
);
600 case WM_SETREDRAW
: return CBSetRedraw(hwnd
, wParam
, lParam
);
601 case WM_PAINT
: return CBPaint(hwnd
, wParam
, lParam
);
602 case WM_LBUTTONDOWN
: return CBLButtonDown(hwnd
, wParam
, lParam
);
603 case WM_SETFOCUS
: return CBSetFocus(hwnd
, wParam
, lParam
);
604 case WM_KILLFOCUS
: return CBKillFocus(hwnd
, wParam
, lParam
);
605 case CB_RESETCONTENT
: return CBResetContent(hwnd
, wParam
, lParam
);
606 case CB_DIR
: return CBDir(hwnd
, wParam
, lParam
);
607 case CB_ADDSTRING
: return CBAddString(hwnd
, wParam
, lParam
);
608 case CB_INSERTSTRING
: return CBInsertString(hwnd
, wParam
, lParam
);
609 case CB_DELETESTRING
: return CBDeleteString(hwnd
, wParam
, lParam
);
610 case CB_FINDSTRING
: return CBFindString(hwnd
, wParam
, lParam
);
611 case CB_GETCOUNT
: return CBGetCount(hwnd
, wParam
, lParam
);
612 case CB_GETCURSEL
: return CBGetCurSel(hwnd
, wParam
, lParam
);
613 case CB_GETITEMDATA
: return CBGetItemData(hwnd
, wParam
, lParam
);
614 case CB_GETITEMHEIGHT
: return CBGetItemHeight(hwnd
, wParam
, lParam
);
615 case CB_GETLBTEXT
: return CBGetLBText(hwnd
, wParam
, lParam
);
616 case CB_GETLBTEXTLEN
: return CBGetLBTextLen(hwnd
, wParam
, lParam
);
617 case CB_SELECTSTRING
: return CBSelectString(hwnd
, wParam
, lParam
);
618 case CB_SETITEMDATA
: return CBSetItemData(hwnd
, wParam
, lParam
);
619 case CB_SETCURSEL
: return CBSetCurSel(hwnd
, wParam
, lParam
);
620 case CB_SETITEMHEIGHT
: return CBSetItemHeight(hwnd
, wParam
, lParam
);
621 case CB_SHOWDROPDOWN
: return CBShowDropDown(hwnd
, wParam
, lParam
);
623 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
626 /*--------------------------------------------------------------------*/
627 /* ComboLBox code starts here */
629 HWND
CLBoxGetCombo(HWND hwnd
)
631 return GetWindowWord(hwnd
,0);
634 LPHEADLIST
CLBoxGetListHeader(HWND hwnd
)
636 return ComboGetListHeader(CLBoxGetCombo(hwnd
));
639 /***********************************************************************
642 static LONG
CBLCreate( HWND hwnd
, WORD wParam
, LONG lParam
)
644 CREATESTRUCT
*createStruct
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
645 SetWindowWord(hwnd
,0,LOWORD(createStruct
->lpCreateParams
));
649 /***********************************************************************
652 static LONG
CBLGetDlgCode( HWND hwnd
, WORD wParam
, LONG lParam
)
654 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
657 /***********************************************************************
660 static LONG
CBLKeyDown( HWND hwnd
, WORD wParam
, LONG lParam
)
662 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
663 WORD newFocused
= lphl
->ItemFocused
;
670 newFocused
= lphl
->ItemsCount
- 1;
673 if (newFocused
> 0) newFocused
--;
679 if (newFocused
> lphl
->ItemsVisible
) {
680 newFocused
-= lphl
->ItemsVisible
;
686 newFocused
+= lphl
->ItemsVisible
;
692 if (newFocused
>= lphl
->ItemsCount
)
693 newFocused
= lphl
->ItemsCount
- 1;
695 ListBoxSetCurSel(lphl
, newFocused
);
696 ListBoxSendNotification(lphl
, hwnd
, CBN_SELCHANGE
);
698 lphl
->ItemFocused
= newFocused
;
699 ListBoxScrollToFocus(lphl
);
700 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
701 InvalidateRect(hwnd
, NULL
, TRUE
);
705 /***********************************************************************
708 static LONG
CBLChar( HWND hwnd
, WORD wParam
, LONG lParam
)
713 /***********************************************************************
716 static LONG
CBLPaint( HWND hwnd
, WORD wParam
, LONG lParam
)
718 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
723 HWND combohwnd
= CLBoxGetCombo(hwnd
);
729 hdc
= BeginPaint( hwnd
, &ps
);
731 if (!IsWindowVisible(hwnd
) || !lphl
->bRedrawFlag
) {
736 hOldFont
= SelectObject(hdc
, lphl
->hFont
);
737 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLOR
, hdc
,
738 MAKELONG(hwnd
, CTLCOLOR_LISTBOX
));
740 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
742 GetClientRect(hwnd
, &rect
);
743 FillRect(hdc
, &rect
, hBrush
);
745 lpls
= lphl
->lpFirst
;
747 lphl
->ItemsVisible
= 0;
748 for(i
= 0; i
< lphl
->ItemsCount
; i
++) {
749 if (lpls
== NULL
) break;
751 if (i
>= lphl
->FirstVisible
) {
752 height
= lpls
->mis
.itemHeight
;
754 if (top
> rect
.bottom
) break;
755 lpls
->itemRect
.top
= top
;
756 lpls
->itemRect
.bottom
= top
+ height
;
757 lpls
->itemRect
.left
= rect
.left
;
758 lpls
->itemRect
.right
= rect
.right
;
760 dprintf_listbox(stddeb
,"drawing item: %d %d %d %d %d\n",rect
.left
,top
,rect
.right
,top
+height
,lpls
->itemState
);
761 if (lphl
->OwnerDrawn
) {
762 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
, 0);
764 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_SELECT
, ODS_SELECTED
);
766 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
,
769 if ((lphl
->ItemFocused
== i
) && GetFocus() == hwnd
)
770 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_FOCUS
, ODS_FOCUS
);
773 lphl
->ItemsVisible
++;
778 SelectObject(hdc
,hOldFont
);
779 EndPaint( hwnd
, &ps
);
784 /***********************************************************************
787 static LONG
CBLKillFocus( HWND hwnd
, WORD wParam
, LONG lParam
)
789 /* SendMessage(CLBoxGetCombo(hwnd),CB_SHOWDROPDOWN,0,0);*/
793 /***********************************************************************
796 static LONG
CBLActivate( HWND hwnd
, WORD wParam
, LONG lParam
)
798 if (wParam
== WA_INACTIVE
)
799 SendMessage(CLBoxGetCombo(hwnd
),CB_SHOWDROPDOWN
,0,0);
803 /***********************************************************************
806 static LONG
CBLLButtonDown( HWND hwnd
, WORD wParam
, LONG lParam
)
808 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
815 lphl
->PrevFocused
= lphl
->ItemFocused
;
817 y
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
821 ListBoxSetCurSel(lphl
, y
);
822 ListBoxGetItemRect(lphl
, y
, &rectsel
);
824 InvalidateRect(hwnd
, NULL
, TRUE
);
828 /***********************************************************************
831 static LONG
CBLLButtonUp( HWND hwnd
, WORD wParam
, LONG lParam
)
833 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
835 if (GetCapture() == hwnd
) ReleaseCapture();
837 if (lphl
->PrevFocused
!= lphl
->ItemFocused
) {
838 SendMessage(CLBoxGetCombo(hwnd
),CB_SETCURSEL
,lphl
->ItemFocused
,0);
839 ListBoxSendNotification(lphl
, CLBoxGetCombo(hwnd
), CBN_SELCHANGE
);
841 SendMessage(CLBoxGetCombo(hwnd
),CB_SHOWDROPDOWN
,0,0);
846 /***********************************************************************
849 static LONG
CBLMouseMove( HWND hwnd
, WORD wParam
, LONG lParam
)
851 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
854 RECT rect
, rectsel
; /* XXX Broken */
856 if ((wParam
& MK_LBUTTON
) != 0) {
859 if (lphl
->FirstVisible
> 0) {
860 lphl
->FirstVisible
--;
861 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
862 InvalidateRect(hwnd
, NULL
, TRUE
);
866 GetClientRect(hwnd
, &rect
);
867 if (y
>= rect
.bottom
) {
868 if (lphl
->FirstVisible
< ListMaxFirstVisible(lphl
)) {
869 lphl
->FirstVisible
++;
870 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
871 InvalidateRect(hwnd
, NULL
, TRUE
);
875 if ((y
> 0) && (y
< (rect
.bottom
- 4))) {
876 if ((y
< rectsel
.top
) || (y
> rectsel
.bottom
)) {
877 wRet
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
878 if (wRet
== lphl
->ItemFocused
) return 0;
879 ListBoxSetCurSel(lphl
, wRet
);
880 ListBoxGetItemRect(lphl
, wRet
, &rectsel
);
881 InvalidateRect(hwnd
, NULL
, TRUE
);
889 /***********************************************************************
892 static LONG
CBLVScroll( HWND hwnd
, WORD wParam
, LONG lParam
)
894 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
897 y
= lphl
->FirstVisible
;
901 if (lphl
->FirstVisible
> 0)
902 lphl
->FirstVisible
--;
906 lphl
->FirstVisible
++;
910 if (lphl
->FirstVisible
> lphl
->ItemsVisible
) {
911 lphl
->FirstVisible
-= lphl
->ItemsVisible
;
913 lphl
->FirstVisible
= 0;
918 lphl
->FirstVisible
+= lphl
->ItemsVisible
;
922 lphl
->FirstVisible
= LOWORD(lParam
);
926 if (lphl
->FirstVisible
> ListMaxFirstVisible(lphl
))
927 lphl
->FirstVisible
= ListMaxFirstVisible(lphl
);
929 if (y
!= lphl
->FirstVisible
) {
930 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
931 InvalidateRect(hwnd
, NULL
, TRUE
);
937 /***********************************************************************
940 LONG
ComboLBoxWndProc(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
943 case WM_CREATE
: return CBLCreate(hwnd
, wParam
, lParam
);
944 case WM_GETDLGCODE
: return CBLGetDlgCode(hwnd
, wParam
, lParam
);
945 case WM_KEYDOWN
: return CBLKeyDown(hwnd
, wParam
, lParam
);
946 case WM_CHAR
: return CBLChar(hwnd
, wParam
, lParam
);
947 case WM_PAINT
: return CBLPaint(hwnd
, wParam
, lParam
);
948 case WM_KILLFOCUS
: return CBLKillFocus(hwnd
, wParam
, lParam
);
949 case WM_ACTIVATE
: return CBLActivate(hwnd
, wParam
, lParam
);
950 case WM_LBUTTONDOWN
: return CBLLButtonDown(hwnd
, wParam
, lParam
);
951 case WM_LBUTTONUP
: return CBLLButtonUp(hwnd
, wParam
, lParam
);
952 case WM_MOUSEMOVE
: return CBLMouseMove(hwnd
, wParam
, lParam
);
953 case WM_VSCROLL
: return CBLVScroll(hwnd
, wParam
, lParam
);
955 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
958 /************************************************************************
959 * DlgDirSelectComboBox [USER.194]
961 BOOL
DlgDirSelectComboBox(HWND hDlg
, LPSTR lpStr
, int nIDLBox
)
963 fprintf(stdnimp
,"DlgDirSelectComboBox(%04X, '%s', %d) \n",
964 hDlg
, lpStr
, nIDLBox
);
969 /************************************************************************
970 * DlgDirListComboBox [USER.195]
972 int DlgDirListComboBox(HWND hDlg
, SEGPTR PathSpec
,
973 int nIDLBox
, int nIDStat
, WORD wType
)
977 LPSTR lpPathSpec
= PTR_SEG_TO_LIN(PathSpec
);
979 dprintf_combo(stddeb
,"DlgDirListComboBox(%04X, '%s', %d, %d, %04X) \n",
980 hDlg
, lpPathSpec
, nIDLBox
, nIDStat
, wType
);
984 hWnd
= GetDlgItem(hDlg
, nIDLBox
);
985 lphl
= ComboGetListHeader(hWnd
);
986 lphc
= ComboGetStorageHeader(hWnd
);
987 ListBoxResetContent(lphl
);
988 ret
= ListBoxDirectory(lphl
, wType
, lpPathSpec
);
989 ComboUpdateWindow(hWnd
, lphl
, lphc
, TRUE
);
997 drive
= DOS_GetDefaultDrive();
998 hTemp
= USER_HEAP_ALLOC( 256 );
999 temp
= (char *) USER_HEAP_LIN_ADDR( hTemp
);
1000 strcpy( temp
+3, DOS_GetCurrentDir(drive
) );
1001 if( temp
[3] == '\\' ) {
1002 temp
[1] = 'A'+drive
;
1004 SendDlgItemMessage( hDlg
, nIDStat
, WM_SETTEXT
, 0,
1005 USER_HEAP_SEG_ADDR(hTemp
) + 1 );
1007 temp
[0] = 'A'+drive
;
1010 SendDlgItemMessage( hDlg
, nIDStat
, WM_SETTEXT
, 0,
1011 USER_HEAP_SEG_ADDR(hTemp
) );
1013 USER_HEAP_FREE( hTemp
);