source: trunk/src/comctl32/comboex.c@ 5655

Last change on this file since 5655 was 5630, checked in by sandervl, 24 years ago

wine resync

File size: 69.5 KB
Line 
1/*
2 * TODO <-------------
3 * 1. The following extended styles need to be implemented, use will
4 * result in a FIXME:
5 * CBES_EX_NOEDITIMAGEINDENT
6 * CBES_EX_PATHWORDBREAKPROC
7 * CBES_EX_NOSIZELIMIT
8 * CBES_EX_CASESENSITIVE
9 * 2. None of the following callback items are implemented. Therefor
10 * no CBEN_GETDISPINFO notifies are issued. Use in either CBEM_INSERTITEM
11 * or CBEM_SETITEM will result in a FIXME:
12 * LPSTR_TEXTCALLBACK
13 * I_IMAGECALLBACK
14 * I_INDENTCALLBACK
15 * 3. No use is made of the iOverlay image.
16 * 4. Notify CBEN_DRAGBEGIN is not implemented.
17 */
18
19
20/*
21 * ComboBoxEx control v2 (mod5)
22 *
23 * Copyright 1998, 1999 Eric Kohl
24 *
25 * NOTES
26 * This is just a dummy control. An author is needed! Any volunteers?
27 * I will only improve this control once in a while.
28 * Eric <ekohl@abo.rhein-zeitung.de>
29 *
30
31 * Changes Guy Albertelli <galberte@neo.lrun.com>
32 * v1 Implemented messages: CB_SETITEMHEIGHT, WM_WINDOWPOSCHANGING,
33 * WM_DRAWITEM, and WM_MEASUREITEM. Fixed WM_CREATE. Fixed height
34 * of window rect reported fixing rebar control.
35 * v2
36 * 1. Rewrite of WM_Create for own created EDIT control. Also try to
37 * generate message sequence similar to native DLL.
38 * 2. Handle case where CBEM_SETITEM is called to display data in EDIT
39 * Control.
40 * 3. Add override for WNDPROC for the EDIT control (reqed for VK_RETURN).
41 * 4. Dump input data for things using COMBOBOXEXITEM{A|W}.
42 * 5. Handle positioning EDIT control based on whether icon present.
43 * 6. Make InsertItemA use InsertItemW, and store all data in ..W form.
44 * 7. Implement CBEM_DELETEITEM, CBEM_GETITEM{A|W}, CB_SETCURSEL,
45 * CBEM_{GET|SET}UNICODEFORMAT.
46 * 8. Add override for WNDPROC for the COMBO control.
47 * 9. Support extended style CBES_EX_NOEDITIMAGE and warn others are not
48 * supported.
49 * 10. Implement CB_FINDSTRINGEXACT in both the Combo and ComboEx window
50 * procs to match the items. This eliminates dup entries in the listbox.
51 *
52 * mod 4
53 * 1. Implemented CBN_SELCHANGE, CBN_KILLFOCUS, and CBN_SELENDOK.
54 * 2. Fix putting text in CBEN_ENDEDIT notifys for CBN_DROPDOWN case.
55 * 3. Lock image selected status to focus state of edit control if
56 * edit control exists. Mimics native actions.
57 * 4. Implemented WM_SETFOCUS in EditWndProc to track status of
58 * focus for 3 above.
59 * 5. The LBN_SELCHANGE is just for documentation purposes.
60 *
61 * mod 5
62 * 1. Add support for CB_GETITEMDATA to a Comboex. Returns the LPARAM
63 * passed during insert of item.
64 * 2. Remember selected item and don't issue CB_SETCURSEL unless needed.
65 * 3. Add initial support for WM_NCCREATE to remove unwanted window styles
66 * (Currently just WS_VSCROLL and WS_HSCROLL, but probably should be
67 * more.)
68 * 4. Improve some traces.
69 * 5. Add support for CB_SETITEMDATA sets LPARAM value from item.
70 *
71 * Test vehicals were the ControlSpy modules (rebar.exe and comboboxex.exe),
72 * WinRAR, and IE 4.0.
73 *
74 */
75
76#include <string.h>
77#include "winbase.h"
78#include "commctrl.h"
79#include "debugtools.h"
80#include "wine/unicode.h"
81#ifdef __WIN32OS2__
82#include "ccbase.h"
83#define inline
84#endif
85
86DEFAULT_DEBUG_CHANNEL(comboex);
87/*
88 * The following is necessary for the test done in COMBOEX_DrawItem
89 * to determine whether to dump out the DRAWITEM structure or not.
90 */
91DECLARE_DEBUG_CHANNEL(message);
92
93/* Item structure */
94typedef struct
95{
96 VOID *next;
97 UINT mask;
98 LPWSTR pszText;
99 int cchTextMax;
100 int iImage;
101 int iSelectedImage;
102 int iOverlay;
103 int iIndent;
104 LPARAM lParam;
105} CBE_ITEMDATA;
106
107/* ComboBoxEx structure */
108typedef struct
109{
110#ifdef __WIN32OS2__
111 COMCTL32_HEADER header;
112#endif
113 HIMAGELIST himl;
114 HWND hwndSelf; /* my own hwnd */
115 HWND hwndCombo;
116 HWND hwndEdit;
117 WNDPROC prevEditWndProc; /* previous Edit WNDPROC value */
118 WNDPROC prevComboWndProc; /* previous Combo WNDPROC value */
119 DWORD dwExtStyle;
120 INT selected; /* index of selected item */
121 DWORD flags; /* WINE internal flags */
122 HFONT font;
123 INT nb_items; /* Number of items */
124 BOOL bUnicode; /* ASCII (FALSE) or Unicode (TRUE)? */
125 CBE_ITEMDATA *edit; /* item data for edit item */
126 CBE_ITEMDATA *items; /* Array of items */
127} COMBOEX_INFO;
128
129/* internal flags in the COMBOEX_INFO structure */
130#define WCBE_ACTEDIT 0x00000001 /* Edit active i.e.
131 * CBEN_BEGINEDIT issued
132 * but CBEN_ENDEDIT{A|W}
133 * not yet issued. */
134#define WCBE_EDITCHG 0x00000002 /* Edit issued EN_CHANGE */
135#define WCBE_EDITFOCUSED 0x00000004 /* Edit control has focus */
136
137
138#define ID_CB_EDIT 1001
139
140
141/*
142 * Special flag set in DRAWITEMSTRUCT itemState field. It is set by
143 * the ComboEx version of the Combo Window Proc so that when the
144 * WM_DRAWITEM message is then passed to ComboEx, we know that this
145 * particular WM_DRAWITEM message is for listbox only items. Any messasges
146 * without this flag is then for the Edit control field.
147 *
148 * We really cannot use the ODS_COMBOBOXEDIT flag because MSDN states that
149 * only version 4.0 applications will have ODS_COMBOBOXEDIT set.
150 */
151#define ODS_COMBOEXLBOX 0x4000
152
153
154
155/* Height in pixels of control over the amount of the selected font */
156#define CBE_EXTRA 3
157
158/* Indent amount per MS documentation */
159#define CBE_INDENT 10
160
161/* Offset in pixels from left side for start of image or text */
162#define CBE_STARTOFFSET 6
163
164/* Offset between image and text */
165#define CBE_SEP 4
166
167#define COMBOEX_GetInfoPtr(hwnd) ((COMBOEX_INFO *)GetWindowLongA (hwnd, 0))
168
169
170/* Things common to the entire DLL */
171static ATOM ComboExInfo;
172static LRESULT WINAPI
173COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
174static LRESULT WINAPI
175COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
176
177static void
178COMBOEX_DumpItem (CBE_ITEMDATA *item)
179{
180 if (TRACE_ON(comboex)){
181 TRACE("item %p - mask=%08x, pszText=%p, cchTM=%d, iImage=%d\n",
182 item, item->mask, item->pszText, item->cchTextMax,
183 item->iImage);
184 TRACE("item %p - iSelectedImage=%d, iOverlay=%d, iIndent=%d, lParam=%08lx\n",
185 item, item->iSelectedImage, item->iOverlay, item->iIndent, item->lParam);
186 if ((item->mask & CBEIF_TEXT) && item->pszText)
187 TRACE("item %p - pszText=%s\n",
188 item, debugstr_w((const WCHAR *)item->pszText));
189 }
190}
191
192
193static void
194COMBOEX_DumpInput (COMBOBOXEXITEMA *input, BOOL true_for_w)
195{
196 if (TRACE_ON(comboex)){
197 TRACE("input - mask=%08x, iItem=%d, pszText=%p, cchTM=%d, iImage=%d\n",
198 input->mask, input->iItem, input->pszText, input->cchTextMax,
199 input->iImage);
200 if ((input->mask & CBEIF_TEXT) && input->pszText) {
201 if (true_for_w)
202 TRACE("input - pszText=<%s>\n",
203 debugstr_w((const WCHAR *)input->pszText));
204 else
205 TRACE("input - pszText=<%s>\n",
206 debugstr_a((const char *)input->pszText));
207 }
208 TRACE("input - iSelectedImage=%d, iOverlay=%d, iIndent=%d, lParam=%08lx\n",
209 input->iSelectedImage, input->iOverlay, input->iIndent, input->lParam);
210 }
211}
212
213
214inline static LRESULT
215COMBOEX_Forward (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
216{
217 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
218
219 if (infoPtr->hwndCombo)
220 return SendMessageA (infoPtr->hwndCombo, uMsg, wParam, lParam);
221
222 return 0;
223}
224
225
226static INT
227COMBOEX_Notify (COMBOEX_INFO *infoPtr, INT code, NMHDR *hdr, BOOL doW)
228{
229
230 hdr->idFrom = GetDlgCtrlID (infoPtr->hwndSelf);
231 hdr->hwndFrom = infoPtr->hwndSelf;
232 hdr->code = code;
233 if (doW)
234 return SendMessageW (GetParent(infoPtr->hwndSelf), WM_NOTIFY, 0,
235 (LPARAM)hdr);
236 else
237 return SendMessageA (GetParent(infoPtr->hwndSelf), WM_NOTIFY, 0,
238 (LPARAM)hdr);
239}
240
241
242static void
243COMBOEX_GetComboFontSize (COMBOEX_INFO *infoPtr, SIZE *size)
244{
245 HFONT nfont, ofont;
246 HDC mydc;
247
248 mydc = GetDC (0); /* why the entire screen???? */
249 nfont = SendMessageW (infoPtr->hwndCombo, WM_GETFONT, 0, 0);
250 ofont = (HFONT) SelectObject (mydc, nfont);
251 GetTextExtentPointA (mydc, "A", 1, size);
252 SelectObject (mydc, ofont);
253 ReleaseDC (0, mydc);
254 TRACE("selected font hwnd=%08x, height=%ld\n", nfont, size->cy);
255}
256
257
258static void
259COMBOEX_CopyItem (COMBOEX_INFO *infoPtr, CBE_ITEMDATA *item, COMBOBOXEXITEMW *cit)
260{
261 if (cit->mask & CBEIF_TEXT) {
262 cit->pszText = item->pszText;
263 cit->cchTextMax = item->cchTextMax;
264 }
265 if (cit->mask & CBEIF_IMAGE)
266 cit->iImage = item->iImage;
267 if (cit->mask & CBEIF_SELECTEDIMAGE)
268 cit->iSelectedImage = item->iSelectedImage;
269 if (cit->mask & CBEIF_OVERLAY)
270 cit->iOverlay = item->iOverlay;
271 if (cit->mask & CBEIF_INDENT)
272 cit->iIndent = item->iIndent;
273 if (cit->mask & CBEIF_LPARAM)
274 cit->lParam = item->lParam;
275
276}
277
278
279static void
280COMBOEX_AdjustEditPos (COMBOEX_INFO *infoPtr)
281{
282 SIZE mysize;
283 IMAGEINFO iinfo;
284 INT x, y, w, h, xoff = 0;
285 RECT rect;
286
287 if (!infoPtr->hwndEdit) return;
288 iinfo.rcImage.left = iinfo.rcImage.right = 0;
289 if (infoPtr->himl) {
290 ImageList_GetImageInfo(infoPtr->himl, 0, &iinfo);
291 xoff = iinfo.rcImage.right - iinfo.rcImage.left + CBE_SEP;
292 }
293 GetClientRect (infoPtr->hwndCombo, &rect);
294 InflateRect (&rect, -2, -2);
295 InvalidateRect (infoPtr->hwndCombo, &rect, TRUE);
296
297 /* reposition the Edit control based on whether icon exists */
298 COMBOEX_GetComboFontSize (infoPtr, &mysize);
299 TRACE("Combo font x=%ld, y=%ld\n", mysize.cx, mysize.cy);
300 x = xoff + CBE_STARTOFFSET + 1;
301 y = CBE_EXTRA + 1;
302 w = rect.right-rect.left - x - GetSystemMetrics(SM_CXVSCROLL) - 1;
303 h = mysize.cy + 1;
304
305 TRACE("Combo client (%d,%d)-(%d,%d), setting Edit to (%d,%d)-(%d,%d)\n",
306 rect.left, rect.top, rect.right, rect.bottom,
307 x, y, x + w, y + h);
308 SetWindowPos(infoPtr->hwndEdit, HWND_TOP,
309 x, y,
310 w, h,
311 SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOZORDER);
312}
313
314
315static void
316COMBOEX_ReSize (HWND hwnd, COMBOEX_INFO *infoPtr)
317{
318 SIZE mysize;
319 UINT cy;
320 IMAGEINFO iinfo;
321
322 COMBOEX_GetComboFontSize (infoPtr, &mysize);
323 cy = mysize.cy + CBE_EXTRA;
324 if (infoPtr->himl) {
325 ImageList_GetImageInfo(infoPtr->himl, 0, &iinfo);
326 cy = max (iinfo.rcImage.bottom - iinfo.rcImage.top, cy);
327 TRACE("upgraded height due to image: height=%d\n", cy);
328 }
329 SendMessageW (hwnd, CB_SETITEMHEIGHT, (WPARAM) -1, (LPARAM) cy);
330 if (infoPtr->hwndCombo)
331 SendMessageW (infoPtr->hwndCombo, CB_SETITEMHEIGHT,
332 (WPARAM) 0, (LPARAM) cy);
333}
334
335
336static void
337COMBOEX_SetEditText (COMBOEX_INFO *infoPtr, CBE_ITEMDATA *item)
338{
339 if (!infoPtr->hwndEdit) return;
340 /* native issues the following messages to the {Edit} control */
341 /* WM_SETTEXT (0,addr) */
342 /* EM_SETSEL32 (0,0) */
343 /* EM_SETSEL32 (0,-1) */
344 if (item->mask & CBEIF_TEXT) {
345 SendMessageW (infoPtr->hwndEdit, WM_SETTEXT, 0, (LPARAM)item->pszText);
346 SendMessageW (infoPtr->hwndEdit, EM_SETSEL, 0, 0);
347 SendMessageW (infoPtr->hwndEdit, EM_SETSEL, 0, -1);
348 }
349}
350
351
352static CBE_ITEMDATA *
353COMBOEX_FindItem(COMBOEX_INFO *infoPtr, INT index)
354{
355 CBE_ITEMDATA *item;
356 INT i;
357
358 if ((index > infoPtr->nb_items) || (index < -1))
359 return 0;
360 if (index == -1)
361 return infoPtr->edit;
362 item = infoPtr->items;
363 i = infoPtr->nb_items - 1;
364
365 /* find the item in the list */
366 while (item && (i > index)) {
367 item = (CBE_ITEMDATA *)item->next;
368 i--;
369 }
370 if (!item || (i != index)) {
371 FIXME("COMBOBOXEX item structures broken. Please report!\n");
372 return 0;
373 }
374 return item;
375}
376
377
378static void
379COMBOEX_WarnCallBack (CBE_ITEMDATA *item)
380{
381 if (item->pszText == LPSTR_TEXTCALLBACKW)
382 FIXME("Callback not implemented yet for pszText\n");
383 if (item->iImage == I_IMAGECALLBACK)
384 FIXME("Callback not implemented yet for iImage\n");
385 if (item->iSelectedImage == I_IMAGECALLBACK)
386 FIXME("Callback not implemented yet for iSelectedImage\n");
387 if (item->iOverlay == I_IMAGECALLBACK)
388 FIXME("Callback not implemented yet for iOverlay\n");
389 if (item->iIndent == I_INDENTCALLBACK)
390 FIXME("Callback not implemented yet for iIndent\n");
391}
392
393
394/* *** CBEM_xxx message support *** */
395
396
397static LRESULT
398COMBOEX_DeleteItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
399{
400 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
401 INT index = (INT) wParam;
402 CBE_ITEMDATA *item;
403
404 TRACE("(0x%08x 0x%08lx)\n", wParam, lParam);
405
406 /* if item number requested does not exist then return failure */
407 if ((index > infoPtr->nb_items) || (index < 0)) {
408 ERR("attempt to delete item that does not exist\n");
409 return CB_ERR;
410 }
411
412 if (!(item = COMBOEX_FindItem(infoPtr, index))) {
413 ERR("attempt to delete item that was not found!\n");
414 return CB_ERR;
415 }
416
417 /* doing this will result in WM_DELETEITEM being issued */
418 SendMessageW (infoPtr->hwndCombo, CB_DELETESTRING, (WPARAM)index, 0);
419
420 return infoPtr->nb_items;
421}
422
423
424inline static LRESULT
425COMBOEX_GetComboControl (HWND hwnd, WPARAM wParam, LPARAM lParam)
426{
427 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
428
429 TRACE("\n");
430
431 return (LRESULT)infoPtr->hwndCombo;
432}
433
434
435inline static LRESULT
436COMBOEX_GetEditControl (HWND hwnd, WPARAM wParam, LPARAM lParam)
437{
438 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
439
440 if ((GetWindowLongA (hwnd, GWL_STYLE) & CBS_DROPDOWNLIST) != CBS_DROPDOWN)
441 return 0;
442
443 TRACE("-- 0x%x\n", infoPtr->hwndEdit);
444
445 return (LRESULT)infoPtr->hwndEdit;
446}
447
448
449inline static LRESULT
450COMBOEX_GetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
451{
452 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
453
454 TRACE("-- 0x%08lx\n", infoPtr->dwExtStyle);
455
456 return (LRESULT)infoPtr->dwExtStyle;
457}
458
459
460inline static LRESULT
461COMBOEX_GetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
462{
463 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
464
465 TRACE("-- 0x%p\n", infoPtr->himl);
466
467 return (LRESULT)infoPtr->himl;
468}
469
470
471static LRESULT
472COMBOEX_GetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
473{
474 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
475 COMBOBOXEXITEMW *cit = (COMBOBOXEXITEMW *) lParam;
476 INT index;
477 CBE_ITEMDATA *item;
478
479 TRACE("(0x%08x 0x%08lx)\n", wParam, lParam);
480
481 /* get real index of item to insert */
482 index = cit->iItem;
483
484 /* if item number requested does not exist then return failure */
485 if ((index > infoPtr->nb_items) || (index < -1)) {
486 ERR("attempt to get item that does not exist\n");
487 return 0;
488 }
489
490 /* if the item is the edit control and there is no edit control, skip */
491 if ((index == -1) &&
492 ((GetWindowLongA (hwnd, GWL_STYLE) & CBS_DROPDOWNLIST) != CBS_DROPDOWN))
493 return 0;
494
495 if (!(item = COMBOEX_FindItem(infoPtr, index))) {
496 ERR("attempt to get item that was not found!\n");
497 return 0;
498 }
499
500 COMBOEX_CopyItem (infoPtr, item, cit);
501
502 return TRUE;
503}
504
505
506inline static LRESULT
507COMBOEX_GetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
508{
509 COMBOBOXEXITEMA *cit = (COMBOBOXEXITEMA *) lParam;
510 COMBOBOXEXITEMW tmpcit;
511 INT len;
512
513 TRACE("(0x%08x 0x%08lx)\n", wParam, lParam);
514
515 tmpcit.mask = cit->mask;
516 tmpcit.iItem = cit->iItem;
517 COMBOEX_GetItemW (hwnd, wParam, (LPARAM) &tmpcit);
518
519 len = WideCharToMultiByte (CP_ACP, 0, tmpcit.pszText, -1, 0, 0, NULL, NULL);
520 if (len > 0)
521 WideCharToMultiByte (CP_ACP, 0, tmpcit.pszText, -1,
522 cit->pszText, cit->cchTextMax, NULL, NULL);
523
524 cit->iImage = tmpcit.iImage;
525 cit->iSelectedImage = tmpcit.iSelectedImage;
526 cit->iOverlay = tmpcit.iOverlay;
527 cit->iIndent = tmpcit.iIndent;
528 cit->lParam = tmpcit.lParam;
529
530 return TRUE;
531}
532
533
534inline static LRESULT
535COMBOEX_GetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
536{
537 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
538
539 TRACE("%s hwnd=0x%x stub!\n",
540 infoPtr->bUnicode ? "TRUE" : "FALSE", hwnd);
541
542 return infoPtr->bUnicode;
543}
544
545
546inline static LRESULT
547COMBOEX_HasEditChanged (HWND hwnd, WPARAM wParam, LPARAM lParam)
548{
549 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
550
551 if ((GetWindowLongA (hwnd, GWL_STYLE) & CBS_DROPDOWNLIST) != CBS_DROPDOWN)
552 return FALSE;
553 if ((infoPtr->flags & (WCBE_ACTEDIT | WCBE_EDITCHG)) ==
554 (WCBE_ACTEDIT | WCBE_EDITCHG))
555 return TRUE;
556 return FALSE;
557}
558
559
560static LRESULT
561COMBOEX_InsertItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
562{
563 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
564 COMBOBOXEXITEMW *cit = (COMBOBOXEXITEMW *) lParam;
565 INT index;
566 CBE_ITEMDATA *item;
567 NMCOMBOBOXEXW nmcit;
568
569 TRACE("\n");
570
571 COMBOEX_DumpInput ((COMBOBOXEXITEMA *) cit, TRUE);
572
573 /* get real index of item to insert */
574 index = cit->iItem;
575 if (index == -1) index = infoPtr->nb_items;
576 if (index > infoPtr->nb_items) index = infoPtr->nb_items;
577
578 /* get space and chain it in */
579 item = (CBE_ITEMDATA *)COMCTL32_Alloc (sizeof (CBE_ITEMDATA));
580 item->next = NULL;
581 item->pszText = NULL;
582
583 /* locate position to insert new item in */
584 if (index == infoPtr->nb_items) {
585 /* fast path for iItem = -1 */
586 item->next = infoPtr->items;
587 infoPtr->items = item;
588 }
589 else {
590 INT i = infoPtr->nb_items-1;
591 CBE_ITEMDATA *moving = infoPtr->items;
592
593 while ((i > index) && moving) {
594 moving = (CBE_ITEMDATA *)moving->next;
595 i--;
596 }
597 if (!moving) {
598 FIXME("COMBOBOXEX item structures broken. Please report!\n");
599 COMCTL32_Free(item);
600 return -1;
601 }
602 item->next = moving->next;
603 moving->next = item;
604 }
605
606 /* fill in our hidden item structure */
607 item->mask = cit->mask;
608 if (item->mask & CBEIF_TEXT) {
609 LPWSTR str;
610 INT len;
611
612 str = cit->pszText;
613 if (!str) str = (LPWSTR) L"";
614 len = strlenW (str);
615 if (len > 0) {
616 item->pszText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
617 strcpyW (item->pszText, str);
618 }
619 item->cchTextMax = cit->cchTextMax;
620 }
621 if (item->mask & CBEIF_IMAGE)
622 item->iImage = cit->iImage;
623 if (item->mask & CBEIF_SELECTEDIMAGE)
624 item->iSelectedImage = cit->iSelectedImage;
625 if (item->mask & CBEIF_OVERLAY)
626 item->iOverlay = cit->iOverlay;
627 if (item->mask & CBEIF_INDENT)
628 item->iIndent = cit->iIndent;
629 if (item->mask & CBEIF_LPARAM)
630 item->lParam = cit->lParam;
631 infoPtr->nb_items++;
632
633 COMBOEX_WarnCallBack (item);
634
635 COMBOEX_DumpItem (item);
636
637 SendMessageW (infoPtr->hwndCombo, CB_INSERTSTRING,
638 (WPARAM)cit->iItem, (LPARAM)item);
639
640 COMBOEX_CopyItem (infoPtr, item, &nmcit.ceItem);
641 COMBOEX_Notify (infoPtr, CBEN_INSERTITEM, (NMHDR *)&nmcit, TRUE);
642
643 return index;
644
645}
646
647
648static LRESULT
649COMBOEX_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
650{
651 COMBOBOXEXITEMA *cit = (COMBOBOXEXITEMA *) lParam;
652 COMBOBOXEXITEMW citW;
653 LRESULT ret;
654
655 memcpy(&citW,cit,sizeof(COMBOBOXEXITEMA));
656 if (cit->mask & CBEIF_TEXT) {
657 LPSTR str;
658 INT len;
659
660 str = cit->pszText;
661 if (!str) str="";
662 len = MultiByteToWideChar (CP_ACP, 0, str, -1, NULL, 0);
663 if (len > 0) {
664 citW.pszText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
665 MultiByteToWideChar (CP_ACP, 0, str, -1, citW.pszText, len);
666 }
667 }
668 ret = COMBOEX_InsertItemW(hwnd,wParam,(LPARAM)&citW);;
669
670 if (cit->mask & CBEIF_TEXT)
671 COMCTL32_Free(citW.pszText);
672 return ret;
673}
674
675
676static LRESULT
677COMBOEX_SetExtendedStyle (HWND hwnd, WPARAM wParam, LPARAM lParam)
678{
679 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
680 DWORD dwTemp;
681
682 TRACE("(0x%08x 0x%08lx)\n", wParam, lParam);
683
684 dwTemp = infoPtr->dwExtStyle;
685
686 if (lParam & (CBES_EX_NOEDITIMAGEINDENT |
687 CBES_EX_PATHWORDBREAKPROC |
688 CBES_EX_NOSIZELIMIT |
689 CBES_EX_CASESENSITIVE))
690 FIXME("Extended style not implemented %08lx\n", lParam);
691
692 if ((DWORD)wParam) {
693 infoPtr->dwExtStyle = (infoPtr->dwExtStyle & ~(DWORD)wParam) | (DWORD)lParam;
694 }
695 else
696 infoPtr->dwExtStyle = (DWORD)lParam;
697
698 /*
699 * native does this for CBES_EX_NOEDITIMAGE state change
700 */
701 if ((infoPtr->dwExtStyle & CBES_EX_NOEDITIMAGE) ^
702 (dwTemp & CBES_EX_NOEDITIMAGE)) {
703 /* if state of EX_NOEDITIMAGE changes, invalidate all */
704 TRACE("EX_NOEDITIMAGE state changed to %ld\n",
705 infoPtr->dwExtStyle & CBES_EX_NOEDITIMAGE);
706 InvalidateRect (hwnd, NULL, TRUE);
707 COMBOEX_AdjustEditPos (infoPtr);
708 if (infoPtr->hwndEdit)
709 InvalidateRect (infoPtr->hwndEdit, NULL, TRUE);
710 }
711
712 return (LRESULT)dwTemp;
713}
714
715
716inline static LRESULT
717COMBOEX_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
718{
719 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
720 HIMAGELIST himlTemp;
721
722 TRACE("(0x%08x 0x%08lx)\n", wParam, lParam);
723
724 himlTemp = infoPtr->himl;
725 infoPtr->himl = (HIMAGELIST)lParam;
726
727 COMBOEX_ReSize (hwnd, infoPtr);
728 InvalidateRect (infoPtr->hwndCombo, NULL, TRUE);
729
730 /* reposition the Edit control based on whether icon exists */
731 COMBOEX_AdjustEditPos (infoPtr);
732 return (LRESULT)himlTemp;
733}
734
735static LRESULT
736COMBOEX_SetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
737{
738 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
739 COMBOBOXEXITEMW *cit = (COMBOBOXEXITEMW *) lParam;
740 INT index;
741 CBE_ITEMDATA *item;
742
743 COMBOEX_DumpInput ((COMBOBOXEXITEMA *) cit, TRUE);
744
745 /* get real index of item to insert */
746 index = cit->iItem;
747
748 /* if item number requested does not exist then return failure */
749 if ((index > infoPtr->nb_items) || (index < -1)) {
750 ERR("attempt to set item that does not exist yet!\n");
751 return 0;
752 }
753
754 /* if the item is the edit control and there is no edit control, skip */
755 if ((index == -1) &&
756 ((GetWindowLongA (hwnd, GWL_STYLE) & CBS_DROPDOWNLIST) != CBS_DROPDOWN))
757 return 0;
758
759 if (!(item = COMBOEX_FindItem(infoPtr, index))) {
760 ERR("attempt to set item that was not found!\n");
761 return 0;
762 }
763
764 /* add/change stuff to the internal item structure */
765 item->mask |= cit->mask;
766 if (cit->mask & CBEIF_TEXT) {
767 LPWSTR str;
768 INT len;
769 WCHAR emptystr[1] = {0};
770
771 str = cit->pszText;
772 if (!str) str=emptystr;
773 len = strlenW(str);
774 if (len > 0) {
775 item->pszText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
776 strcpyW(item->pszText,str);
777 }
778 item->cchTextMax = cit->cchTextMax;
779 }
780 if (cit->mask & CBEIF_IMAGE)
781 item->iImage = cit->iImage;
782 if (cit->mask & CBEIF_SELECTEDIMAGE)
783 item->iSelectedImage = cit->iSelectedImage;
784 if (cit->mask & CBEIF_OVERLAY)
785 item->iOverlay = cit->iOverlay;
786 if (cit->mask & CBEIF_INDENT)
787 item->iIndent = cit->iIndent;
788 if (cit->mask & CBEIF_LPARAM)
789 cit->lParam = cit->lParam;
790
791 COMBOEX_WarnCallBack (item);
792
793 COMBOEX_DumpItem (item);
794
795 /* if original request was to update edit control, do some fast foot work */
796 if (cit->iItem == -1) {
797 COMBOEX_SetEditText (infoPtr, item);
798 RedrawWindow (infoPtr->hwndCombo, 0, 0, RDW_ERASE | RDW_INVALIDATE);
799 }
800 return TRUE;
801}
802
803static LRESULT
804COMBOEX_SetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
805{
806 COMBOBOXEXITEMA *cit = (COMBOBOXEXITEMA *) lParam;
807 COMBOBOXEXITEMW citW;
808 LRESULT ret;
809
810 memcpy(&citW,cit,sizeof(COMBOBOXEXITEMA));
811 if (cit->mask & CBEIF_TEXT) {
812 LPSTR str;
813 INT len;
814
815 str = cit->pszText;
816 if (!str) str="";
817 len = MultiByteToWideChar (CP_ACP, 0, str, -1, NULL, 0);
818 if (len > 0) {
819 citW.pszText = (LPWSTR)COMCTL32_Alloc ((len + 1)*sizeof(WCHAR));
820 MultiByteToWideChar (CP_ACP, 0, str, -1, citW.pszText, len);
821 }
822 }
823 ret = COMBOEX_SetItemW(hwnd,wParam,(LPARAM)&citW);;
824
825 if (cit->mask & CBEIF_TEXT)
826 COMCTL32_Free(citW.pszText);
827 return ret;
828}
829
830
831inline static LRESULT
832COMBOEX_SetUnicodeFormat (HWND hwnd, WPARAM wParam, LPARAM lParam)
833{
834 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
835 BOOL bTemp;
836
837 TRACE("%s hwnd=0x%04x stub!\n",
838 ((BOOL)wParam) ? "TRUE" : "FALSE", hwnd);
839
840 bTemp = infoPtr->bUnicode;
841 infoPtr->bUnicode = (BOOL)wParam;
842
843 return bTemp;
844}
845
846
847
848/* *** CB_xxx message support *** */
849
850
851static LRESULT
852COMBOEX_FindStringExact (COMBOEX_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
853{
854 INT i, count;
855 CBE_ITEMDATA *item;
856 LPWSTR desired = NULL;
857 INT start = (INT) wParam;
858
859 i = MultiByteToWideChar (CP_ACP, 0, (LPSTR)lParam, -1, NULL, 0);
860 if (i > 0) {
861 desired = (LPWSTR)COMCTL32_Alloc ((i + 1)*sizeof(WCHAR));
862 MultiByteToWideChar (CP_ACP, 0, (LPSTR)lParam, -1, desired, i);
863 }
864
865 count = SendMessageW (infoPtr->hwndCombo, CB_GETCOUNT, 0 , 0);
866
867 /* now search from after starting loc and wrapping back to start */
868 for(i=start+1; i<count; i++) {
869 item = (CBE_ITEMDATA *)SendMessageW (infoPtr->hwndCombo,
870 CB_GETITEMDATA, (WPARAM)i, 0);
871 TRACE("desired=%s, item=%s\n",
872 debugstr_w(desired), debugstr_w(item->pszText));
873 if (lstrcmpiW(item->pszText, desired) == 0) {
874 COMCTL32_Free (desired);
875 return i;
876 }
877 }
878 for(i=0; i<=start; i++) {
879 item = (CBE_ITEMDATA *)SendMessageW (infoPtr->hwndCombo,
880 CB_GETITEMDATA, (WPARAM)i, 0);
881 TRACE("desired=%s, item=%s\n",
882 debugstr_w(desired), debugstr_w(item->pszText));
883 if (lstrcmpiW(item->pszText, desired) == 0) {
884 COMCTL32_Free (desired);
885 return i;
886 }
887 }
888 COMCTL32_Free(desired);
889 return CB_ERR;
890}
891
892
893static LRESULT
894COMBOEX_GetItemData (HWND hwnd, WPARAM wParam, LPARAM lParam)
895{
896 INT index = wParam;
897 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
898 CBE_ITEMDATA *item1, *item2;
899 LRESULT lret = 0;
900
901 item1 = (CBE_ITEMDATA *)COMBOEX_Forward (hwnd, CB_GETITEMDATA,
902 wParam, lParam);
903 if ((item1 != NULL) && ((LRESULT)item1 != CB_ERR)) {
904 item2 = COMBOEX_FindItem (infoPtr, index);
905 if (item2 != item1) {
906 ERR("data structures damaged!\n");
907 return CB_ERR;
908 }
909 if (item1->mask & CBEIF_LPARAM)
910 lret = (LRESULT) item1->lParam;
911 TRACE("returning 0x%08lx\n", lret);
912 return lret;
913 }
914 lret = (LRESULT)item1;
915 TRACE("non-valid result from combo, returning 0x%08lx\n", lret);
916 return lret;
917}
918
919
920static LRESULT
921COMBOEX_SetCursel (HWND hwnd, WPARAM wParam, LPARAM lParam)
922{
923 INT index = wParam;
924 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
925 CBE_ITEMDATA *item;
926 LRESULT lret;
927
928 if (!(item = COMBOEX_FindItem(infoPtr, index))) {
929 /* FIXME: need to clear selection */
930 return CB_ERR;
931 }
932
933 TRACE("selecting item %d text=%s\n", index, (item->pszText) ?
934 debugstr_w(item->pszText) : "<null>");
935 infoPtr->selected = index;
936
937 lret = SendMessageW (infoPtr->hwndCombo, CB_SETCURSEL, wParam, lParam);
938 COMBOEX_SetEditText (infoPtr, item);
939 return lret;
940}
941
942
943static LRESULT
944COMBOEX_SetItemData (HWND hwnd, WPARAM wParam, LPARAM lParam)
945{
946 INT index = wParam;
947 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
948 CBE_ITEMDATA *item1, *item2;
949
950 item1 = (CBE_ITEMDATA *)COMBOEX_Forward (hwnd, CB_GETITEMDATA,
951 wParam, lParam);
952 if ((item1 != NULL) && ((LRESULT)item1 != CB_ERR)) {
953 item2 = COMBOEX_FindItem (infoPtr, index);
954 if (item2 != item1) {
955 ERR("data structures damaged!\n");
956 return CB_ERR;
957 }
958 item1->mask |= CBEIF_LPARAM;
959 item1->lParam = lParam;
960 TRACE("setting lparam to 0x%08lx\n", lParam);
961 return 0;
962 }
963 TRACE("non-valid result from combo 0x%08lx\n", (DWORD)item1);
964 return (LRESULT)item1;
965}
966
967
968static LRESULT
969COMBOEX_SetItemHeight (HWND hwnd, WPARAM wParam, LPARAM lParam)
970{
971 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
972 RECT cb_wrect, cbx_wrect, cbx_crect;
973 LRESULT ret = 0;
974 UINT height;
975
976 /* First, lets forward the message to the normal combo control
977 just like Windows. */
978 if (infoPtr->hwndCombo)
979 SendMessageW (infoPtr->hwndCombo, CB_SETITEMHEIGHT, wParam, lParam);
980
981 GetWindowRect (infoPtr->hwndCombo, &cb_wrect);
982 GetWindowRect (hwnd, &cbx_wrect);
983 GetClientRect (hwnd, &cbx_crect);
984 /* the height of comboex as height of the combo + comboex border */
985 height = cb_wrect.bottom-cb_wrect.top
986 + cbx_wrect.bottom-cbx_wrect.top
987 - (cbx_crect.bottom-cbx_crect.top);
988 TRACE("EX window=(%d,%d)-(%d,%d), client=(%d,%d)-(%d,%d)\n",
989 cbx_wrect.left, cbx_wrect.top, cbx_wrect.right, cbx_wrect.bottom,
990 cbx_crect.left, cbx_crect.top, cbx_crect.right, cbx_crect.bottom);
991 TRACE("CB window=(%d,%d)-(%d,%d), EX setting=(0,0)-(%d,%d)\n",
992 cb_wrect.left, cb_wrect.top, cb_wrect.right, cb_wrect.bottom,
993 cbx_wrect.right-cbx_wrect.left, height);
994 SetWindowPos (hwnd, HWND_TOP, 0, 0,
995 cbx_wrect.right-cbx_wrect.left,
996 height,
997 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
998
999 return ret;
1000}
1001
1002
1003/* *** WM_xxx message support *** */
1004
1005
1006static LRESULT
1007COMBOEX_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1008{
1009 LPCREATESTRUCTA cs = (LPCREATESTRUCTA) lParam;
1010 COMBOEX_INFO *infoPtr;
1011 DWORD dwComboStyle;
1012 LOGFONTA mylogfont;
1013 CBE_ITEMDATA *item;
1014 RECT wnrc1, clrc1, cmbwrc;
1015 LONG test;
1016
1017 /* allocate memory for info structure */
1018#ifdef __WIN32OS2__
1019 infoPtr = (COMBOEX_INFO*)initControl(hwnd,sizeof(COMBOEX_INFO));
1020#else
1021 infoPtr = (COMBOEX_INFO *)COMCTL32_Alloc (sizeof(COMBOEX_INFO));
1022#endif
1023 if (infoPtr == NULL) {
1024 ERR("could not allocate info memory!\n");
1025 return 0;
1026 }
1027
1028 /* initialize info structure */
1029
1030 infoPtr->items = NULL;
1031 infoPtr->nb_items = 0;
1032 infoPtr->hwndSelf = hwnd;
1033 infoPtr->selected = -1;
1034
1035 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
1036
1037 /* create combo box */
1038 dwComboStyle = GetWindowLongA (hwnd, GWL_STYLE) &
1039 (CBS_SIMPLE|CBS_DROPDOWN|CBS_DROPDOWNLIST|WS_CHILD);
1040
1041 GetWindowRect(hwnd, &wnrc1);
1042 GetClientRect(hwnd, &clrc1);
1043 TRACE("EX window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d)\n",
1044 wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom,
1045 clrc1.left, clrc1.top, clrc1.right, clrc1.bottom);
1046 TRACE("combo style=%08lx, adding style=%08lx\n", dwComboStyle,
1047 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VSCROLL |
1048 CBS_NOINTEGRALHEIGHT | CBS_DROPDOWNLIST |
1049 WS_CHILD | WS_VISIBLE | CBS_OWNERDRAWFIXED);
1050
1051 /* Native version of ComboEx creates the ComboBox with DROPDOWNLIST */
1052 /* specified. It then creates it's own version of the EDIT control */
1053 /* and makes the ComboBox the parent. This is because a normal */
1054 /* DROPDOWNLIST does not have a EDIT control, but we need one. */
1055 /* We also need to place the edit control at the proper location */
1056 /* (allow space for the icons). */
1057
1058 infoPtr->hwndCombo = CreateWindowA ("ComboBox", "",
1059 /* following line added to match native */
1060 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VSCROLL |
1061 CBS_NOINTEGRALHEIGHT | CBS_DROPDOWNLIST |
1062 /* was base and is necessary */
1063 WS_CHILD | WS_VISIBLE | CBS_OWNERDRAWFIXED | dwComboStyle,
1064 cs->y, cs->x, cs->cx, cs->cy, hwnd,
1065 (HMENU) GetWindowLongA (hwnd, GWL_ID),
1066 GetWindowLongA (hwnd, GWL_HINSTANCE), NULL);
1067
1068 /*
1069 * native does the following at this point according to trace:
1070 * GetWindowThreadProcessId(hwndCombo,0)
1071 * GetCurrentThreadId()
1072 * GetWindowThreadProcessId(hwndCombo, &???)
1073 * GetCurrentProcessId()
1074 */
1075
1076 /*
1077 * Setup a property to hold the pointer to the COMBOBOXEX
1078 * data structure.
1079 */
1080 test = GetPropA(infoPtr->hwndCombo, (LPCSTR)(LONG)ComboExInfo);
1081 if (!test || ((COMBOEX_INFO *)test != infoPtr)) {
1082 SetPropA(infoPtr->hwndCombo, "CC32SubclassInfo", (LONG)infoPtr);
1083 }
1084 infoPtr->prevComboWndProc = (WNDPROC)SetWindowLongA(infoPtr->hwndCombo,
1085 GWL_WNDPROC, (LONG)COMBOEX_ComboWndProc);
1086 infoPtr->font = SendMessageW (infoPtr->hwndCombo, WM_GETFONT, 0, 0);
1087
1088
1089 /*
1090 * Now create our own EDIT control so we can position it.
1091 * It is created only for CBS_DROPDOWN style
1092 */
1093 if ((cs->style & CBS_DROPDOWNLIST) == CBS_DROPDOWN) {
1094 infoPtr->hwndEdit = CreateWindowExA (0, "EDIT", "",
1095 WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | ES_AUTOHSCROLL,
1096 0, 0, 0, 0, /* will set later */
1097 infoPtr->hwndCombo,
1098 (HMENU) GetWindowLongA (hwnd, GWL_ID),
1099 GetWindowLongA (hwnd, GWL_HINSTANCE),
1100 NULL);
1101
1102 /* native does the following at this point according to trace:
1103 * GetWindowThreadProcessId(hwndEdit,0)
1104 * GetCurrentThreadId()
1105 * GetWindowThreadProcessId(hwndEdit, &???)
1106 * GetCurrentProcessId()
1107 */
1108
1109 /*
1110 * Setup a property to hold the pointer to the COMBOBOXEX
1111 * data structure.
1112 */
1113 test = GetPropA(infoPtr->hwndEdit, (LPCSTR)(LONG)ComboExInfo);
1114 if (!test || ((COMBOEX_INFO *)test != infoPtr)) {
1115 SetPropA(infoPtr->hwndEdit, "CC32SubclassInfo", (LONG)infoPtr);
1116 }
1117 infoPtr->prevEditWndProc = (WNDPROC)SetWindowLongA(infoPtr->hwndEdit,
1118 GWL_WNDPROC, (LONG)COMBOEX_EditWndProc);
1119 infoPtr->font = SendMessageW (infoPtr->hwndCombo, WM_GETFONT, 0, 0);
1120 }
1121 else {
1122 infoPtr->hwndEdit = 0;
1123 infoPtr->font = 0;
1124 }
1125
1126 /*
1127 * Locate the default font if necessary and then set it in
1128 * all associated controls
1129 */
1130 if (!infoPtr->font) {
1131 SystemParametersInfoA (SPI_GETICONTITLELOGFONT, sizeof(mylogfont),
1132 &mylogfont, 0);
1133 infoPtr->font = CreateFontIndirectA (&mylogfont);
1134 }
1135 SendMessageW (infoPtr->hwndCombo, WM_SETFONT, (WPARAM)infoPtr->font, 0);
1136 if (infoPtr->hwndEdit) {
1137 SendMessageW (infoPtr->hwndEdit, WM_SETFONT, (WPARAM)infoPtr->font, 0);
1138 SendMessageW (infoPtr->hwndEdit, EM_SETMARGINS, (WPARAM)EC_USEFONTINFO, 0);
1139 }
1140
1141 COMBOEX_ReSize (hwnd, infoPtr);
1142
1143 /* Above is fairly certain, below is much less certain. */
1144
1145 GetWindowRect(hwnd, &wnrc1);
1146 GetClientRect(hwnd, &clrc1);
1147 GetWindowRect(infoPtr->hwndCombo, &cmbwrc);
1148 TRACE("EX window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d) CB wnd=(%d,%d)-(%d,%d)\n",
1149 wnrc1.left, wnrc1.top, wnrc1.right, wnrc1.bottom,
1150 clrc1.left, clrc1.top, clrc1.right, clrc1.bottom,
1151 cmbwrc.left, cmbwrc.top, cmbwrc.right, cmbwrc.bottom);
1152 SetWindowPos(infoPtr->hwndCombo, HWND_TOP,
1153 0, 0, wnrc1.right-wnrc1.left, wnrc1.bottom-wnrc1.top,
1154 SWP_NOACTIVATE | SWP_NOREDRAW);
1155
1156 GetWindowRect(infoPtr->hwndCombo, &cmbwrc);
1157 TRACE("CB window=(%d,%d)-(%d,%d)\n",
1158 cmbwrc.left, cmbwrc.top, cmbwrc.right, cmbwrc.bottom);
1159 SetWindowPos(hwnd, HWND_TOP,
1160 0, 0, cmbwrc.right-cmbwrc.left, cmbwrc.bottom-cmbwrc.top,
1161 SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE);
1162
1163 COMBOEX_AdjustEditPos (infoPtr);
1164
1165 /*
1166 * Create an item structure to represent the data in the
1167 * EDIT control.
1168 */
1169 item = (CBE_ITEMDATA *)COMCTL32_Alloc (sizeof (CBE_ITEMDATA));
1170 item->next = NULL;
1171 item->pszText = NULL;
1172 item->mask = 0;
1173 infoPtr->edit = item;
1174
1175 return 0;
1176}
1177
1178
1179inline static LRESULT
1180COMBOEX_Command (HWND hwnd, WPARAM wParam, LPARAM lParam)
1181{
1182 LRESULT lret;
1183 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
1184 INT command = HIWORD(wParam);
1185 CBE_ITEMDATA *item = 0;
1186 WCHAR wintext[520];
1187 INT cursel, n, oldItem;
1188 NMCBEENDEDITA cbeend;
1189 DWORD oldflags;
1190
1191 TRACE("for command %d\n", command);
1192
1193 switch (command)
1194 {
1195 case CBN_DROPDOWN:
1196 SendMessageW (GetParent (hwnd), WM_COMMAND, wParam,
1197 (LPARAM)hwnd);
1198 /*
1199 * from native trace of first dropdown after typing in URL in IE4
1200 * CB_GETCURSEL(Combo)
1201 * GetWindowText(Edit)
1202 * CB_GETCURSEL(Combo)
1203 * CB_GETCOUNT(Combo)
1204 * CB_GETITEMDATA(Combo, n)
1205 * WM_NOTIFY(parent, CBEN_ENDEDITA|W)
1206 * CB_GETCURSEL(Combo)
1207 * CB_SETCURSEL(COMBOEX, n)
1208 * SetFocus(Combo)
1209 * the rest is supposition
1210 */
1211 cursel = SendMessageW (infoPtr->hwndCombo, CB_GETCURSEL, 0, 0);
1212 if (cursel == -1) {
1213 /* find match from edit against those in Combobox */
1214 GetWindowTextW (infoPtr->hwndEdit, wintext, 520);
1215 n = SendMessageW (infoPtr->hwndCombo, CB_GETCOUNT, 0, 0);
1216 for (cursel = 0; cursel < n; cursel++){
1217 item = (CBE_ITEMDATA *)SendMessageW (infoPtr->hwndCombo,
1218 CB_GETITEMDATA,
1219 cursel, 0);
1220 if ((INT)item == CB_ERR) break;
1221 if (lstrcmpiW(item->pszText, wintext) == 0) break;
1222 }
1223 if ((cursel == n) || ((INT)item == CB_ERR)) {
1224 TRACE("failed to find match??? item=%p cursel=%d\n",
1225 item, cursel);
1226 if (infoPtr->hwndEdit)
1227 SetFocus(infoPtr->hwndEdit);
1228 return 0;
1229 }
1230 }
1231 else {
1232 item = (CBE_ITEMDATA *)SendMessageW (infoPtr->hwndCombo,
1233 CB_GETITEMDATA,
1234 cursel, 0);
1235 if ((INT)item == CB_ERR) {
1236 TRACE("failed to find match??? item=%p cursel=%d\n",
1237 item, cursel);
1238 if (infoPtr->hwndEdit)
1239 SetFocus(infoPtr->hwndEdit);
1240 return 0;
1241 }
1242 }
1243
1244 /* Save flags for testing and reset them */
1245 oldflags = infoPtr->flags;
1246 infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG);
1247
1248 if (oldflags & WCBE_ACTEDIT) {
1249 WideCharToMultiByte (CP_ACP, 0, item->pszText, -1,
1250 cbeend.szText, sizeof(cbeend.szText),
1251 NULL, NULL);
1252 cbeend.fChanged = (oldflags & WCBE_EDITCHG);
1253 cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo,
1254 CB_GETCURSEL, 0, 0);
1255 cbeend.iWhy = CBENF_DROPDOWN;
1256
1257 if (COMBOEX_Notify (infoPtr, CBEN_ENDEDITA,
1258 (NMHDR *)&cbeend, FALSE)) {
1259 /* abort the change */
1260 TRACE("Notify requested abort of change\n");
1261 return 0;
1262 }
1263 }
1264
1265 /* if selection has changed the set the new current selection */
1266 cursel = SendMessageW (infoPtr->hwndCombo, CB_GETCURSEL, 0, 0);
1267 if ((oldflags & WCBE_EDITCHG) || (cursel != infoPtr->selected)) {
1268 infoPtr->selected = cursel;
1269 SendMessageW (hwnd, CB_SETCURSEL, cursel, 0);
1270 SetFocus(infoPtr->hwndCombo);
1271 }
1272 return 0;
1273
1274 case CBN_SELCHANGE:
1275 /*
1276 * CB_GETCURSEL(Combo)
1277 * CB_GETITEMDATA(Combo) < simulated by COMBOEX_FindItem
1278 * lstrlenA
1279 * WM_SETTEXT(Edit)
1280 * WM_GETTEXTLENGTH(Edit)
1281 * WM_GETTEXT(Edit)
1282 * EM_SETSEL(Edit, 0,0)
1283 * WM_GETTEXTLENGTH(Edit)
1284 * WM_GETTEXT(Edit)
1285 * EM_SETSEL(Edit, 0,len)
1286 * return WM_COMMAND to parent
1287 */
1288 oldItem = SendMessageW (infoPtr->hwndCombo, CB_GETCURSEL, 0, 0);
1289 if (!(item = COMBOEX_FindItem(infoPtr, oldItem))) {
1290 ERR("item %d not found. Problem!\n", oldItem);
1291 break;
1292 }
1293 infoPtr->selected = oldItem;
1294 COMBOEX_SetEditText (infoPtr, item);
1295 return SendMessageW (GetParent (hwnd), WM_COMMAND, wParam,
1296 (LPARAM)hwnd);
1297
1298 case CBN_SELENDOK:
1299 /*
1300 * We have to change the handle since we are the control
1301 * issuing the message. IE4 depends on this.
1302 */
1303 return SendMessageW (GetParent (hwnd), WM_COMMAND, wParam,
1304 (LPARAM)hwnd);
1305
1306 case CBN_KILLFOCUS:
1307 /*
1308 * from native trace:
1309 *
1310 * pass to parent
1311 * WM_GETTEXT(Edit, 104)
1312 * CB_GETCURSEL(Combo) rets -1
1313 * WM_NOTIFY(CBEN_ENDEDITA) with CBENF_KILLFOCUS
1314 * CB_GETCURSEL(Combo)
1315 * InvalidateRect(Combo, 0, 0)
1316 * return 0
1317 */
1318 SendMessageW (GetParent (hwnd), WM_COMMAND, wParam,
1319 (LPARAM)hwnd);
1320 if (infoPtr->flags & WCBE_ACTEDIT) {
1321 GetWindowTextA (infoPtr->hwndEdit, cbeend.szText, 260);
1322 cbeend.fChanged = (infoPtr->flags & WCBE_EDITCHG);
1323 cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo,
1324 CB_GETCURSEL, 0, 0);
1325 cbeend.iWhy = CBENF_KILLFOCUS;
1326
1327 infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG);
1328 if (COMBOEX_Notify (infoPtr, CBEN_ENDEDITA,
1329 (NMHDR *)&cbeend, FALSE)) {
1330 /* abort the change */
1331 TRACE("Notify requested abort of change\n");
1332 return 0;
1333 }
1334 }
1335 /* possible CB_GETCURSEL */
1336 InvalidateRect (infoPtr->hwndCombo, 0, 0);
1337 return 0;
1338
1339 case CBN_CLOSEUP:
1340 default:
1341 /*
1342 * We have to change the handle since we are the control
1343 * issuing the message. IE4 depends on this.
1344 * We also need to set the focus back to the Edit control
1345 * after passing the command to the parent of the ComboEx.
1346 */
1347 lret = SendMessageW (GetParent (hwnd), WM_COMMAND, wParam,
1348 (LPARAM)hwnd);
1349 if (infoPtr->hwndEdit)
1350 SetFocus(infoPtr->hwndEdit);
1351 return lret;
1352 }
1353 return 0;
1354}
1355
1356
1357inline static LRESULT
1358COMBOEX_WM_DeleteItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
1359{
1360 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
1361 DELETEITEMSTRUCT *dis = (DELETEITEMSTRUCT *)lParam;
1362 CBE_ITEMDATA *item, *olditem;
1363 INT i;
1364 NMCOMBOBOXEXW nmcit;
1365
1366 TRACE("CtlType=%08x, CtlID=%08x, itemID=%08x, hwnd=%x, data=%08lx\n",
1367 dis->CtlType, dis->CtlID, dis->itemID, dis->hwndItem, dis->itemData);
1368
1369 if ((dis->itemID >= infoPtr->nb_items) || (dis->itemID < 0)) return FALSE;
1370
1371 olditem = infoPtr->items;
1372 i = infoPtr->nb_items - 1;
1373
1374 if (i == dis->itemID) {
1375 infoPtr->items = infoPtr->items->next;
1376 }
1377 else {
1378 item = olditem;
1379 i--;
1380
1381 /* find the prior item in the list */
1382 while (item->next && (i > dis->itemID)) {
1383 item = (CBE_ITEMDATA *)item->next;
1384 i--;
1385 }
1386 if (!item->next || (i != dis->itemID)) {
1387 FIXME("COMBOBOXEX item structures broken. Please report!\n");
1388 return FALSE;
1389 }
1390 olditem = item->next;
1391 item->next = (CBE_ITEMDATA *)((CBE_ITEMDATA *)item->next)->next;
1392 }
1393 infoPtr->nb_items--;
1394
1395 COMBOEX_CopyItem (infoPtr, olditem, &nmcit.ceItem);
1396 COMBOEX_Notify (infoPtr, CBEN_DELETEITEM, (NMHDR *)&nmcit, TRUE);
1397
1398 COMCTL32_Free(olditem);
1399
1400 return TRUE;
1401
1402}
1403
1404
1405inline static LRESULT
1406COMBOEX_DrawItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
1407{
1408 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
1409 DRAWITEMSTRUCT *dis = (DRAWITEMSTRUCT *)lParam;
1410 CBE_ITEMDATA *item = 0;
1411 SIZE txtsize;
1412 RECT rect;
1413 int drawimage, drawstate;
1414 UINT xbase;
1415 UINT xioff = 0; /* size and spacer of image if any */
1416 IMAGEINFO iinfo;
1417 INT len;
1418
1419 if (!IsWindowEnabled(infoPtr->hwndCombo)) return 0;
1420
1421 /* MSDN says: */
1422 /* "itemID - Specifies the menu item identifier for a menu */
1423 /* item or the index of the item in a list box or combo box. */
1424 /* For an empty list box or combo box, this member can be -1. */
1425 /* This allows the application to draw only the focus */
1426 /* rectangle at the coordinates specified by the rcItem */
1427 /* member even though there are no items in the control. */
1428 /* This indicates to the user whether the list box or combo */
1429 /* box has the focus. How the bits are set in the itemAction */
1430 /* member determines whether the rectangle is to be drawn as */
1431 /* though the list box or combo box has the focus. */
1432 if (dis->itemID == 0xffffffff) {
1433 if ( ( (dis->itemAction & ODA_FOCUS) && (dis->itemState & ODS_SELECTED)) ||
1434 ( (dis->itemAction & (ODA_SELECT | ODA_DRAWENTIRE)) && (dis->itemState & ODS_FOCUS) ) ) {
1435
1436 TRACE("drawing item -1 special focus, rect=(%d,%d)-(%d,%d)\n",
1437 dis->rcItem.left, dis->rcItem.top,
1438 dis->rcItem.right, dis->rcItem.bottom);
1439 }
1440 else if ((dis->CtlType == ODT_COMBOBOX) &&
1441 (dis->itemAction == ODA_DRAWENTIRE)) {
1442 /* draw of edit control data */
1443
1444 /* testing */
1445 {
1446 RECT exrc, cbrc, edrc;
1447 GetWindowRect (hwnd, &exrc);
1448 GetWindowRect (infoPtr->hwndCombo, &cbrc);
1449 edrc.left=edrc.top=edrc.right=edrc.bottom=-1;
1450 if (infoPtr->hwndEdit)
1451 GetWindowRect (infoPtr->hwndEdit, &edrc);
1452 TRACE("window rects ex=(%d,%d)-(%d,%d), cb=(%d,%d)-(%d,%d), ed=(%d,%d)-(%d,%d)\n",
1453 exrc.left, exrc.top, exrc.right, exrc.bottom,
1454 cbrc.left, cbrc.top, cbrc.right, cbrc.bottom,
1455 edrc.left, edrc.top, edrc.right, edrc.bottom);
1456 }
1457 }
1458 else {
1459 ERR("NOT drawing item -1 special focus, rect=(%d,%d)-(%d,%d), action=%08x, state=%08x\n",
1460 dis->rcItem.left, dis->rcItem.top,
1461 dis->rcItem.right, dis->rcItem.bottom,
1462 dis->itemAction, dis->itemState);
1463 return 0;
1464 }
1465 }
1466
1467 /* If draw item is -1 (edit control) setup the item pointer */
1468 if (dis->itemID == 0xffffffff) {
1469 CHAR str[260];
1470 INT wlen, alen;
1471
1472 if (!infoPtr->hwndEdit) {
1473 ERR("request to draw edit item, but no edit control exists!\n");
1474 return 0;
1475 }
1476
1477 item = infoPtr->edit;
1478 /* free previous text of edit item */
1479 if (item->pszText) {
1480 COMCTL32_Free(item->pszText);
1481 item->pszText = 0;
1482 item->mask &= ~CBEIF_TEXT;
1483 }
1484 alen = SendMessageA (infoPtr->hwndEdit, WM_GETTEXT, 260, (LPARAM)&str);
1485 TRACE("edit control hwndEdit=%0x, text len=%d str=<%s>\n",
1486 infoPtr->hwndEdit, alen, str);
1487 if (alen > 0) {
1488 item->mask |= CBEIF_TEXT;
1489 wlen = MultiByteToWideChar (CP_ACP, 0, str, -1, NULL, 0);
1490 if (wlen > 0) {
1491 item->pszText = (LPWSTR)COMCTL32_Alloc ((wlen + 1)*sizeof(WCHAR));
1492 MultiByteToWideChar (CP_ACP, 0, str, -1, item->pszText, wlen);
1493 }
1494 }
1495 }
1496
1497 /* if the item pointer is not set, then get the data and locate it */
1498 if (!item) {
1499 item = (CBE_ITEMDATA *)SendMessageW (infoPtr->hwndCombo,
1500 CB_GETITEMDATA, (WPARAM)dis->itemID, 0);
1501 if (item == (CBE_ITEMDATA *)CB_ERR)
1502 {
1503 FIXME("invalid item for id %d \n",dis->itemID);
1504 return 0;
1505 }
1506 }
1507
1508 /* dump the DRAWITEMSTRUCT if tracing "comboex" but not "message" */
1509 if (!TRACE_ON(message)) {
1510 TRACE("DRAWITEMSTRUCT: CtlType=0x%08x CtlID=0x%08x\n",
1511 dis->CtlType, dis->CtlID);
1512 TRACE("itemID=0x%08x itemAction=0x%08x itemState=0x%08x\n",
1513 dis->itemID, dis->itemAction, dis->itemState);
1514 TRACE("hWnd=0x%04x hDC=0x%04x (%d,%d)-(%d,%d) itemData=0x%08lx\n",
1515 dis->hwndItem, dis->hDC, dis->rcItem.left,
1516 dis->rcItem.top, dis->rcItem.right, dis->rcItem.bottom,
1517 dis->itemData);
1518 }
1519 COMBOEX_DumpItem (item);
1520
1521 xbase = CBE_STARTOFFSET;
1522 if ((item->mask & CBEIF_INDENT) && (dis->itemState & ODS_COMBOEXLBOX))
1523 xbase += (item->iIndent * CBE_INDENT);
1524 if (item->mask & CBEIF_IMAGE) {
1525 ImageList_GetImageInfo(infoPtr->himl, item->iImage, &iinfo);
1526 xioff = (iinfo.rcImage.right - iinfo.rcImage.left + CBE_SEP);
1527 }
1528
1529 switch (dis->itemAction) {
1530 case ODA_FOCUS:
1531 if (dis->itemState & ODS_SELECTED /*1*/) {
1532 if ((item->mask & CBEIF_TEXT) && item->pszText) {
1533 RECT rect2;
1534
1535 len = strlenW (item->pszText);
1536 GetTextExtentPointW (dis->hDC, item->pszText, len, &txtsize);
1537 rect.left = xbase + xioff - 1;
1538 rect.right = rect.left + txtsize.cx + 2;
1539 rect.top = dis->rcItem.top;
1540 rect.bottom = dis->rcItem.bottom;
1541 GetClipBox (dis->hDC, &rect2);
1542 TRACE("drawing item %d focus, rect=(%d,%d)-(%d,%d)\n",
1543 dis->itemID, rect.left, rect.top,
1544 rect.right, rect.bottom);
1545 TRACE(" clip=(%d,%d)-(%d,%d)\n",
1546 rect2.left, rect2.top,
1547 rect2.right, rect2.bottom);
1548
1549 DrawFocusRect(dis->hDC, &rect);
1550 }
1551 else {
1552 FIXME("ODA_FOCUS and ODS_SELECTED but no text\n");
1553 }
1554 }
1555 else {
1556 FIXME("ODA_FOCUS but not ODS_SELECTED\n");
1557 }
1558 break;
1559 case ODA_SELECT:
1560 case ODA_DRAWENTIRE:
1561 drawimage = -1;
1562 drawstate = ILD_NORMAL;
1563 if (!(infoPtr->dwExtStyle & CBES_EX_NOEDITIMAGE)) {
1564 if (item->mask & CBEIF_IMAGE)
1565 drawimage = item->iImage;
1566 if (dis->itemState & ODS_COMBOEXLBOX) {
1567 /* drawing listbox entry */
1568 if (dis->itemState & ODS_SELECTED) {
1569 if (item->mask & CBEIF_SELECTEDIMAGE)
1570 drawimage = item->iSelectedImage;
1571 drawstate = ILD_SELECTED;
1572 }
1573 }
1574 else {
1575 /* drawing combo/edit entry */
1576 if (infoPtr->hwndEdit) {
1577 /* if we have an edit control, the slave the
1578 * selection state to the Edit focus state
1579 */
1580 if (infoPtr->flags & WCBE_EDITFOCUSED) {
1581 if (item->mask & CBEIF_SELECTEDIMAGE)
1582 drawimage = item->iSelectedImage;
1583 drawstate = ILD_SELECTED;
1584 }
1585 }
1586 else {
1587 /* if we don't have an edit control, use
1588 * the requested state.
1589 */
1590 if (dis->itemState & ODS_SELECTED) {
1591 if (item->mask & CBEIF_SELECTEDIMAGE)
1592 drawimage = item->iSelectedImage;
1593 drawstate = ILD_SELECTED;
1594 }
1595 }
1596 }
1597 }
1598 if (drawimage != -1) {
1599 TRACE("drawing image state=%d\n", dis->itemState & ODS_SELECTED);
1600 ImageList_Draw (infoPtr->himl, drawimage, dis->hDC,
1601 xbase, dis->rcItem.top, drawstate);
1602 }
1603 if ((item->mask & CBEIF_TEXT) && item->pszText) {
1604 UINT x, y;
1605 COLORREF nbkc, ntxc;
1606
1607 len = lstrlenW (item->pszText);
1608 GetTextExtentPointW (dis->hDC, item->pszText, len, &txtsize);
1609 nbkc = GetSysColor ((dis->itemState & ODS_SELECTED) ?
1610 COLOR_HIGHLIGHT : COLOR_WINDOW);
1611 SetBkColor (dis->hDC, nbkc);
1612 ntxc = GetSysColor ((dis->itemState & ODS_SELECTED) ?
1613 COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT);
1614 SetTextColor (dis->hDC, ntxc);
1615 x = xbase + xioff;
1616 y = dis->rcItem.top +
1617 (dis->rcItem.bottom - dis->rcItem.top - txtsize.cy) / 2;
1618 rect.left = x;
1619 rect.right = x + txtsize.cx;
1620 rect.top = dis->rcItem.top + 1;
1621 rect.bottom = dis->rcItem.bottom - 1;
1622 TRACE("drawing item %d text, rect=(%d,%d)-(%d,%d)\n",
1623 dis->itemID, rect.left, rect.top, rect.right, rect.bottom);
1624 ExtTextOutW (dis->hDC, x, y, ETO_OPAQUE | ETO_CLIPPED,
1625 &rect, item->pszText, len, 0);
1626 if (dis->itemState & ODS_FOCUS) {
1627 rect.top -= 1;
1628 rect.bottom += 1;
1629 rect.left -= 1;
1630 rect.right += 1;
1631 TRACE("drawing item %d focus after text, rect=(%d,%d)-(%d,%d)\n",
1632 dis->itemID, rect.left, rect.top, rect.right, rect.bottom);
1633 DrawFocusRect (dis->hDC, &rect);
1634 }
1635 }
1636 break;
1637 default:
1638 FIXME("unknown action hwnd=%08x, wparam=%08x, lparam=%08lx, action=%d\n",
1639 hwnd, wParam, lParam, dis->itemAction);
1640 }
1641
1642 return 0;
1643}
1644
1645
1646static LRESULT
1647COMBOEX_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
1648{
1649 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
1650
1651 if (infoPtr->hwndCombo)
1652 DestroyWindow (infoPtr->hwndCombo);
1653
1654 if (infoPtr->edit) {
1655 COMCTL32_Free (infoPtr->edit);
1656 infoPtr->edit = 0;
1657 }
1658
1659 if (infoPtr->items) {
1660 CBE_ITEMDATA *this, *next;
1661
1662 this = infoPtr->items;
1663 while (this) {
1664 next = (CBE_ITEMDATA *)this->next;
1665 if ((this->mask & CBEIF_TEXT) && this->pszText)
1666 COMCTL32_Free (this->pszText);
1667 COMCTL32_Free (this);
1668 this = next;
1669 }
1670 }
1671
1672 DeleteObject (infoPtr->font);
1673
1674 /* free comboex info data */
1675 COMCTL32_Free (infoPtr);
1676 SetWindowLongA (hwnd, 0, 0);
1677 return 0;
1678}
1679
1680
1681static LRESULT
1682COMBOEX_MeasureItem (HWND hwnd, WPARAM wParam, LPARAM lParam)
1683{
1684 /*COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);*/
1685 MEASUREITEMSTRUCT *mis = (MEASUREITEMSTRUCT *) lParam;
1686 HDC hdc;
1687 SIZE mysize;
1688
1689 hdc = GetDC (0);
1690 GetTextExtentPointA (hdc, "W", 1, &mysize);
1691 ReleaseDC (0, hdc);
1692 mis->itemHeight = mysize.cy + CBE_EXTRA;
1693
1694 TRACE("adjusted height hwnd=%08x, height=%d\n",
1695 hwnd, mis->itemHeight);
1696
1697 return 0;
1698}
1699
1700
1701static LRESULT
1702COMBOEX_NCCreate (HWND hwnd, WPARAM wParam, LPARAM lParam)
1703{
1704 /* WARNING: The COMBOEX_INFO structure is not yet created */
1705 DWORD oldstyle, newstyle;
1706
1707 oldstyle = (DWORD)GetWindowLongA (hwnd, GWL_STYLE);
1708 newstyle = oldstyle & ~(WS_VSCROLL | WS_HSCROLL);
1709 if (newstyle != oldstyle) {
1710 TRACE("req style %08lx, reseting style %08lx\n",
1711 oldstyle, newstyle);
1712 SetWindowLongA (hwnd, GWL_STYLE, newstyle);
1713 }
1714 return 1;
1715}
1716
1717
1718static LRESULT
1719COMBOEX_Size (HWND hwnd, WPARAM wParam, LPARAM lParam)
1720{
1721 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
1722 RECT rect;
1723
1724 GetWindowRect (hwnd, &rect);
1725 TRACE("my rect (%d,%d)-(%d,%d)\n",
1726 rect.left, rect.top, rect.right, rect.bottom);
1727
1728 MoveWindow (infoPtr->hwndCombo, 0, 0, rect.right -rect.left,
1729 rect.bottom - rect.top, TRUE);
1730
1731 COMBOEX_AdjustEditPos (infoPtr);
1732
1733 return 0;
1734}
1735
1736
1737static LRESULT
1738COMBOEX_WindowPosChanging (HWND hwnd, WPARAM wParam, LPARAM lParam)
1739{
1740 COMBOEX_INFO *infoPtr = COMBOEX_GetInfoPtr (hwnd);
1741 LRESULT ret;
1742 RECT cbx_wrect, cbx_crect, cb_wrect;
1743 UINT width, height;
1744 WINDOWPOS *wp = (WINDOWPOS *)lParam;
1745
1746 ret = DefWindowProcA (hwnd, WM_WINDOWPOSCHANGING, wParam, lParam);
1747 GetWindowRect (hwnd, &cbx_wrect);
1748 GetClientRect (hwnd, &cbx_crect);
1749 GetWindowRect (infoPtr->hwndCombo, &cb_wrect);
1750
1751 /* width is winpos value + border width of comboex */
1752 width = wp->cx
1753 + (cbx_wrect.right-cbx_wrect.left)
1754 - (cbx_crect.right-cbx_crect.left);
1755
1756 TRACE("winpos=(%d,%d %dx%d) flags=0x%08x\n",
1757 wp->x, wp->y, wp->cx, wp->cy, wp->flags);
1758 TRACE("EX window=(%d,%d)-(%d,%d), client=(%d,%d)-(%d,%d)\n",
1759 cbx_wrect.left, cbx_wrect.top, cbx_wrect.right, cbx_wrect.bottom,
1760 cbx_crect.left, cbx_crect.top, cbx_crect.right, cbx_crect.bottom);
1761 TRACE("CB window=(%d,%d)-(%d,%d), EX setting=(0,0)-(%d,%d)\n",
1762 cb_wrect.left, cb_wrect.top, cb_wrect.right, cb_wrect.bottom,
1763 width, cb_wrect.bottom-cb_wrect.top);
1764
1765 if (width) SetWindowPos (infoPtr->hwndCombo, HWND_TOP, 0, 0,
1766 width,
1767 cb_wrect.bottom-cb_wrect.top,
1768 SWP_NOACTIVATE);
1769
1770 GetWindowRect (infoPtr->hwndCombo, &cb_wrect);
1771
1772 /* height is combo window height plus border width of comboex */
1773 height = (cb_wrect.bottom-cb_wrect.top)
1774 + (cbx_wrect.bottom-cbx_wrect.top)
1775 - (cbx_crect.bottom-cbx_crect.top);
1776 if (wp->cy < height) wp->cy = height;
1777 if (infoPtr->hwndEdit) {
1778 COMBOEX_AdjustEditPos (infoPtr);
1779 InvalidateRect (infoPtr->hwndCombo, 0, TRUE);
1780 }
1781
1782 return 0;
1783}
1784
1785
1786static LRESULT WINAPI
1787COMBOEX_EditWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1788{
1789 COMBOEX_INFO *infoPtr = (COMBOEX_INFO *)GetPropA (hwnd, (LPCSTR)(LONG) ComboExInfo);
1790 NMCBEENDEDITA cbeend;
1791 COLORREF nbkc, obkc;
1792 HDC hDC;
1793 RECT rect;
1794 LRESULT lret;
1795
1796 TRACE("hwnd=%x msg=%x wparam=%x lParam=%lx, info_ptr=%p\n",
1797 hwnd, uMsg, wParam, lParam, infoPtr);
1798
1799 if (!infoPtr) return 0;
1800
1801 switch (uMsg)
1802 {
1803
1804 case WM_CHAR:
1805 /* handle (ignore) the return character */
1806 if (wParam == VK_RETURN) return 0;
1807 /* all other characters pass into the real Edit */
1808 return CallWindowProcA (infoPtr->prevEditWndProc,
1809 hwnd, uMsg, wParam, lParam);
1810
1811 case WM_ERASEBKGND:
1812 /*
1813 * The following was determined by traces of the native
1814 */
1815 hDC = (HDC) wParam;
1816 nbkc = GetSysColor (COLOR_WINDOW);
1817 obkc = SetBkColor (hDC, nbkc);
1818 GetClientRect (hwnd, &rect);
1819 TRACE("erasing (%d,%d)-(%d,%d)\n",
1820 rect.left, rect.top, rect.right, rect.bottom);
1821 ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0);
1822 SetBkColor (hDC, obkc);
1823 return CallWindowProcA (infoPtr->prevEditWndProc,
1824 hwnd, uMsg, wParam, lParam);
1825
1826 case WM_KEYDOWN: {
1827 INT oldItem, selected;
1828 CBE_ITEMDATA *item;
1829 WCHAR edit_text[260];
1830
1831 switch ((INT)wParam)
1832 {
1833 case VK_ESCAPE:
1834 /* native version seems to do following for COMBOEX */
1835 /*
1836 * GetWindowTextA(Edit,&?, 0x104) x
1837 * CB_GETCURSEL to Combo rets -1 x
1838 * WM_NOTIFY to COMBOEX parent (rebar) x
1839 * (CBEN_ENDEDIT{A|W}
1840 * fChanged = FALSE x
1841 * inewSelection = -1 x
1842 * txt="www.hoho" x
1843 * iWhy = 3 x
1844 * CB_GETCURSEL to Combo rets -1 x
1845 * InvalidateRect(Combo, 0) x
1846 * WM_SETTEXT to Edit x
1847 * EM_SETSEL to Edit (0,0) x
1848 * EM_SETSEL to Edit (0,-1) x
1849 * RedrawWindow(Combo, 0, 0, 5) x
1850 */
1851 TRACE("special code for VK_ESCAPE\n");
1852
1853 GetWindowTextA (infoPtr->hwndEdit, cbeend.szText, 260);
1854
1855 infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG);
1856 cbeend.fChanged = FALSE;
1857 cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo,
1858 CB_GETCURSEL, 0, 0);
1859 cbeend.iWhy = CBENF_ESCAPE;
1860
1861 if (COMBOEX_Notify (infoPtr, CBEN_ENDEDITA,
1862 (NMHDR *)&cbeend, FALSE)) {
1863 /* abort the change */
1864 TRACE("Notify requested abort of change\n");
1865 return 0;
1866 }
1867 oldItem = SendMessageW (infoPtr->hwndCombo,CB_GETCURSEL, 0, 0);
1868 InvalidateRect (infoPtr->hwndCombo, 0, 0);
1869 if (!(item = COMBOEX_FindItem(infoPtr, oldItem))) {
1870 ERR("item %d not found. Problem!\n", oldItem);
1871 break;
1872 }
1873 infoPtr->selected = oldItem;
1874 COMBOEX_SetEditText (infoPtr, item);
1875 RedrawWindow (infoPtr->hwndCombo, 0, 0, RDW_ERASE |
1876 RDW_INVALIDATE);
1877 break;
1878
1879 case VK_RETURN:
1880 /* native version seems to do following for COMBOEX */
1881 /*
1882 * GetWindowTextA(Edit,&?, 0x104) x
1883 * CB_GETCURSEL to Combo rets -1 x
1884 * CB_GETCOUNT to Combo rets 0
1885 * if >0 loop
1886 * CB_GETITEMDATA to match
1887 * *** above 3 lines simulated by FindItem x
1888 * WM_NOTIFY to COMBOEX parent (rebar) x
1889 * (CBEN_ENDEDIT{A|W} x
1890 * fChanged = TRUE (-1) x
1891 * iNewSelection = -1 or selected x
1892 * txt= x
1893 * iWhy = 2 (CBENF_RETURN) x
1894 * CB_GETCURSEL to Combo rets -1 x
1895 * if -1 send CB_SETCURSEL to Combo -1 x
1896 * InvalidateRect(Combo, 0, 0) x
1897 * SetFocus(Edit) x
1898 * CallWindowProc(406615a8, Edit, 0x100, 0xd, 0x1c0001)
1899 */
1900
1901 TRACE("special code for VK_RETURN\n");
1902
1903 GetWindowTextW (infoPtr->hwndEdit, edit_text, 260);
1904
1905 infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG);
1906 selected = SendMessageW (infoPtr->hwndCombo,
1907 CB_GETCURSEL, 0, 0);
1908
1909 if (selected != -1) {
1910 item = COMBOEX_FindItem (infoPtr, selected);
1911 TRACE("handling VK_RETURN, selected = %d, selected_text=%s\n",
1912 selected, debugstr_w(item->pszText));
1913 TRACE("handling VK_RETURN, edittext=%s\n",
1914 debugstr_w(edit_text));
1915 if (lstrcmpiW (item->pszText, edit_text)) {
1916 /* strings not equal -- indicate edit has changed */
1917 selected = -1;
1918 }
1919 }
1920
1921 cbeend.iNewSelection = selected;
1922 cbeend.fChanged = TRUE;
1923 cbeend.iWhy = CBENF_RETURN;
1924 WideCharToMultiByte (CP_ACP, 0, edit_text, -1,
1925 cbeend.szText, sizeof(cbeend.szText),
1926 NULL, NULL);
1927
1928 if (COMBOEX_Notify (infoPtr, CBEN_ENDEDITA,
1929 (NMHDR *)&cbeend, FALSE)) {
1930 /* abort the change, restore previous */
1931 TRACE("Notify requested abort of change\n");
1932 COMBOEX_SetEditText (infoPtr, infoPtr->edit);
1933 RedrawWindow (infoPtr->hwndCombo, 0, 0, RDW_ERASE |
1934 RDW_INVALIDATE);
1935 return 0;
1936 }
1937 oldItem = SendMessageW (infoPtr->hwndCombo,CB_GETCURSEL, 0, 0);
1938 if (oldItem != -1) {
1939 /* if something is selected, then deselect it */
1940 SendMessageW (infoPtr->hwndCombo, CB_SETCURSEL,
1941 (WPARAM)-1, 0);
1942 }
1943 InvalidateRect (infoPtr->hwndCombo, 0, 0);
1944 SetFocus(infoPtr->hwndEdit);
1945 break;
1946
1947 default:
1948 return CallWindowProcA (infoPtr->prevEditWndProc,
1949 hwnd, uMsg, wParam, lParam);
1950 }
1951 return 0;
1952 }
1953
1954 case WM_SETFOCUS:
1955 /* remember the focus to set state of icon */
1956 lret = CallWindowProcA (infoPtr->prevEditWndProc,
1957 hwnd, uMsg, wParam, lParam);
1958 infoPtr->flags |= WCBE_EDITFOCUSED;
1959 return lret;
1960
1961 case WM_KILLFOCUS:
1962 /*
1963 * do NOTIFY CBEN_ENDEDIT with CBENF_KILLFOCUS
1964 */
1965 infoPtr->flags &= ~WCBE_EDITFOCUSED;
1966 if (infoPtr->flags & WCBE_ACTEDIT) {
1967 infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG);
1968 cbeend.fChanged = FALSE;
1969 cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo,
1970 CB_GETCURSEL, 0, 0);
1971 cbeend.iWhy = CBENF_KILLFOCUS;
1972
1973 COMBOEX_Notify (infoPtr, CBEN_ENDEDITA,
1974 (NMHDR *)&cbeend, FALSE);
1975 }
1976 /* fall through */
1977
1978 default:
1979 return CallWindowProcA (infoPtr->prevEditWndProc,
1980 hwnd, uMsg, wParam, lParam);
1981 }
1982 return 0;
1983}
1984
1985
1986static LRESULT WINAPI
1987COMBOEX_ComboWndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1988{
1989 COMBOEX_INFO *infoPtr = (COMBOEX_INFO *)GetPropA (hwnd, (LPCSTR)(LONG) ComboExInfo);
1990 NMCBEENDEDITA cbeend;
1991 NMMOUSE nmmse;
1992 COLORREF nbkc, obkc;
1993 HDC hDC;
1994 HWND focusedhwnd;
1995 RECT rect;
1996
1997 TRACE("hwnd=%x msg=%x wparam=%x lParam=%lx, info_ptr=%p\n",
1998 hwnd, uMsg, wParam, lParam, infoPtr);
1999
2000 if (!infoPtr) return 0;
2001
2002 switch (uMsg)
2003 {
2004
2005 case CB_FINDSTRINGEXACT:
2006 return COMBOEX_FindStringExact (infoPtr, wParam, lParam);
2007
2008 case WM_DRAWITEM:
2009 /*
2010 * The only way this message should come is from the
2011 * child Listbox issuing the message. Flag this so
2012 * that ComboEx knows this is listbox.
2013 */
2014 ((DRAWITEMSTRUCT *)lParam)->itemState |= ODS_COMBOEXLBOX;
2015 return CallWindowProcA (infoPtr->prevComboWndProc,
2016 hwnd, uMsg, wParam, lParam);
2017
2018 case WM_ERASEBKGND:
2019 /*
2020 * The following was determined by traces of the native
2021 */
2022 hDC = (HDC) wParam;
2023 nbkc = GetSysColor (COLOR_WINDOW);
2024 obkc = SetBkColor (hDC, nbkc);
2025 GetClientRect (hwnd, &rect);
2026 TRACE("erasing (%d,%d)-(%d,%d)\n",
2027 rect.left, rect.top, rect.right, rect.bottom);
2028 ExtTextOutW (hDC, 0, 0, ETO_OPAQUE, &rect, 0, 0, 0);
2029 SetBkColor (hDC, obkc);
2030 return CallWindowProcA (infoPtr->prevComboWndProc,
2031 hwnd, uMsg, wParam, lParam);
2032
2033 case WM_SETCURSOR:
2034 /*
2035 * WM_NOTIFY to comboex parent (rebar)
2036 * with NM_SETCURSOR with extra words of 0,0,0,0,0x02010001
2037 * CallWindowProc (previous)
2038 */
2039 nmmse.dwItemSpec = 0;
2040 nmmse.dwItemData = 0;
2041 nmmse.pt.x = 0;
2042 nmmse.pt.y = 0;
2043 nmmse.dwHitInfo = lParam;
2044 COMBOEX_Notify (infoPtr, NM_SETCURSOR, (NMHDR *)&nmmse, FALSE);
2045 return CallWindowProcA (infoPtr->prevComboWndProc,
2046 hwnd, uMsg, wParam, lParam);
2047
2048 case WM_COMMAND:
2049 switch (HIWORD(wParam)) {
2050
2051 case EN_UPDATE:
2052 /* traces show that COMBOEX does not issue CBN_EDITUPDATE
2053 * on the EN_UPDATE
2054 */
2055 return 0;
2056
2057 case EN_KILLFOCUS:
2058 /*
2059 * Native does:
2060 *
2061 * GetFocus() retns AA
2062 * GetWindowTextA(Edit)
2063 * CB_GETCURSEL(Combo) (got -1)
2064 * WM_NOTIFY(CBEN_ENDEDITA) with CBENF_KILLFOCUS
2065 * CB_GETCURSEL(Combo) (got -1)
2066 * InvalidateRect(Combo, 0, 0)
2067 * WM_KILLFOCUS(Combo, AA)
2068 * return 0;
2069 */
2070 focusedhwnd = GetFocus();
2071 if (infoPtr->flags & WCBE_ACTEDIT) {
2072 GetWindowTextA (infoPtr->hwndEdit, cbeend.szText, 260);
2073 cbeend.fChanged = (infoPtr->flags & WCBE_EDITCHG);
2074 cbeend.iNewSelection = SendMessageW (infoPtr->hwndCombo,
2075 CB_GETCURSEL, 0, 0);
2076 cbeend.iWhy = CBENF_KILLFOCUS;
2077
2078 infoPtr->flags &= ~(WCBE_ACTEDIT | WCBE_EDITCHG);
2079 if (COMBOEX_Notify (infoPtr, CBEN_ENDEDITA,
2080 (NMHDR *)&cbeend, FALSE)) {
2081 /* abort the change */
2082 TRACE("Notify requested abort of change\n");
2083 return 0;
2084 }
2085 }
2086 /* possible CB_GETCURSEL */
2087 InvalidateRect (infoPtr->hwndCombo, 0, 0);
2088 if (focusedhwnd)
2089 SendMessageW (infoPtr->hwndCombo, WM_KILLFOCUS,
2090 (WPARAM)focusedhwnd, 0);
2091 return 0;
2092
2093 case EN_SETFOCUS: {
2094 /*
2095 * For EN_SETFOCUS this issues the same calls and messages
2096 * as the native seems to do.
2097 *
2098 * for some cases however native does the following:
2099 * (noticed after SetFocus during LBUTTONDOWN on
2100 * on dropdown arrow)
2101 * WM_GETTEXTLENGTH (Edit);
2102 * WM_GETTEXT (Edit, len+1, str);
2103 * EM_SETSEL (Edit, 0, 0);
2104 * WM_GETTEXTLENGTH (Edit);
2105 * WM_GETTEXT (Edit, len+1, str);
2106 * EM_SETSEL (Edit, 0, len);
2107 * WM_NOTIFY (parent, CBEN_BEGINEDIT)
2108 */
2109 NMHDR hdr;
2110
2111 SendMessageW (infoPtr->hwndEdit, EM_SETSEL, 0, 0);
2112 SendMessageW (infoPtr->hwndEdit, EM_SETSEL, 0, -1);
2113 COMBOEX_Notify (infoPtr, CBEN_BEGINEDIT, &hdr, FALSE);
2114 infoPtr->flags |= WCBE_ACTEDIT;
2115 infoPtr->flags &= ~WCBE_EDITCHG; /* no change yet */
2116 return 0;
2117 }
2118
2119 case EN_CHANGE: {
2120 /*
2121 * For EN_CHANGE this issues the same calls and messages
2122 * as the native seems to do.
2123 */
2124 WCHAR edit_text[260];
2125 WCHAR *lastwrk;
2126 INT selected, cnt;
2127 CBE_ITEMDATA *item;
2128
2129 selected = SendMessageW (infoPtr->hwndCombo,
2130 CB_GETCURSEL, 0, 0);
2131
2132 /* lstrlenA( lastworkingURL ) */
2133
2134 GetWindowTextW (infoPtr->hwndEdit, edit_text, 260);
2135 if (selected == -1) {
2136 lastwrk = infoPtr->edit->pszText;
2137 cnt = lstrlenW (lastwrk);
2138 if (cnt >= 259) cnt = 259;
2139 }
2140 else {
2141 item = COMBOEX_FindItem (infoPtr, selected);
2142 cnt = lstrlenW (item->pszText);
2143 lastwrk = item->pszText;
2144 if (cnt >= 259) cnt = 259;
2145 }
2146
2147 TRACE("handling EN_CHANGE, selected = %d, selected_text=%s\n",
2148 selected, debugstr_w(lastwrk));
2149 TRACE("handling EN_CHANGE, edittext=%s\n",
2150 debugstr_w(edit_text));
2151
2152 /* lstrcmpiW is between lastworkingURL and GetWindowText */
2153
2154 if (lstrcmpiW (lastwrk, edit_text)) {
2155 /* strings not equal -- indicate edit has changed */
2156 infoPtr->flags |= WCBE_EDITCHG;
2157 }
2158 SendMessageW ( GetParent(infoPtr->hwndSelf), WM_COMMAND,
2159 MAKEWPARAM(GetDlgCtrlID (infoPtr->hwndSelf),
2160 CBN_EDITCHANGE),
2161 infoPtr->hwndSelf);
2162 return 0;
2163 }
2164
2165 case LBN_SELCHANGE:
2166 /*
2167 * Therefore from traces there is no additional code here
2168 */
2169
2170 /*
2171 * Using native COMCTL32 gets the following:
2172 * 1 == SHDOCVW.DLL issues call/message
2173 * 2 == COMCTL32.DLL issues call/message
2174 * 3 == WINE issues call/message
2175 *
2176 *
2177 * for LBN_SELCHANGE:
2178 * 1 CB_GETCURSEL(ComboEx)
2179 * 1 CB_GETDROPPEDSTATE(ComboEx)
2180 * 1 CallWindowProc( *2* for WM_COMMAND(LBN_SELCHANGE)
2181 * 2 CallWindowProc( *3* for WM_COMMAND(LBN_SELCHANGE)
2182 ** call CBRollUp( xxx, TRUE for LBN_SELCHANGE, TRUE)
2183 * 3 WM_COMMAND(ComboEx, CBN_SELENDOK)
2184 * WM_USER+49(ComboLB, 1,0) <=============!!!!!!!!!!!
2185 * 3 ShowWindow(ComboLB, SW_HIDE)
2186 * 3 RedrawWindow(Combo, RDW_UPDATENOW)
2187 * 3 WM_COMMAND(ComboEX, CBN_CLOSEUP)
2188 ** end of CBRollUp
2189 * 3 WM_COMMAND(ComboEx, CBN_SELCHANGE) (echo to parent)
2190 * ? LB_GETCURSEL <==|
2191 * ? LB_GETTEXTLEN |
2192 * ? LB_GETTEXT | Needs to be added to
2193 * ? WM_CTLCOLOREDIT(ComboEx) | Combo processing
2194 * ? LB_GETITEMDATA |
2195 * ? WM_DRAWITEM(ComboEx) <==|
2196 */
2197 default:
2198 break;
2199 }/* fall through */
2200 default:
2201 return CallWindowProcA (infoPtr->prevComboWndProc,
2202 hwnd, uMsg, wParam, lParam);
2203 }
2204 return 0;
2205}
2206
2207
2208static LRESULT WINAPI
2209COMBOEX_WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
2210{
2211 TRACE("hwnd=%x msg=%x wparam=%x lParam=%lx\n", hwnd, uMsg, wParam, lParam);
2212
2213 if (!COMBOEX_GetInfoPtr (hwnd)) {
2214 if (uMsg == WM_CREATE)
2215 return COMBOEX_Create (hwnd, wParam, lParam);
2216 if (uMsg == WM_NCCREATE)
2217 COMBOEX_NCCreate (hwnd, wParam, lParam);
2218 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2219 }
2220
2221 switch (uMsg)
2222 {
2223 case CBEM_DELETEITEM: /* maps to CB_DELETESTRING */
2224 return COMBOEX_DeleteItem (hwnd, wParam, lParam);
2225
2226 case CBEM_GETCOMBOCONTROL:
2227 return COMBOEX_GetComboControl (hwnd, wParam, lParam);
2228
2229 case CBEM_GETEDITCONTROL:
2230 return COMBOEX_GetEditControl (hwnd, wParam, lParam);
2231
2232 case CBEM_GETEXTENDEDSTYLE:
2233 return COMBOEX_GetExtendedStyle (hwnd, wParam, lParam);
2234
2235 case CBEM_GETIMAGELIST:
2236 return COMBOEX_GetImageList (hwnd, wParam, lParam);
2237
2238 case CBEM_GETITEMA:
2239 return COMBOEX_GetItemA (hwnd, wParam, lParam);
2240
2241 case CBEM_GETITEMW:
2242 return COMBOEX_GetItemW (hwnd, wParam, lParam);
2243
2244 case CBEM_GETUNICODEFORMAT:
2245 return COMBOEX_GetUnicodeFormat (hwnd, wParam, lParam);
2246
2247 case CBEM_HASEDITCHANGED:
2248 return COMBOEX_HasEditChanged (hwnd, wParam, lParam);
2249
2250 case CBEM_INSERTITEMA:
2251 return COMBOEX_InsertItemA (hwnd, wParam, lParam);
2252
2253 case CBEM_INSERTITEMW:
2254 return COMBOEX_InsertItemW (hwnd, wParam, lParam);
2255
2256 case CBEM_SETEXSTYLE: /* FIXME: obsoleted, should be the same as: */
2257 case CBEM_SETEXTENDEDSTYLE:
2258 return COMBOEX_SetExtendedStyle (hwnd, wParam, lParam);
2259
2260 case CBEM_SETIMAGELIST:
2261 return COMBOEX_SetImageList (hwnd, wParam, lParam);
2262
2263 case CBEM_SETITEMA:
2264 return COMBOEX_SetItemA (hwnd, wParam, lParam);
2265
2266 case CBEM_SETITEMW:
2267 return COMBOEX_SetItemW (hwnd, wParam, lParam);
2268
2269 case CBEM_SETUNICODEFORMAT:
2270 return COMBOEX_SetUnicodeFormat (hwnd, wParam, lParam);
2271
2272
2273/* Combo messages we are not sure if we need to process or just forward */
2274 case CB_GETDROPPEDCONTROLRECT:
2275 case CB_GETITEMHEIGHT:
2276 case CB_GETLBTEXT:
2277 case CB_GETLBTEXTLEN:
2278 case CB_GETEXTENDEDUI:
2279 case CB_LIMITTEXT:
2280 case CB_RESETCONTENT:
2281 case CB_SELECTSTRING:
2282 case WM_SETTEXT:
2283 case WM_GETTEXT:
2284 FIXME("(0x%x 0x%x 0x%lx): possibly missing function\n",
2285 uMsg, wParam, lParam);
2286 return COMBOEX_Forward (hwnd, uMsg, wParam, lParam);
2287
2288/* Combo messages OK to just forward to the regular COMBO */
2289 case CB_GETCOUNT:
2290 case CB_GETCURSEL:
2291 case CB_GETDROPPEDSTATE:
2292 case CB_SETDROPPEDWIDTH:
2293 case CB_SETEXTENDEDUI:
2294 case CB_SHOWDROPDOWN:
2295 return COMBOEX_Forward (hwnd, uMsg, wParam, lParam);
2296
2297/* Combo messages we need to process specially */
2298 case CB_FINDSTRINGEXACT:
2299 return COMBOEX_FindStringExact (COMBOEX_GetInfoPtr (hwnd),
2300 wParam, lParam);
2301
2302 case CB_GETITEMDATA:
2303 return COMBOEX_GetItemData (hwnd, wParam, lParam);
2304
2305 case CB_SETCURSEL:
2306 return COMBOEX_SetCursel (hwnd, wParam, lParam);
2307
2308 case CB_SETITEMDATA:
2309 return COMBOEX_SetItemData (hwnd, wParam, lParam);
2310
2311 case CB_SETITEMHEIGHT:
2312 return COMBOEX_SetItemHeight (hwnd, wParam, lParam);
2313
2314
2315
2316/* Window messages passed to parent */
2317 case WM_COMMAND:
2318 return COMBOEX_Command (hwnd, wParam, lParam);
2319
2320 case WM_NOTIFY:
2321 return SendMessageA (GetParent (hwnd), uMsg, wParam, lParam);
2322
2323
2324/* Window messages we need to process */
2325 case WM_DELETEITEM:
2326 return COMBOEX_WM_DeleteItem (hwnd, wParam, lParam);
2327
2328 case WM_DRAWITEM:
2329 return COMBOEX_DrawItem (hwnd, wParam, lParam);
2330
2331 case WM_DESTROY:
2332 return COMBOEX_Destroy (hwnd, wParam, lParam);
2333
2334 case WM_MEASUREITEM:
2335 return COMBOEX_MeasureItem (hwnd, wParam, lParam);
2336
2337 case WM_SIZE:
2338 return COMBOEX_Size (hwnd, wParam, lParam);
2339
2340 case WM_WINDOWPOSCHANGING:
2341 return COMBOEX_WindowPosChanging (hwnd, wParam, lParam);
2342
2343 default:
2344 if (uMsg >= WM_USER)
2345 ERR("unknown msg %04x wp=%08x lp=%08lx\n",
2346 uMsg, wParam, lParam);
2347#ifdef __WIN32OS2__
2348 return defComCtl32ProcA (hwnd, uMsg, wParam, lParam);
2349#else
2350 return DefWindowProcA (hwnd, uMsg, wParam, lParam);
2351#endif
2352 }
2353 return 0;
2354}
2355
2356
2357VOID
2358COMBOEX_Register (void)
2359{
2360 WNDCLASSA wndClass;
2361
2362 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
2363 wndClass.style = CS_GLOBALCLASS;
2364 wndClass.lpfnWndProc = (WNDPROC)COMBOEX_WindowProc;
2365 wndClass.cbClsExtra = 0;
2366 wndClass.cbWndExtra = sizeof(COMBOEX_INFO *);
2367 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
2368 wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2369 wndClass.lpszClassName = WC_COMBOBOXEXA;
2370
2371 RegisterClassA (&wndClass);
2372
2373 ComboExInfo = GlobalAddAtomA("CC32SubclassInfo");
2374}
2375
2376
2377VOID
2378COMBOEX_Unregister (void)
2379{
2380 UnregisterClassA (WC_COMBOBOXEXA, (HINSTANCE)NULL);
2381}
2382
Note: See TracBrowser for help on using the repository browser.