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
, 1, GetWindowWord(hwnd
,GWW_HINSTANCE
), 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
, 1, GetWindowWord(hwnd
,GWW_HINSTANCE
), 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, GetWindowWord(hwnd
,GWW_HINSTANCE
),
171 (SEGPTR
)MAKELONG(hwnd
, hwnd
));
172 ShowWindow(lphc
->hWndLBox
, SW_HIDE
);
173 dprintf_combo(stddeb
,"Combo Creation LBox=%X!\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
);
223 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLOR
, hdc
,
224 MAKELONG(hwnd
, CTLCOLOR_LISTBOX
));
225 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
227 GetClientRect(hwnd
, &rect
);
228 rect
.right
-= (lphc
->RectButton
.right
- lphc
->RectButton
.left
);
229 FillRect(hdc
, &rect
, hBrush
);
231 lpls
= ListBoxGetItem(lphl
,lphl
->ItemFocused
);
233 height
= lpls
->mis
.itemHeight
;
234 rect
.bottom
= rect
.top
+ height
;
236 if (lphl
->OwnerDrawn
) {
237 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &rect
, ODA_DRAWENTIRE
, 0);
239 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &rect
, ODA_DRAWENTIRE
, 0);
241 if (GetFocus() == hwnd
)
242 ListBoxDrawItem (hwnd
,lphl
, hdc
, lpls
, &rect
, ODA_FOCUS
, ODS_FOCUS
);
244 SelectObject(hdc
,hOldFont
);
249 /***********************************************************************
252 static LONG
CBGetDlgCode(HWND hwnd
, WORD wParam
, LONG lParam
)
254 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
257 /***********************************************************************
260 static LONG
CBLButtonDown(HWND hwnd
, WORD wParam
, LONG lParam
)
262 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
263 SendMessage(hwnd
,CB_SHOWDROPDOWN
,!lphc
->DropDownVisible
,0);
267 /***********************************************************************
270 static LONG
CBKeyDown(HWND hwnd
, WORD wParam
, LONG lParam
)
272 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
273 WORD newFocused
= lphl
->ItemFocused
;
280 newFocused
= lphl
->ItemsCount
- 1;
283 if (newFocused
> 0) newFocused
--;
292 if (newFocused
>= lphl
->ItemsCount
)
293 newFocused
= lphl
->ItemsCount
- 1;
295 ListBoxSetCurSel(lphl
, newFocused
);
296 ListBoxSendNotification(lphl
, hwnd
, CBN_SELCHANGE
);
298 lphl
->ItemFocused
= newFocused
;
299 ListBoxScrollToFocus(lphl
);
300 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
301 InvalidateRect(hwnd
, NULL
, TRUE
);
306 /***********************************************************************
309 static LONG
CBChar(HWND hwnd
, WORD wParam
, LONG lParam
)
311 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
314 newFocused
= ListBoxFindNextMatch(lphl
, wParam
);
315 if (newFocused
== (WORD
)LB_ERR
) return 0;
317 if (newFocused
>= lphl
->ItemsCount
)
318 newFocused
= lphl
->ItemsCount
- 1;
320 ListBoxSetCurSel(lphl
, newFocused
);
321 ListBoxSendNotification(lphl
, hwnd
, CBN_SELCHANGE
);
322 lphl
->ItemFocused
= newFocused
;
323 ListBoxScrollToFocus(lphl
);
325 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
326 InvalidateRect(hwnd
, NULL
, TRUE
);
331 /***********************************************************************
334 static LONG
CBKillFocus(HWND hwnd
, WORD wParam
, LONG lParam
)
339 /***********************************************************************
342 static LONG
CBSetFocus(HWND hwnd
, WORD wParam
, LONG lParam
)
347 /***********************************************************************
350 static LONG
CBResetContent(HWND hwnd
, WORD wParam
, LONG lParam
)
352 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
353 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
355 ListBoxResetContent(lphl
);
356 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
360 /***********************************************************************
363 static LONG
CBDir(HWND hwnd
, WORD wParam
, LONG lParam
)
366 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
367 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
369 wRet
= ListBoxDirectory(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
370 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
374 /***********************************************************************
377 static LONG
CBInsertString(HWND hwnd
, WORD wParam
, LONG lParam
)
380 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
381 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
383 if (lphl
->HasStrings
)
384 wRet
= ListBoxInsertString(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
386 wRet
= ListBoxInsertString(lphl
, wParam
, (LPSTR
)lParam
);
388 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
392 /***********************************************************************
395 static LONG
CBAddString(HWND hwnd
, WORD wParam
, LONG lParam
)
398 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
399 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
401 if (lphl
->HasStrings
)
402 wRet
= ListBoxAddString(lphl
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
404 wRet
= ListBoxAddString(lphl
, (LPSTR
)lParam
);
406 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
410 /***********************************************************************
413 static LONG
CBDeleteString(HWND hwnd
, WORD wParam
, LONG lParam
)
415 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
416 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
417 LONG lRet
= ListBoxDeleteString(lphl
,wParam
);
419 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
423 /***********************************************************************
426 static LONG
CBSelectString(HWND hwnd
, WORD wParam
, LONG lParam
)
428 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
431 wRet
= ListBoxFindString(lphl
, wParam
, lParam
);
433 /* XXX add functionality here */
438 /***********************************************************************
441 static LONG
CBFindString(HWND hwnd
, WORD wParam
, LONG lParam
)
443 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
444 return ListBoxFindString(lphl
, wParam
, lParam
);
447 /***********************************************************************
450 static LONG
CBGetCount(HWND hwnd
, WORD wParam
, LONG lParam
)
452 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
453 return lphl
->ItemsCount
;
456 /***********************************************************************
459 static LONG
CBSetCurSel(HWND hwnd
, WORD wParam
, LONG lParam
)
461 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
464 wRet
= ListBoxSetCurSel(lphl
, wParam
);
466 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
467 InvalidateRect(hwnd
, NULL
, TRUE
);
472 /***********************************************************************
475 static LONG
CBGetCurSel(HWND hwnd
, WORD wParam
, LONG lParam
)
477 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
478 return lphl
->ItemFocused
;
481 /***********************************************************************
484 static LONG
CBGetItemHeight(HWND hwnd
, WORD wParam
, LONG lParam
)
486 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
487 LPLISTSTRUCT lpls
= ListBoxGetItem (lphl
, wParam
);
489 if (lpls
== NULL
) return LB_ERR
;
490 return lpls
->mis
.itemHeight
;
493 /***********************************************************************
496 static LONG
CBSetItemHeight(HWND hwnd
, WORD wParam
, LONG lParam
)
498 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
499 return ListBoxSetItemHeight(lphl
, wParam
, lParam
);
502 /***********************************************************************
505 static LONG
CBSetRedraw(HWND hwnd
, WORD wParam
, LONG lParam
)
507 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
508 lphl
->bRedrawFlag
= wParam
;
512 /***********************************************************************
515 static LONG
CBSetFont(HWND hwnd
, WORD wParam
, LONG lParam
)
517 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
520 lphl
->hFont
= GetStockObject(SYSTEM_FONT
);
522 lphl
->hFont
= wParam
;
527 /***********************************************************************
530 static LONG
CBGetLBTextLen(HWND hwnd
, WORD wParam
, LONG lParam
)
532 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
533 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
,wParam
);
535 if (lpls
== NULL
|| !lphl
->HasStrings
) return LB_ERR
;
536 return strlen(lpls
->itemText
);
539 /***********************************************************************
542 static LONG
CBGetLBText(HWND hwnd
, WORD wParam
, LONG lParam
)
544 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
545 return ListBoxGetText(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
548 /***********************************************************************
551 static LONG
CBGetItemData(HWND hwnd
, WORD wParam
, LONG lParam
)
553 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
554 return ListBoxGetItemData(lphl
, wParam
);
557 /***********************************************************************
560 static LONG
CBSetItemData(HWND hwnd
, WORD wParam
, LONG lParam
)
562 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
563 return ListBoxSetItemData(lphl
, wParam
, lParam
);
566 /***********************************************************************
569 static LONG
CBShowDropDown(HWND hwnd
, WORD wParam
, LONG lParam
)
571 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
574 if (lphc
->dwStyle
& 3 == CBS_SIMPLE
) return LB_ERR
;
577 if (wParam
!= lphc
->DropDownVisible
) {
578 lphc
->DropDownVisible
= wParam
;
579 GetWindowRect(hwnd
,&rect
);
580 SetWindowPos(lphc
->hWndLBox
, 0, rect
.left
, rect
.top
+lphc
->LBoxTop
, 0, 0,
581 SWP_NOSIZE
| (wParam
? SWP_SHOWWINDOW
: SWP_HIDEWINDOW
));
582 if (!wParam
) SetFocus(hwnd
);
588 /***********************************************************************
591 LONG
ComboBoxWndProc(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
594 case WM_NCCREATE
: return CBNCCreate(hwnd
, wParam
, lParam
);
595 case WM_CREATE
: return CBCreate(hwnd
, wParam
, lParam
);
596 case WM_DESTROY
: return CBDestroy(hwnd
, wParam
, lParam
);
597 case WM_GETDLGCODE
: return CBGetDlgCode(hwnd
, wParam
, lParam
);
598 case WM_KEYDOWN
: return CBKeyDown(hwnd
, wParam
, lParam
);
599 case WM_CHAR
: return CBChar(hwnd
, wParam
, lParam
);
600 case WM_SETFONT
: return CBSetFont(hwnd
, wParam
, lParam
);
601 case WM_SETREDRAW
: return CBSetRedraw(hwnd
, wParam
, lParam
);
602 case WM_PAINT
: return CBPaint(hwnd
, wParam
, lParam
);
603 case WM_LBUTTONDOWN
: return CBLButtonDown(hwnd
, wParam
, lParam
);
604 case WM_SETFOCUS
: return CBSetFocus(hwnd
, wParam
, lParam
);
605 case WM_KILLFOCUS
: return CBKillFocus(hwnd
, wParam
, lParam
);
606 case CB_RESETCONTENT
: return CBResetContent(hwnd
, wParam
, lParam
);
607 case CB_DIR
: return CBDir(hwnd
, wParam
, lParam
);
608 case CB_ADDSTRING
: return CBAddString(hwnd
, wParam
, lParam
);
609 case CB_INSERTSTRING
: return CBInsertString(hwnd
, wParam
, lParam
);
610 case CB_DELETESTRING
: return CBDeleteString(hwnd
, wParam
, lParam
);
611 case CB_FINDSTRING
: return CBFindString(hwnd
, wParam
, lParam
);
612 case CB_GETCOUNT
: return CBGetCount(hwnd
, wParam
, lParam
);
613 case CB_GETCURSEL
: return CBGetCurSel(hwnd
, wParam
, lParam
);
614 case CB_GETITEMDATA
: return CBGetItemData(hwnd
, wParam
, lParam
);
615 case CB_GETITEMHEIGHT
: return CBGetItemHeight(hwnd
, wParam
, lParam
);
616 case CB_GETLBTEXT
: return CBGetLBText(hwnd
, wParam
, lParam
);
617 case CB_GETLBTEXTLEN
: return CBGetLBTextLen(hwnd
, wParam
, lParam
);
618 case CB_SELECTSTRING
: return CBSelectString(hwnd
, wParam
, lParam
);
619 case CB_SETITEMDATA
: return CBSetItemData(hwnd
, wParam
, lParam
);
620 case CB_SETCURSEL
: return CBSetCurSel(hwnd
, wParam
, lParam
);
621 case CB_SETITEMHEIGHT
: return CBSetItemHeight(hwnd
, wParam
, lParam
);
622 case CB_SHOWDROPDOWN
: return CBShowDropDown(hwnd
, wParam
, lParam
);
624 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
627 /*--------------------------------------------------------------------*/
628 /* ComboLBox code starts here */
630 HWND
CLBoxGetCombo(HWND hwnd
)
632 return GetWindowWord(hwnd
,0);
635 LPHEADLIST
CLBoxGetListHeader(HWND hwnd
)
637 return ComboGetListHeader(CLBoxGetCombo(hwnd
));
640 /***********************************************************************
643 static LONG
CBLCreate( HWND hwnd
, WORD wParam
, LONG lParam
)
645 CREATESTRUCT
*createStruct
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
646 SetWindowWord(hwnd
,0,LOWORD(createStruct
->lpCreateParams
));
650 /***********************************************************************
653 static LONG
CBLGetDlgCode( HWND hwnd
, WORD wParam
, LONG lParam
)
655 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
658 /***********************************************************************
661 static LONG
CBLKeyDown( HWND hwnd
, WORD wParam
, LONG lParam
)
663 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
664 WORD newFocused
= lphl
->ItemFocused
;
671 newFocused
= lphl
->ItemsCount
- 1;
674 if (newFocused
> 0) newFocused
--;
680 if (newFocused
> lphl
->ItemsVisible
) {
681 newFocused
-= lphl
->ItemsVisible
;
687 newFocused
+= lphl
->ItemsVisible
;
693 if (newFocused
>= lphl
->ItemsCount
)
694 newFocused
= lphl
->ItemsCount
- 1;
696 ListBoxSetCurSel(lphl
, newFocused
);
697 ListBoxSendNotification(lphl
, hwnd
, CBN_SELCHANGE
);
699 lphl
->ItemFocused
= newFocused
;
700 ListBoxScrollToFocus(lphl
);
701 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
702 InvalidateRect(hwnd
, NULL
, TRUE
);
706 /***********************************************************************
709 static LONG
CBLChar( HWND hwnd
, WORD wParam
, LONG lParam
)
714 /***********************************************************************
717 static LONG
CBLPaint( HWND hwnd
, WORD wParam
, LONG lParam
)
719 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
724 HWND combohwnd
= CLBoxGetCombo(hwnd
);
730 hdc
= BeginPaint( hwnd
, &ps
);
732 if (!IsWindowVisible(hwnd
) || !lphl
->bRedrawFlag
) {
737 hOldFont
= SelectObject(hdc
, lphl
->hFont
);
738 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLOR
, hdc
,
739 MAKELONG(hwnd
, CTLCOLOR_LISTBOX
));
741 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
743 GetClientRect(hwnd
, &rect
);
744 FillRect(hdc
, &rect
, hBrush
);
746 lpls
= lphl
->lpFirst
;
748 lphl
->ItemsVisible
= 0;
749 for(i
= 0; i
< lphl
->ItemsCount
; i
++) {
750 if (lpls
== NULL
) break;
752 if (i
>= lphl
->FirstVisible
) {
753 height
= lpls
->mis
.itemHeight
;
755 if (top
> rect
.bottom
) break;
756 lpls
->itemRect
.top
= top
;
757 lpls
->itemRect
.bottom
= top
+ height
;
758 lpls
->itemRect
.left
= rect
.left
;
759 lpls
->itemRect
.right
= rect
.right
;
761 dprintf_listbox(stddeb
,"drawing item: %d %d %d %d %d\n",rect
.left
,top
,rect
.right
,top
+height
,lpls
->itemState
);
762 if (lphl
->OwnerDrawn
) {
763 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
, 0);
765 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_SELECT
, ODS_SELECTED
);
767 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
,
770 if ((lphl
->ItemFocused
== i
) && GetFocus() == hwnd
)
771 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_FOCUS
, ODS_FOCUS
);
774 lphl
->ItemsVisible
++;
779 SelectObject(hdc
,hOldFont
);
780 EndPaint( hwnd
, &ps
);
785 /***********************************************************************
788 static LONG
CBLKillFocus( HWND hwnd
, WORD wParam
, LONG lParam
)
790 /* SendMessage(CLBoxGetCombo(hwnd),CB_SHOWDROPDOWN,0,0);*/
794 /***********************************************************************
797 static LONG
CBLActivate( HWND hwnd
, WORD wParam
, LONG lParam
)
799 if (wParam
== WA_INACTIVE
)
800 SendMessage(CLBoxGetCombo(hwnd
),CB_SHOWDROPDOWN
,0,0);
804 /***********************************************************************
807 static LONG
CBLLButtonDown( HWND hwnd
, WORD wParam
, LONG lParam
)
809 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
816 lphl
->PrevFocused
= lphl
->ItemFocused
;
818 y
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
822 ListBoxSetCurSel(lphl
, y
);
823 ListBoxGetItemRect(lphl
, y
, &rectsel
);
825 InvalidateRect(hwnd
, NULL
, TRUE
);
829 /***********************************************************************
832 static LONG
CBLLButtonUp( HWND hwnd
, WORD wParam
, LONG lParam
)
834 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
836 if (GetCapture() == hwnd
) ReleaseCapture();
838 if (lphl
->PrevFocused
!= lphl
->ItemFocused
) {
839 SendMessage(CLBoxGetCombo(hwnd
),CB_SETCURSEL
,lphl
->ItemFocused
,0);
840 ListBoxSendNotification(lphl
, CLBoxGetCombo(hwnd
), CBN_SELCHANGE
);
842 SendMessage(CLBoxGetCombo(hwnd
),CB_SHOWDROPDOWN
,0,0);
847 /***********************************************************************
850 static LONG
CBLMouseMove( HWND hwnd
, WORD wParam
, LONG lParam
)
852 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
855 RECT rect
, rectsel
; /* XXX Broken */
857 if ((wParam
& MK_LBUTTON
) != 0) {
860 if (lphl
->FirstVisible
> 0) {
861 lphl
->FirstVisible
--;
862 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
863 InvalidateRect(hwnd
, NULL
, TRUE
);
867 GetClientRect(hwnd
, &rect
);
868 if (y
>= rect
.bottom
) {
869 if (lphl
->FirstVisible
< ListMaxFirstVisible(lphl
)) {
870 lphl
->FirstVisible
++;
871 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
872 InvalidateRect(hwnd
, NULL
, TRUE
);
876 if ((y
> 0) && (y
< (rect
.bottom
- 4))) {
877 if ((y
< rectsel
.top
) || (y
> rectsel
.bottom
)) {
878 wRet
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
879 if (wRet
== lphl
->ItemFocused
) return 0;
880 ListBoxSetCurSel(lphl
, wRet
);
881 ListBoxGetItemRect(lphl
, wRet
, &rectsel
);
882 InvalidateRect(hwnd
, NULL
, TRUE
);
890 /***********************************************************************
893 static LONG
CBLVScroll( HWND hwnd
, WORD wParam
, LONG lParam
)
895 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
898 y
= lphl
->FirstVisible
;
902 if (lphl
->FirstVisible
> 0)
903 lphl
->FirstVisible
--;
907 lphl
->FirstVisible
++;
911 if (lphl
->FirstVisible
> lphl
->ItemsVisible
) {
912 lphl
->FirstVisible
-= lphl
->ItemsVisible
;
914 lphl
->FirstVisible
= 0;
919 lphl
->FirstVisible
+= lphl
->ItemsVisible
;
923 lphl
->FirstVisible
= LOWORD(lParam
);
927 if (lphl
->FirstVisible
> ListMaxFirstVisible(lphl
))
928 lphl
->FirstVisible
= ListMaxFirstVisible(lphl
);
930 if (y
!= lphl
->FirstVisible
) {
931 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
932 InvalidateRect(hwnd
, NULL
, TRUE
);
938 /***********************************************************************
941 LONG
ComboLBoxWndProc(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
944 case WM_CREATE
: return CBLCreate(hwnd
, wParam
, lParam
);
945 case WM_GETDLGCODE
: return CBLGetDlgCode(hwnd
, wParam
, lParam
);
946 case WM_KEYDOWN
: return CBLKeyDown(hwnd
, wParam
, lParam
);
947 case WM_CHAR
: return CBLChar(hwnd
, wParam
, lParam
);
948 case WM_PAINT
: return CBLPaint(hwnd
, wParam
, lParam
);
949 case WM_KILLFOCUS
: return CBLKillFocus(hwnd
, wParam
, lParam
);
950 case WM_ACTIVATE
: return CBLActivate(hwnd
, wParam
, lParam
);
951 case WM_LBUTTONDOWN
: return CBLLButtonDown(hwnd
, wParam
, lParam
);
952 case WM_LBUTTONUP
: return CBLLButtonUp(hwnd
, wParam
, lParam
);
953 case WM_MOUSEMOVE
: return CBLMouseMove(hwnd
, wParam
, lParam
);
954 case WM_VSCROLL
: return CBLVScroll(hwnd
, wParam
, lParam
);
956 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
959 /************************************************************************
960 * DlgDirSelectComboBox [USER.194]
962 BOOL
DlgDirSelectComboBox(HWND hDlg
, LPSTR lpStr
, int nIDLBox
)
964 fprintf(stdnimp
,"DlgDirSelectComboBox(%04X, '%s', %d) \n",
965 hDlg
, lpStr
, nIDLBox
);
970 /************************************************************************
971 * DlgDirListComboBox [USER.195]
973 int DlgDirListComboBox(HWND hDlg
, SEGPTR PathSpec
,
974 int nIDLBox
, int nIDStat
, WORD wType
)
978 LPSTR lpPathSpec
= PTR_SEG_TO_LIN(PathSpec
);
980 dprintf_combo(stddeb
,"DlgDirListComboBox(%04X, '%s', %d, %d, %04X) \n",
981 hDlg
, lpPathSpec
, nIDLBox
, nIDStat
, wType
);
985 hWnd
= GetDlgItem(hDlg
, nIDLBox
);
986 lphl
= ComboGetListHeader(hWnd
);
987 lphc
= ComboGetStorageHeader(hWnd
);
988 ListBoxResetContent(lphl
);
989 ret
= ListBoxDirectory(lphl
, wType
, lpPathSpec
);
990 ComboUpdateWindow(hWnd
, lphl
, lphc
, TRUE
);
998 drive
= DOS_GetDefaultDrive();
999 hTemp
= USER_HEAP_ALLOC( 256 );
1000 temp
= (char *) USER_HEAP_LIN_ADDR( hTemp
);
1001 strcpy( temp
+3, DOS_GetCurrentDir(drive
) );
1002 if( temp
[3] == '\\' ) {
1003 temp
[1] = 'A'+drive
;
1005 SendDlgItemMessage( hDlg
, nIDStat
, WM_SETTEXT
, 0,
1006 USER_HEAP_SEG_ADDR(hTemp
) + 1 );
1008 temp
[0] = 'A'+drive
;
1011 SendDlgItemMessage( hDlg
, nIDStat
, WM_SETTEXT
, 0,
1012 USER_HEAP_SEG_ADDR(hTemp
) );
1014 USER_HEAP_FREE( hTemp
);