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 LONG
CBNCCreate( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
33 static LONG
CBCreate( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
34 static LONG
CBGetDlgCode( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
35 static LONG
CBDestroy( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
36 static LONG
CBPaint( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
37 static LONG
CBKeyDown( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
38 static LONG
CBChar( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
39 static LONG
CBSetFont( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
40 static LONG
CBSetRedraw( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
41 static LONG
CBLButtonDown( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
42 static LONG
CBSetFocus( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
43 static LONG
CBKillFocus( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
44 static LONG
CBResetContent( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
45 static LONG
CBDir( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
46 static LONG
CBAddString( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
47 static LONG
CBGetLBText( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
48 static LONG
CBInsertString( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
49 static LONG
CBDeleteString( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
50 static LONG
CBFindString( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
51 static LONG
CBGetCount( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
52 static LONG
CBGetCurSel( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
53 static LONG
CBGetItemData( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
54 static LONG
CBGetItemHeight( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
55 static LONG
CBGetLBTextLen( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
56 static LONG
CBSelectString( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
57 static LONG
CBSetItemData( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
58 static LONG
CBSetCurSel( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
59 static LONG
CBSetItemHeight( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
60 static LONG
CBShowDropDown( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
62 static LONG
CBLCreate( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
63 static LONG
CBLGetDlgCode( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
64 static LONG
CBLKeyDown( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
65 static LONG
CBLChar( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
66 static LONG
CBLPaint( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
67 static LONG
CBLKillFocus( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
68 static LONG
CBLActivate( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
69 static LONG
CBLLButtonDown( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
70 static LONG
CBLLButtonUp( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
71 static LONG
CBLMouseMove( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
72 static LONG
CBLVScroll( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
);
76 LONG (*handler
)(HWND
, WORD
, WPARAM
, LPARAM
);
79 static msg_tbl combo_tbl
[] = {
80 {WM_NCCREATE
, CBNCCreate
},
81 {WM_CREATE
, CBCreate
},
82 {WM_DESTROY
, CBDestroy
},
83 {WM_GETDLGCODE
, CBGetDlgCode
},
84 {WM_KEYDOWN
, CBKeyDown
},
86 {WM_SETFONT
, CBSetFont
},
87 {WM_SETREDRAW
, CBSetRedraw
},
89 {WM_LBUTTONDOWN
, CBLButtonDown
},
90 {WM_SETFOCUS
, CBSetFocus
},
91 {WM_KILLFOCUS
, CBKillFocus
},
92 {CB_RESETCONTENT
, CBResetContent
},
94 {CB_ADDSTRING
, CBAddString
},
95 {CB_INSERTSTRING
, CBInsertString
},
96 {CB_DELETESTRING
, CBDeleteString
},
97 {CB_FINDSTRING
, CBFindString
},
98 {CB_GETCOUNT
, CBGetCount
},
99 {CB_GETCURSEL
, CBGetCurSel
},
100 {CB_GETITEMDATA
, CBGetItemData
},
101 {CB_GETITEMHEIGHT
, CBGetItemHeight
},
102 {CB_GETLBTEXT
, CBGetLBText
},
103 {CB_GETLBTEXTLEN
, CBGetLBTextLen
},
104 {CB_SELECTSTRING
, CBSelectString
},
105 {CB_SETITEMDATA
, CBSetItemData
},
106 {CB_SETCURSEL
, CBSetCurSel
},
107 {CB_SETITEMHEIGHT
, CBSetItemHeight
},
108 {CB_SHOWDROPDOWN
, CBShowDropDown
}
112 static msg_tbl clbox_tbl
[] = {
113 {WM_CREATE
, CBLCreate
},
114 {WM_GETDLGCODE
, CBLGetDlgCode
},
115 {WM_KEYDOWN
, CBLKeyDown
},
117 {WM_PAINT
, CBLPaint
},
118 {WM_KILLFOCUS
, CBLKillFocus
},
119 {WM_ACTIVATE
, CBLActivate
},
120 {WM_LBUTTONDOWN
, CBLLButtonDown
},
121 {WM_LBUTTONUP
, CBLLButtonUp
},
122 {WM_MOUSEMOVE
, CBLMouseMove
},
123 {WM_VSCROLL
, CBLVScroll
}
126 static HBITMAP hComboBit
= 0;
127 static WORD CBitHeight
, CBitWidth
;
129 static int COMBO_Init()
133 dprintf_combo(stddeb
, "COMBO_Init\n");
134 hComboBit
= LoadBitmap(0, MAKEINTRESOURCE(OBM_COMBO
));
135 GetObject(hComboBit
, sizeof(BITMAP
), (LPSTR
)&bm
);
136 CBitHeight
= bm
.bmHeight
;
137 CBitWidth
= bm
.bmWidth
;
141 LPHEADCOMBO
ComboGetStorageHeader(HWND hwnd
)
143 return (LPHEADCOMBO
)GetWindowLong(hwnd
,4);
146 LPHEADLIST
ComboGetListHeader(HWND hwnd
)
148 return (LPHEADLIST
)GetWindowLong(hwnd
,0);
151 int CreateComboStruct(HWND hwnd
, LONG style
)
155 lphc
= (LPHEADCOMBO
)malloc(sizeof(HEADCOMBO
));
156 SetWindowLong(hwnd
,4,(LONG
)lphc
);
161 lphc
->dwStyle
= style
;
162 lphc
->DropDownVisible
= FALSE
;
166 void ComboUpdateWindow(HWND hwnd
, LPHEADLIST lphl
, LPHEADCOMBO lphc
, BOOL repaint
)
168 SetScrollRange(lphc
->hWndLBox
, SB_VERT
, 0, ListMaxFirstVisible(lphl
), TRUE
);
169 if (repaint
&& lphl
->bRedrawFlag
) {
170 InvalidateRect(hwnd
, NULL
, TRUE
);
174 /***********************************************************************
177 static LONG
CBNCCreate(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
179 CREATESTRUCT
*createStruct
;
181 if (!hComboBit
) COMBO_Init();
183 createStruct
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
184 createStruct
->style
&= ~(WS_VSCROLL
| WS_HSCROLL
);
185 SetWindowLong(hwnd
, GWL_STYLE
, createStruct
->style
);
187 dprintf_combo(stddeb
,"ComboBox WM_NCCREATE!\n");
188 return DefWindowProc(hwnd
, message
, wParam
, lParam
);
192 /***********************************************************************
195 static LONG
CBCreate(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
200 LONG cstyle
= GetWindowLong(hwnd
,GWL_STYLE
);
203 /* translate combo into listbox styles */
204 if (cstyle
& CBS_OWNERDRAWFIXED
) style
|= LBS_OWNERDRAWFIXED
;
205 if (cstyle
& CBS_OWNERDRAWVARIABLE
) style
|= LBS_OWNERDRAWVARIABLE
;
206 if (cstyle
& CBS_SORT
) style
|= LBS_SORT
;
207 if (cstyle
& CBS_HASSTRINGS
) style
|= LBS_HASSTRINGS
;
209 CreateListBoxStruct(hwnd
, ODT_COMBOBOX
, style
, GetParent(hwnd
));
210 CreateComboStruct(hwnd
,cstyle
);
211 lphl
= ComboGetListHeader(hwnd
);
212 lphc
= ComboGetStorageHeader(hwnd
);
214 GetClientRect(hwnd
,&rect
);
215 GetWindowRect(hwnd
,&lboxrect
);
216 /* FIXME: combos with edit controls are broken. */
218 case CBS_SIMPLE
: /* edit control, list always visible */
219 dprintf_combo(stddeb
,"CBS_SIMPLE\n");
220 SetRectEmpty(&lphc
->RectButton
);
221 lphc
->LBoxTop
= lphl
->StdItemHeight
;
222 lphc
->hWndEdit
= CreateWindow("EDIT", "",
223 WS_CHILD
| WS_CLIPCHILDREN
| WS_VISIBLE
| SS_LEFT
,
224 0, 0, rect
.right
, lphl
->StdItemHeight
,
225 hwnd
, 1, GetWindowWord(hwnd
,GWW_HINSTANCE
), 0L);
227 case CBS_DROPDOWN
: /* edit control, dropdown listbox */
228 dprintf_combo(stddeb
,"CBS_DROPDOWN\n");
229 lphc
->RectButton
= rect
;
230 lphc
->RectButton
.left
= lphc
->RectButton
.right
- 6 - CBitWidth
;
231 lphc
->RectButton
.bottom
= lphc
->RectButton
.top
+ lphl
->StdItemHeight
;
232 lphc
->LBoxTop
= lphl
->StdItemHeight
;
233 SetWindowPos(hwnd
, 0, 0, 0, rect
.right
- rect
.left
+ 2*SYSMETRICS_CXBORDER
,
234 lphl
->StdItemHeight
+ 2*SYSMETRICS_CYBORDER
,
235 SWP_NOMOVE
| SWP_NOZORDER
);
236 lphc
->hWndEdit
= CreateWindow("EDIT", "",
237 WS_CHILD
| WS_CLIPCHILDREN
| WS_VISIBLE
| SS_LEFT
,
238 0, 0, lphc
->RectButton
.left
, lphl
->StdItemHeight
,
239 hwnd
, 1, GetWindowWord(hwnd
,GWW_HINSTANCE
), 0L);
241 case CBS_DROPDOWNLIST
: /* static control, downdown listbox */
242 dprintf_combo(stddeb
,"CBS_DROPDOWNLIST\n");
243 lphc
->RectButton
= rect
;
244 lphc
->RectButton
.left
= lphc
->RectButton
.right
- 6 - CBitWidth
;
245 lphc
->RectButton
.bottom
= lphc
->RectButton
.top
+ lphl
->StdItemHeight
;
246 lphc
->LBoxTop
= lphl
->StdItemHeight
;
247 SetWindowPos(hwnd
, 0, 0, 0, rect
.right
- rect
.left
+ 2*SYSMETRICS_CXBORDER
,
248 lphl
->StdItemHeight
+ 2*SYSMETRICS_CYBORDER
,
249 SWP_NOMOVE
| SWP_NOZORDER
);
252 lboxrect
.top
+= lphc
->LBoxTop
;
253 /* FIXME: WinSight says these should be CHILD windows with the TOPMOST flag
254 * set. Wine doesn't support TOPMOST, and simply setting the WS_CHILD
255 * flag doesn't work. */
256 lphc
->hWndLBox
= CreateWindow("COMBOLBOX", "",
257 WS_POPUP
| WS_BORDER
| WS_VSCROLL
,
258 lboxrect
.left
, lboxrect
.top
,
259 lboxrect
.right
- lboxrect
.left
,
260 lboxrect
.bottom
- lboxrect
.top
,
261 0, 0, GetWindowWord(hwnd
,GWW_HINSTANCE
),
262 (SEGPTR
)MAKELONG(hwnd
, hwnd
));
263 ShowWindow(lphc
->hWndLBox
, SW_HIDE
);
264 dprintf_combo(stddeb
,"Combo Creation LBox=%X!\n", lphc
->hWndLBox
);
268 /***********************************************************************
271 static LONG
CBDestroy(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
273 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
275 ListBoxResetContent(lphl
);
276 DestroyListBoxStruct(lphl
);
277 dprintf_combo(stddeb
,"Combo WM_DESTROY %p !\n", lphl
);
281 /***********************************************************************
284 static LONG
CBPaint(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
286 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
287 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
296 hdc
= BeginPaint(hwnd
, &ps
);
298 if (hComboBit
!= 0) {
299 GRAPH_DrawReliefRect(hdc
, &lphc
->RectButton
, 2, 2, FALSE
);
300 GRAPH_DrawBitmap(hdc
, hComboBit
,
301 lphc
->RectButton
.left
+ 3,lphc
->RectButton
.top
+ 2,
302 0, 0, CBitWidth
, CBitHeight
);
304 if (!IsWindowVisible(hwnd
) || !lphl
->bRedrawFlag
305 || (lphc
->dwStyle
& 3) != CBS_DROPDOWNLIST
)
307 /* we don't want to draw an entry when there is an edit control */
312 hOldFont
= SelectObject(hdc
, lphl
->hFont
);
314 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLOR
, hdc
,
315 MAKELONG(hwnd
, CTLCOLOR_LISTBOX
));
316 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
318 GetClientRect(hwnd
, &rect
);
319 rect
.right
-= (lphc
->RectButton
.right
- lphc
->RectButton
.left
);
320 FillRect(hdc
, &rect
, hBrush
);
322 lpls
= ListBoxGetItem(lphl
,lphl
->ItemFocused
);
324 height
= lpls
->mis
.itemHeight
;
325 rect
.bottom
= rect
.top
+ height
;
327 if (OWNER_DRAWN(lphl
)) {
328 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &rect
, ODA_DRAWENTIRE
, 0);
330 ListBoxDrawItem (hwnd
, lphl
, hdc
, lpls
, &rect
, ODA_DRAWENTIRE
, 0);
332 if (GetFocus() == hwnd
)
333 ListBoxDrawItem (hwnd
,lphl
, hdc
, lpls
, &rect
, ODA_FOCUS
, ODS_FOCUS
);
335 SelectObject(hdc
,hOldFont
);
340 /***********************************************************************
343 static LONG
CBGetDlgCode(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
345 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
348 /***********************************************************************
351 static LONG
CBLButtonDown(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
353 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
354 SendMessage(hwnd
,CB_SHOWDROPDOWN
,!lphc
->DropDownVisible
,0);
358 /***********************************************************************
361 static LONG
CBKeyDown(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
363 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
364 WORD newFocused
= lphl
->ItemFocused
;
371 newFocused
= lphl
->ItemsCount
- 1;
374 if (newFocused
> 0) newFocused
--;
383 if (newFocused
>= lphl
->ItemsCount
)
384 newFocused
= lphl
->ItemsCount
- 1;
386 ListBoxSetCurSel(lphl
, newFocused
);
387 ListBoxSendNotification(lphl
, hwnd
, CBN_SELCHANGE
);
389 lphl
->ItemFocused
= newFocused
;
390 ListBoxScrollToFocus(lphl
);
391 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
392 InvalidateRect(hwnd
, NULL
, TRUE
);
397 /***********************************************************************
400 static LONG
CBChar(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
402 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
405 newFocused
= ListBoxFindNextMatch(lphl
, wParam
);
406 if (newFocused
== (WORD
)LB_ERR
) return 0;
408 if (newFocused
>= lphl
->ItemsCount
)
409 newFocused
= lphl
->ItemsCount
- 1;
411 ListBoxSetCurSel(lphl
, newFocused
);
412 ListBoxSendNotification(lphl
, hwnd
, CBN_SELCHANGE
);
413 lphl
->ItemFocused
= newFocused
;
414 ListBoxScrollToFocus(lphl
);
416 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
417 InvalidateRect(hwnd
, NULL
, TRUE
);
422 /***********************************************************************
425 static LONG
CBKillFocus(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
430 /***********************************************************************
433 static LONG
CBSetFocus(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
438 /***********************************************************************
441 static LONG
CBResetContent(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
443 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
444 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
446 ListBoxResetContent(lphl
);
447 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
451 /***********************************************************************
454 static LONG
CBDir(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
457 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
458 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
460 wRet
= ListBoxDirectory(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
461 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
465 /***********************************************************************
468 static LONG
CBInsertString(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
471 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
472 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
474 if (HasStrings(lphl
))
475 wRet
= ListBoxInsertString(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
477 wRet
= ListBoxInsertString(lphl
, wParam
, (LPSTR
)lParam
);
479 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
483 /***********************************************************************
486 static LONG
CBAddString(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
489 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
490 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
492 if (HasStrings(lphl
))
493 wRet
= ListBoxAddString(lphl
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
495 wRet
= ListBoxAddString(lphl
, (LPSTR
)lParam
);
497 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
501 /***********************************************************************
504 static LONG
CBDeleteString(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
506 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
507 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
508 LONG lRet
= ListBoxDeleteString(lphl
,wParam
);
510 ComboUpdateWindow(hwnd
, lphl
, lphc
, TRUE
);
514 /***********************************************************************
517 static LONG
CBSelectString(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
519 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
522 wRet
= ListBoxFindString(lphl
, wParam
, lParam
);
524 /* XXX add functionality here */
529 /***********************************************************************
532 static LONG
CBFindString(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
534 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
535 return ListBoxFindString(lphl
, wParam
, lParam
);
538 /***********************************************************************
541 static LONG
CBGetCount(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
543 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
544 return lphl
->ItemsCount
;
547 /***********************************************************************
550 static LONG
CBSetCurSel(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
552 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
555 wRet
= ListBoxSetCurSel(lphl
, wParam
);
557 /* SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);*/
558 InvalidateRect(hwnd
, NULL
, TRUE
);
563 /***********************************************************************
566 static LONG
CBGetCurSel(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
568 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
569 return lphl
->ItemFocused
;
572 /***********************************************************************
575 static LONG
CBGetItemHeight(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
577 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
578 LPLISTSTRUCT lpls
= ListBoxGetItem (lphl
, wParam
);
580 if (lpls
== NULL
) return LB_ERR
;
581 return lpls
->mis
.itemHeight
;
584 /***********************************************************************
587 static LONG
CBSetItemHeight(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
589 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
590 return ListBoxSetItemHeight(lphl
, wParam
, lParam
);
593 /***********************************************************************
596 static LONG
CBSetRedraw(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
598 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
599 lphl
->bRedrawFlag
= wParam
;
603 /***********************************************************************
606 static LONG
CBSetFont(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
608 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
611 lphl
->hFont
= GetStockObject(SYSTEM_FONT
);
613 lphl
->hFont
= wParam
;
618 /***********************************************************************
621 static LONG
CBGetLBTextLen(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
623 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
624 LPLISTSTRUCT lpls
= ListBoxGetItem(lphl
,wParam
);
626 if (lpls
== NULL
|| !HasStrings(lphl
)) return LB_ERR
;
627 return strlen(lpls
->itemText
);
630 /***********************************************************************
633 static LONG
CBGetLBText(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
635 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
636 return ListBoxGetText(lphl
, wParam
, (LPSTR
)PTR_SEG_TO_LIN(lParam
));
639 /***********************************************************************
642 static LONG
CBGetItemData(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
644 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
645 return ListBoxGetItemData(lphl
, wParam
);
648 /***********************************************************************
651 static LONG
CBSetItemData(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
653 LPHEADLIST lphl
= ComboGetListHeader(hwnd
);
654 return ListBoxSetItemData(lphl
, wParam
, lParam
);
657 /***********************************************************************
660 static LONG
CBShowDropDown(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
662 LPHEADCOMBO lphc
= ComboGetStorageHeader(hwnd
);
665 if (lphc
->dwStyle
& 3 == CBS_SIMPLE
) return LB_ERR
;
668 if (wParam
!= lphc
->DropDownVisible
) {
669 lphc
->DropDownVisible
= wParam
;
670 GetWindowRect(hwnd
,&rect
);
671 SetWindowPos(lphc
->hWndLBox
, 0, rect
.left
, rect
.top
+lphc
->LBoxTop
, 0, 0,
672 SWP_NOSIZE
| (wParam
? SWP_SHOWWINDOW
: SWP_HIDEWINDOW
));
673 if (!wParam
) SetFocus(hwnd
);
679 /***********************************************************************
682 LONG
ComboBoxWndProc(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
685 int table_size
= sizeof (combo_tbl
) / sizeof (msg_tbl
);
687 while (idx
< table_size
) {
688 if (message
== combo_tbl
[idx
].message
) {
689 return (*(combo_tbl
[idx
].handler
))(hwnd
, message
, wParam
, lParam
);
693 return DefWindowProc (hwnd
, message
, wParam
, lParam
);
696 /*--------------------------------------------------------------------*/
697 /* ComboLBox code starts here */
699 HWND
CLBoxGetCombo(HWND hwnd
)
701 return GetWindowWord(hwnd
,0);
704 LPHEADLIST
CLBoxGetListHeader(HWND hwnd
)
706 return ComboGetListHeader(CLBoxGetCombo(hwnd
));
709 /***********************************************************************
712 static LONG
CBLCreate( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
714 CREATESTRUCT
*createStruct
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
715 SetWindowWord(hwnd
,0,LOWORD(createStruct
->lpCreateParams
));
719 /***********************************************************************
722 static LONG
CBLGetDlgCode( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
724 return DLGC_WANTARROWS
| DLGC_WANTCHARS
;
727 /***********************************************************************
730 static LONG
CBLKeyDown( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
732 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
733 WORD newFocused
= lphl
->ItemFocused
;
740 newFocused
= lphl
->ItemsCount
- 1;
743 if (newFocused
> 0) newFocused
--;
749 if (newFocused
> lphl
->ItemsVisible
) {
750 newFocused
-= lphl
->ItemsVisible
;
756 newFocused
+= lphl
->ItemsVisible
;
762 if (newFocused
>= lphl
->ItemsCount
)
763 newFocused
= lphl
->ItemsCount
- 1;
765 ListBoxSetCurSel(lphl
, newFocused
);
766 ListBoxSendNotification(lphl
, hwnd
, CBN_SELCHANGE
);
768 lphl
->ItemFocused
= newFocused
;
769 ListBoxScrollToFocus(lphl
);
770 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
771 InvalidateRect(hwnd
, NULL
, TRUE
);
775 /***********************************************************************
778 static LONG
CBLChar( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
783 /***********************************************************************
786 static LONG
CBLPaint( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
788 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
793 HWND combohwnd
= CLBoxGetCombo(hwnd
);
799 hdc
= BeginPaint( hwnd
, &ps
);
801 if (!IsWindowVisible(hwnd
) || !lphl
->bRedrawFlag
) {
806 hOldFont
= SelectObject(hdc
, lphl
->hFont
);
807 hBrush
= SendMessage(lphl
->hParent
, WM_CTLCOLOR
, hdc
,
808 MAKELONG(hwnd
, CTLCOLOR_LISTBOX
));
810 if (hBrush
== 0) hBrush
= GetStockObject(WHITE_BRUSH
);
812 GetClientRect(hwnd
, &rect
);
813 FillRect(hdc
, &rect
, hBrush
);
815 lpls
= lphl
->lpFirst
;
817 lphl
->ItemsVisible
= 0;
818 for(i
= 0; i
< lphl
->ItemsCount
; i
++) {
819 if (lpls
== NULL
) break;
821 if (i
>= lphl
->FirstVisible
) {
822 height
= lpls
->mis
.itemHeight
;
824 if (top
> rect
.bottom
) break;
825 lpls
->itemRect
.top
= top
;
826 lpls
->itemRect
.bottom
= top
+ height
;
827 lpls
->itemRect
.left
= rect
.left
;
828 lpls
->itemRect
.right
= rect
.right
;
830 dprintf_listbox(stddeb
,"drawing item: %d %d %d %d %d\n",rect
.left
,top
,rect
.right
,top
+height
,lpls
->itemState
);
831 if (OWNER_DRAWN(lphl
)) {
832 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
, 0);
834 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_SELECT
, ODS_SELECTED
);
836 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_DRAWENTIRE
,
839 if ((lphl
->ItemFocused
== i
) && GetFocus() == hwnd
)
840 ListBoxDrawItem (combohwnd
, lphl
, hdc
, lpls
, &lpls
->itemRect
, ODA_FOCUS
, ODS_FOCUS
);
843 lphl
->ItemsVisible
++;
848 SelectObject(hdc
,hOldFont
);
849 EndPaint( hwnd
, &ps
);
854 /***********************************************************************
857 static LONG
CBLKillFocus( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
859 /* SendMessage(CLBoxGetCombo(hwnd),CB_SHOWDROPDOWN,0,0);*/
863 /***********************************************************************
866 static LONG
CBLActivate( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
868 if (wParam
== WA_INACTIVE
)
869 SendMessage(CLBoxGetCombo(hwnd
),CB_SHOWDROPDOWN
,0,0);
873 /***********************************************************************
876 static LONG
CBLLButtonDown( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
878 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
885 lphl
->PrevFocused
= lphl
->ItemFocused
;
887 y
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
891 ListBoxSetCurSel(lphl
, y
);
892 ListBoxGetItemRect(lphl
, y
, &rectsel
);
894 InvalidateRect(hwnd
, NULL
, TRUE
);
898 /***********************************************************************
901 static LONG
CBLLButtonUp( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
903 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
905 if (GetCapture() == hwnd
) ReleaseCapture();
907 if (lphl
->PrevFocused
!= lphl
->ItemFocused
) {
908 SendMessage(CLBoxGetCombo(hwnd
),CB_SETCURSEL
,lphl
->ItemFocused
,0);
909 ListBoxSendNotification(lphl
, CLBoxGetCombo(hwnd
), CBN_SELCHANGE
);
911 SendMessage(CLBoxGetCombo(hwnd
),CB_SHOWDROPDOWN
,0,0);
916 /***********************************************************************
919 static LONG
CBLMouseMove( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
921 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
924 RECT rect
, rectsel
; /* XXX Broken */
926 if ((wParam
& MK_LBUTTON
) != 0) {
929 if (lphl
->FirstVisible
> 0) {
930 lphl
->FirstVisible
--;
931 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
932 InvalidateRect(hwnd
, NULL
, TRUE
);
936 GetClientRect(hwnd
, &rect
);
937 if (y
>= rect
.bottom
) {
938 if (lphl
->FirstVisible
< ListMaxFirstVisible(lphl
)) {
939 lphl
->FirstVisible
++;
940 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
941 InvalidateRect(hwnd
, NULL
, TRUE
);
945 if ((y
> 0) && (y
< (rect
.bottom
- 4))) {
946 if ((y
< rectsel
.top
) || (y
> rectsel
.bottom
)) {
947 wRet
= ListBoxFindMouse(lphl
, LOWORD(lParam
), HIWORD(lParam
));
948 if (wRet
== lphl
->ItemFocused
) return 0;
949 ListBoxSetCurSel(lphl
, wRet
);
950 ListBoxGetItemRect(lphl
, wRet
, &rectsel
);
951 InvalidateRect(hwnd
, NULL
, TRUE
);
959 /***********************************************************************
962 static LONG
CBLVScroll( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
964 LPHEADLIST lphl
= CLBoxGetListHeader(hwnd
);
967 y
= lphl
->FirstVisible
;
971 if (lphl
->FirstVisible
> 0)
972 lphl
->FirstVisible
--;
976 lphl
->FirstVisible
++;
980 if (lphl
->FirstVisible
> lphl
->ItemsVisible
) {
981 lphl
->FirstVisible
-= lphl
->ItemsVisible
;
983 lphl
->FirstVisible
= 0;
988 lphl
->FirstVisible
+= lphl
->ItemsVisible
;
992 lphl
->FirstVisible
= LOWORD(lParam
);
996 if (lphl
->FirstVisible
> ListMaxFirstVisible(lphl
))
997 lphl
->FirstVisible
= ListMaxFirstVisible(lphl
);
999 if (y
!= lphl
->FirstVisible
) {
1000 SetScrollPos(hwnd
, SB_VERT
, lphl
->FirstVisible
, TRUE
);
1001 InvalidateRect(hwnd
, NULL
, TRUE
);
1007 /***********************************************************************
1010 LONG
ComboLBoxWndProc(HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
1013 int table_size
= sizeof (clbox_tbl
) / sizeof (msg_tbl
);
1015 while (idx
< table_size
) {
1016 if (message
== clbox_tbl
[idx
].message
) {
1017 return (*(clbox_tbl
[idx
].handler
))(hwnd
, message
, wParam
, lParam
);
1021 return DefWindowProc (hwnd
, message
, wParam
, lParam
);
1024 /************************************************************************
1025 * DlgDirSelectComboBox [USER.194]
1027 BOOL
DlgDirSelectComboBox(HWND hDlg
, LPSTR lpStr
, int nIDLBox
)
1029 fprintf(stdnimp
,"DlgDirSelectComboBox(%04X, '%s', %d) \n",
1030 hDlg
, lpStr
, nIDLBox
);
1035 /************************************************************************
1036 * DlgDirListComboBox [USER.195]
1038 int DlgDirListComboBox(HWND hDlg
, SEGPTR PathSpec
,
1039 int nIDLBox
, int nIDStat
, WORD wType
)
1043 LPSTR lpPathSpec
= PTR_SEG_TO_LIN(PathSpec
);
1045 dprintf_combo(stddeb
,"DlgDirListComboBox(%04X, '%s', %d, %d, %04X) \n",
1046 hDlg
, lpPathSpec
, nIDLBox
, nIDStat
, wType
);
1050 hWnd
= GetDlgItem(hDlg
, nIDLBox
);
1051 lphl
= ComboGetListHeader(hWnd
);
1052 lphc
= ComboGetStorageHeader(hWnd
);
1053 ListBoxResetContent(lphl
);
1054 ret
= ListBoxDirectory(lphl
, wType
, lpPathSpec
);
1055 ComboUpdateWindow(hWnd
, lphl
, lphc
, TRUE
);
1063 drive
= DOS_GetDefaultDrive();
1064 hTemp
= USER_HEAP_ALLOC( 256 );
1065 temp
= (char *) USER_HEAP_LIN_ADDR( hTemp
);
1066 strcpy( temp
+3, DOS_GetCurrentDir(drive
) );
1067 if( temp
[3] == '\\' ) {
1068 temp
[1] = 'A'+drive
;
1070 SendDlgItemMessage( hDlg
, nIDStat
, WM_SETTEXT
, 0,
1071 USER_HEAP_SEG_ADDR(hTemp
) + 1 );
1073 temp
[0] = 'A'+drive
;
1076 SendDlgItemMessage( hDlg
, nIDStat
, WM_SETTEXT
, 0,
1077 USER_HEAP_SEG_ADDR(hTemp
) );
1079 USER_HEAP_FREE( hTemp
);