1 /* ComboBox Control Test for ReactOS.
2 
3 * This is a test program. Not made to be fast, small
4 * easy to mantain, or portable.
5 
6 * I'm not erasing text because I don't want to use other functions from the API
7 * or make this more complex. Also Fonts are not heavily used.
8 
9 * This source code is in the PUBLIC DOMAIN and has NO WARRANTY.
10 * by Waldo Alvarez Ca�izares <wac at ghost.matcom.uh.cu>, started July 11, 2003. */
11 
12 //#define WIN32_LEAN_AND_MEAN
13 #include <windows.h>
14 #include "utils.h"
15 
16 #define CONTROLCLASS  "COMBOBOX"  /* the class name */
17 #define CONTROLCLASSW L"COMBOBOX" /* the class name in unicode*/
18 
19 #define WINDOWWIDTH 560
20 #define WINDOWHEIGHT 350
21 
22 /* --- Command IDs of some buttons --- */
23 #define CREATEWINDOW_ID 106
24 #define CREATEWINDOWEX_ID 107
25 #define CREATEWINDOWW_ID 108
26 #define INITPAGE_ID 400
27 #define SECONDPAGE_ID 401
28 #define BACKFIRSTPAGE_ID 402
29 
30 /* --- Position where the result text goes --- */
31 #define ResultX 0
32 #define ResultY 305
33 
34 /* --- Position where the notify text goes --- */
35 #define NOTIFYX 390
36 #define NOTIFYY 285
37 
38 /* --- The width of most buttons --- */
39 #define CHECKBUTWIDTH 190
40 #define SCROLLAMOUNT -15
41 
42 /* Size of buffer to hold resulting strings from conversion
43 and returned by messages */
44 #define BUFFERLEN 80
45 char TextBuffer[BUFFERLEN]={'R','e','s','u','l','t',':',' '};
46 
47 HWND g_hwnd = NULL;
48 HINSTANCE g_hInst = NULL;
49 
50 int pos = 10;
51 int n = 0;
52 int yButPos = 10;
53 int xButPos = 0;
54 
55 DWORD ComboStyle = 0;
56 
57 /* --- Control coordinates --- */
58 #define CONTROLPOSX 390
59 #define CONTROLPOSY 10
60 DWORD ControlWidth = 160;
61 DWORD ControlHeight = 150;
62 
63 static RECT  srect = {CONTROLPOSX,CONTROLPOSY,WINDOWWIDTH,WINDOWHEIGHT};
64 
65 HWND hwndEdit = NULL;
66 
67 RECT  rect;
68 DWORD StartP,EndP;
69 HWND hwnd; /* main window handle */
70 
71 char AddString[] = "string added";
72 
73 typedef void FunctionHandler(HWND,DWORD,WPARAM,LPARAM);
74 typedef FunctionHandler* LPFUNCTIONHANDLER;
75 
76 void PrintTextXY(char* Text,int x,int y,int len, RECT rect)
77     {
78     HDC hdc;
79     hdc = GetDC (g_hwnd);
80     SelectObject (hdc, GetStockObject (SYSTEM_FIXED_FONT));
81 
82     TextOut (hdc, x,y,Text,len);
83     ReleaseDC (g_hwnd, hdc);
84 
85     ValidateRect (g_hwnd, &rect);
86     }
87 
88 static
89 VOID
90 HandlePrintReturnHex(HWND handle,DWORD Msg,WPARAM wParam,LPARAM lParam)
91     {
92     LRESULT ret;
93     RECT rect;
94     ret = SendMessage(handle,Msg,wParam,lParam);
95     htoa((unsigned int)ret,&TextBuffer[8]);
96     GetWindowRect(g_hwnd,&rect);
97     PrintTextXY(TextBuffer,ResultX,ResultY,16,rect);
98     }
99 
100 
101 static
102 VOID
103 HandlePrintReturnStr(HWND handle,DWORD Msg,WPARAM wParam,LPARAM lParam)
104     {
105     LRESULT ret;
106     RECT rect;
107 
108     TextBuffer[8] = (char)(BUFFERLEN - 8); /* Setting the max size to put chars in first byte */
109     ret = SendMessage(handle,Msg,wParam,lParam);
110     GetWindowRect(g_hwnd,&rect);
111     PrintTextXY(TextBuffer,ResultX,ResultY,8+(int)ret,rect);
112     }
113 
114 static
115 VOID
116 HandlePrintRect(HWND handle,DWORD Msg,WPARAM wParam,LPARAM lParam)
117     {
118     RECT rect = *(RECT*)lParam;
119     TextBuffer[8] = (char)(BUFFERLEN - 8); /* Setting the max size to put chars in first byte */
120     SendMessage(handle,Msg,wParam,lParam);
121 
122     htoa(rect.top,&TextBuffer[8]);
123     TextBuffer[8+8] = ' ';
124     htoa(rect.bottom,&TextBuffer[8+8+1]);
125     TextBuffer[8+8+8+1] = ' ';
126     htoa(rect.left,&TextBuffer[8+8+8+1+1]);
127     TextBuffer[8+8+8+8+1+1] = ' ';
128     htoa(rect.right,&TextBuffer[8+8+8+8+1+1+1]);
129 
130     GetWindowRect(g_hwnd,&rect);
131     PrintTextXY(TextBuffer,ResultX,ResultY,8+4*9-1,rect);
132     }
133 
134 struct
135     {
136     char* Text;                	/* Text for the button */
137     DWORD MsgCode;             	/* Message Code */
138     WPARAM wParam;             	/* Well hope you can understand this */
139     LPARAM lParam;             	/* ditto */
140     LPFUNCTIONHANDLER Handler; 	/* Funtion called to handle the result of each message */
141     }
142 Msg[] =
143     {
144 		{"CB_ADDSTRING",CB_ADDSTRING,0,(LPARAM)&AddString,&HandlePrintReturnHex},
145         {"CB_ADDSTRING - long",CB_ADDSTRING,0,(LPARAM)"very loooooooooong striiinnnnnnnnnggg",&HandlePrintReturnHex},
146         {"CB_DELETESTRING",CB_DELETESTRING,2,0,&HandlePrintReturnHex},   /* remember to catch WM_DELETEITEM*/
147 
148         /* What a message, why M$ decided to implement his thing ? */
149         {"CB_DIR - drives",CB_DIR,DDL_DRIVES,
150         /* Hoping that most machines have this */
151         (LPARAM)"C:\\",
152         &HandlePrintReturnHex},
153 
154         {"CB_DIR - dirs",CB_DIR,DDL_DIRECTORY,(LPARAM)"C:\\*",&HandlePrintReturnHex},
155 
156         {"CB_DIR - files",CB_DIR,
157         DDL_ARCHIVE | DDL_EXCLUSIVE | DDL_HIDDEN | DDL_READONLY | DDL_READWRITE | DDL_SYSTEM,
158         (LPARAM)"C:\\*",&HandlePrintReturnHex},
159 
160         /* Do not forget WM_COMPAREITEM */
161 
162         {"CB_FINDSTRING",CB_FINDSTRING,1,(LPARAM)"str",&HandlePrintReturnHex},
163         {"CB_FINDSTRINGEXACT(-1)",CB_FINDSTRINGEXACT,-1,(LPARAM)&AddString,&HandlePrintReturnHex},
164         {"CB_FINDSTRINGEXACT(2)",CB_FINDSTRINGEXACT,2,(LPARAM)&AddString,&HandlePrintReturnHex},
165 
166         /* "CB_GETCOMBOBOXINFO",CB_GETCOMBOBOXINFO,0,0,&HandlePrintReturnHex, winXP & .net server remember to handle the struct  */
167 
168         {"CB_GETCOUNT",CB_GETCOUNT,0,0,&HandlePrintReturnHex},
169 
170         {"CB_GETCURSEL",CB_GETCURSEL,0,0,&HandlePrintReturnHex},
171 
172         /* To implement "CB_GETEDITSEL - vars",CB_GETEDITSEL,,,&HandlePrintReturnHex, */
173 
174         {"CB_GETEXTENDEDUI",CB_GETEXTENDEDUI,0,0,&HandlePrintReturnHex},
175         {"CB_GETHORIZONTALEXTENT",CB_GETHORIZONTALEXTENT,0,0,&HandlePrintReturnHex},
176 
177 
178 
179         {"CB_GETLBTEXT",CB_GETLBTEXT,1,(LPARAM)&TextBuffer[8],&HandlePrintReturnStr},
180         {"CB_GETLBTEXTLEN",CB_GETLBTEXTLEN,1,0,&HandlePrintReturnHex},
181         {"CB_GETLOCALE",CB_GETLOCALE,0,0,&HandlePrintReturnHex},
182 
183         /* "CB_GETMINVISIBLE",CB_GETMINVISIBLE,0,0,&HandlePrintReturnHex, Included in Windows XP and Windows .NET Server. */
184 
185         {"CB_GETTOPINDEX",CB_GETTOPINDEX,0,0,&HandlePrintReturnHex},
186 
187         {"CB_INITSTORAGE",CB_INITSTORAGE,10,200,&HandlePrintReturnHex},
188         {"CB_INSERTSTRING",CB_INSERTSTRING,2,(LPARAM)"inserted string",&HandlePrintReturnHex},
189 
190         {"CB_LIMITTEXT",CB_LIMITTEXT,10,0,&HandlePrintReturnHex},
191         {"CB_RESETCONTENT",CB_RESETCONTENT ,0,0,&HandlePrintReturnHex},
192         {"CB_SELECTSTRING",CB_SELECTSTRING,2,(LPARAM)"str",&HandlePrintReturnHex},
193         {"CB_SETCURSEL",CB_SETCURSEL,1,0,&HandlePrintReturnHex},
194 
195         {"CB_SETDROPPEDWIDTH",CB_SETDROPPEDWIDTH,250,0,&HandlePrintReturnHex},
196 
197         {"CB_SETEXTENDEDUI - set",CB_SETEXTENDEDUI,TRUE,0,&HandlePrintReturnHex},
198         {"CB_SETEXTENDEDUI - clear",CB_SETEXTENDEDUI,FALSE,0,&HandlePrintReturnHex},
199 
200         /*
201         * win2k have a small bug with this ^ , if you press F4 while it is cleared,
202         * the combobox is using style cbs_dropdown
203         * and the pointer is over the edit box then the mouse pointer is not changed
204         * to an arrow
205         */
206 
207         {"CB_SETHORIZONTALEXTENT",CB_SETHORIZONTALEXTENT,500,0,&HandlePrintReturnHex},
208 
209         {"CB_GETITEMDATA",CB_GETITEMDATA,1,0,&HandlePrintReturnHex},
210         {"CB_SETITEMDATA",CB_SETITEMDATA,1,0x791031,&HandlePrintReturnHex},
211 
212         {"CB_SETITEMHEIGHT",CB_SETITEMHEIGHT,-1,30,&HandlePrintReturnHex},
213         {"CB_GETITEMHEIGHT",CB_GETITEMHEIGHT,2,0,&HandlePrintReturnHex},
214 
215         /* "CB_SETMINVISIBLE",CB_SETMINVISIBLE,4,0,&HandlePrintReturnHex, Included in Windows XP and Windows .NET Server */
216 
217         {"CB_GETEDITSEL",CB_GETEDITSEL,(WPARAM)NULL,(LPARAM)NULL,&HandlePrintReturnHex},
218         {"CB_SETEDITSEL",CB_SETEDITSEL,0,0x00020005,&HandlePrintReturnHex},
219         {"CB_SETEDITSEL - clear",CB_SETEDITSEL,0,0xFFFFFFFF,&HandlePrintReturnHex},
220 
221         {"CB_SETTOPINDEX",CB_SETTOPINDEX,3,0,&HandlePrintReturnHex},
222 
223         {"CB_SHOWDROPDOWN - true",CB_SHOWDROPDOWN,TRUE,0,&HandlePrintReturnHex},
224         {"CB_SHOWDROPDOWN - false",CB_SHOWDROPDOWN,FALSE,0,&HandlePrintReturnHex},
225 
226         {"CB_GETDROPPEDCONTROLRECT",CB_GETDROPPEDCONTROLRECT,0,(LPARAM)&rect,&HandlePrintRect},
227         {"CB_GETDROPPEDSTATE",CB_GETDROPPEDSTATE,0,0,&HandlePrintReturnHex},
228         {"CB_GETDROPPEDWIDTH",CB_GETDROPPEDWIDTH,0,0,&HandlePrintReturnHex},
229 
230         {"WM_PASTE",WM_PASTE,0,0,&HandlePrintReturnHex},
231     };
232 
233 #define MAXMESSAGEBUTTONS 40
234 
235 struct
236     {
237     char* Name;                	/* Text for the button */
238     DWORD Code;             	/* Style Code */
239     }
240 Styles[] = {
241     {"WS_DISABLED",WS_DISABLED},
242 	{"CBS_AUTOHSCROLL",CBS_AUTOHSCROLL},
243 	{"CBS_DISABLENOSCROLL",CBS_DISABLENOSCROLL},
244 	{"CBS_DROPDOWN",CBS_DROPDOWN},
245 	{"CBS_DROPDOWNLIST",CBS_DROPDOWNLIST},
246 	{"CBS_HASSTRINGS",CBS_HASSTRINGS},
247 	{"CBS_LOWERCASE",CBS_LOWERCASE},
248 	{"CBS_NOINTEGRALHEIGHT",CBS_NOINTEGRALHEIGHT},
249 	{"CBS_OEMCONVERT",CBS_OEMCONVERT},
250 	{"CBS_OWNERDRAWFIXED",CBS_OWNERDRAWFIXED},
251 	{"CBS_OWNERDRAWVARIABLE",CBS_OWNERDRAWVARIABLE},
252 	{"CBS_SIMPLE",CBS_SIMPLE},
253 	{"CBS_SORT",CBS_SORT},
254 	{"CBS_UPPERCASE",CBS_UPPERCASE},
255 	{"CBS_DISABLENOSCROLL",CBS_DISABLENOSCROLL},
256 	{"WS_HSCROLL",WS_HSCROLL},
257 	{"WS_VSCROLL",WS_VSCROLL}
258     };
259 
260 /* The number of check buttons we have.
261 * Maybe some calculations at compile time would be better
262 */
263 
264 #define NUMBERCHECKS 17
265 
266 #define NUMBERBUTTONS  NUMBERCHECKS + 7
267 HWND Buttons[NUMBERBUTTONS];
268 HWND MessageButtons[MAXMESSAGEBUTTONS];
269 HWND Back1But,Back2But;
270 HWND NextBut;
271 
272 HWND
273 CreateCheckButton(const char* lpWindowName, DWORD xSize, DWORD id)
274     {
275     HWND h;
276     h  = CreateWindowEx(0,
277         "BUTTON",
278         lpWindowName,
279         WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
280         xButPos, /*  x  */
281         yButPos, /*  y  */
282         xSize,   /* nWidth  */
283         20,      /* nHeight */
284         g_hwnd,
285         UlongToHandle(id),
286         g_hInst,
287         NULL
288         );
289     yButPos += 21;
290     return h;
291     }
292 
293 HWND
294 CreatePushButton(const char* lpWindowName, DWORD xSize, DWORD id,DWORD Style)
295     {
296 
297     HWND h = CreateWindow("BUTTON",
298         lpWindowName,
299         WS_CHILD | BS_PUSHBUTTON | Style,
300         xButPos, /* x */
301         yButPos, /* y */
302         xSize,   /* nWidth */
303         20,      /* nHeight */
304         g_hwnd,
305         LongToHandle(id),
306         g_hInst,
307         NULL
308         );
309 
310     yButPos += 21;
311     return h;
312     }
313 
314 VOID
315 ReadNHide()
316     {
317     int i;
318     ComboStyle = 0;
319     for (i=0 ; i< NUMBERCHECKS ; i++)
320         {
321         if(BST_CHECKED == SendMessage(Buttons[i],BM_GETCHECK,0,0))
322             ComboStyle |= Styles[i].Code;
323         ShowWindow(Buttons[i],SW_HIDE);
324         }
325 
326     for (; i< NUMBERBUTTONS ; i++)ShowWindow(Buttons[i],SW_HIDE);
327     for (i=0 ; i< 26 ; i++) ShowWindow(MessageButtons[i],SW_SHOW);
328 
329     ShowWindow(Back1But,SW_SHOW);
330     ShowWindow(NextBut,SW_SHOW);
331     }
332 
333 VOID
334 ForwardToSecondPage()
335     {
336     int i;
337     for (i=0;i<26;i++)ShowWindow(MessageButtons[i],SW_HIDE);
338     for(;i<MAXMESSAGEBUTTONS;i++)ShowWindow(MessageButtons[i],SW_SHOW);
339     ShowWindow(Back2But,SW_SHOW);
340 
341     ShowWindow(Back1But,SW_HIDE);
342     ShowWindow(NextBut,SW_HIDE);
343     }
344 
345 VOID
346 BackToFirstPage()
347     {
348     int i;
349     for (i=0;i<26;i++)ShowWindow(MessageButtons[i],SW_SHOW);
350     for(;i<MAXMESSAGEBUTTONS;i++)ShowWindow(MessageButtons[i],SW_HIDE);
351     ShowWindow(Back2But,SW_HIDE);
352     ShowWindow(Back1But,SW_SHOW);
353     ShowWindow(NextBut,SW_SHOW);
354     }
355 
356 VOID
357 BackToInitialPage()
358     {
359     int i;
360     DestroyWindow(hwndEdit);
361     for (i=0 ; i< NUMBERBUTTONS ; i++) {ShowWindow(Buttons[i],SW_SHOW);}
362 for (i=0;i<26;i++)ShowWindow(MessageButtons[i],SW_HIDE);
363 ShowWindow(Back1But,SW_HIDE);
364 ShowWindow(NextBut,SW_HIDE);
365     }
366 
367 LRESULT
368 CALLBACK
369 WndProc ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
370     {
371     int i;
372     switch ( msg )
373         {
374         case WM_CREATE:
375             g_hwnd = hwnd;
376 
377             /* ---- Initial page ---- */
378 
379             for (i = 0 ; i < 14 ; i++)
380                 Buttons[i] = CreateCheckButton(Styles[i].Name,CHECKBUTWIDTH,500+i);
381 
382             xButPos += CHECKBUTWIDTH + 10;
383             yButPos = 10;
384 
385             for (; i < NUMBERCHECKS ; i++)
386                 Buttons[i] = CreateCheckButton(Styles[i].Name,CHECKBUTWIDTH,500+i);
387 
388             Buttons[i++] = CreatePushButton("Width +",70,100,WS_VISIBLE);
389             Buttons[i++] = CreatePushButton("Width -",70,101,WS_VISIBLE);
390 
391             Buttons[i++] = CreatePushButton("Height +",70,102,WS_VISIBLE);
392             Buttons[i++] = CreatePushButton("Height -",70,103,WS_VISIBLE);
393 
394             Buttons[i++] = CreatePushButton("CreateWindowA",CHECKBUTWIDTH,CREATEWINDOW_ID,WS_VISIBLE);
395             Buttons[i++] = CreatePushButton("CreateWindowExA",CHECKBUTWIDTH,CREATEWINDOWEX_ID,WS_VISIBLE);
396             Buttons[i++] = CreatePushButton("CreateWindowExW",CHECKBUTWIDTH,CREATEWINDOWW_ID,WS_VISIBLE);
397 
398 
399             /* ---- The 1st page of buttons ---- */
400 
401             xButPos = 0;
402             yButPos = 10;
403 
404             for (i = 0 ; i < 14 ; i++)
405                 MessageButtons[i] = CreatePushButton(Msg[i].Text,CHECKBUTWIDTH,600+i,0);
406 
407             xButPos += CHECKBUTWIDTH + 10;
408             yButPos = 10;
409 
410             for (; i < 26 ; i++)
411                 MessageButtons[i] = CreatePushButton(Msg[i].Text,CHECKBUTWIDTH,600+i,0);
412 
413             Back1But = CreatePushButton("Back - destroys ComboBox",CHECKBUTWIDTH,INITPAGE_ID,0);
414             NextBut = CreatePushButton("Next",CHECKBUTWIDTH,SECONDPAGE_ID,0);
415 
416             /* ---- The 2nd page of buttons ------*/
417 
418             xButPos = 0;
419             yButPos = 10;
420 
421             for (; i<40; i++)
422                 MessageButtons[i] = CreatePushButton(Msg[i].Text,CHECKBUTWIDTH,600+i,0);
423 
424             xButPos += CHECKBUTWIDTH + 10;
425             yButPos = 10;
426 
427             for (; i < MAXMESSAGEBUTTONS ; i++)
428                 MessageButtons[i] = CreatePushButton(Msg[i].Text,CHECKBUTWIDTH,600+i,0);
429 
430             Back2But = CreatePushButton("Back",CHECKBUTWIDTH,BACKFIRSTPAGE_ID,0);
431 
432             break;
433 
434         case WM_COMMAND:
435             if (LOWORD(wParam) >= 600)
436                 {
437                 Msg[LOWORD(wParam)-600].Handler(hwndEdit,
438                     Msg[LOWORD(wParam)-600].MsgCode,
439                     Msg[LOWORD(wParam)-600].wParam,
440                     Msg[LOWORD(wParam)-600].lParam);
441                 break;
442                 }
443 
444             switch(LOWORD(wParam)){
445 
446         case 100:
447             ControlWidth += 10;
448             break;
449 
450         case 101:
451             ControlWidth -= 10;
452             break;
453 
454         case 102:
455             ControlHeight += 10;
456             break;
457 
458         case 103:
459             ControlHeight -= 10;
460             break;
461 
462         case INITPAGE_ID:
463             BackToInitialPage();
464             break;
465 
466         case SECONDPAGE_ID:
467             ForwardToSecondPage();
468             break;
469 
470         case BACKFIRSTPAGE_ID:
471             BackToFirstPage();
472             break;
473 
474         case CREATEWINDOW_ID:
475             ReadNHide();
476             srect.top = CONTROLPOSY + ControlHeight;
477             hwndEdit = CreateWindow(CONTROLCLASS,
478                 NULL,
479                 ComboStyle | WS_CHILD | WS_VISIBLE,
480                 CONTROLPOSX,
481                 CONTROLPOSY,
482                 ControlWidth,
483                 ControlHeight,
484                 g_hwnd,
485                 NULL,
486                 g_hInst,
487                 NULL);
488             break;
489 
490         case CREATEWINDOWEX_ID:
491             ReadNHide();
492             srect.top = CONTROLPOSY + ControlHeight;
493             hwndEdit = CreateWindowEx(WS_EX_CLIENTEDGE,
494                 CONTROLCLASS,
495                 NULL,
496                 ComboStyle | WS_CHILD | WS_VISIBLE ,
497                 CONTROLPOSX,
498                 CONTROLPOSY,
499                 ControlWidth,
500                 ControlHeight,
501                 g_hwnd,
502                 NULL,
503                 g_hInst,
504                 NULL);
505             break;
506 
507         case CREATEWINDOWW_ID:
508             ReadNHide();
509             srect.top = CONTROLPOSY + ControlHeight;
510             hwndEdit = CreateWindowExW(WS_EX_CLIENTEDGE,
511                 CONTROLCLASSW,
512                 NULL,
513                 ComboStyle | WS_CHILD | WS_VISIBLE ,
514                 CONTROLPOSX,
515                 CONTROLPOSY,
516                 ControlWidth,
517                 ControlHeight,
518                 g_hwnd,
519                 NULL,
520                 g_hInst,
521                 NULL);
522             break;
523                 }
524 
525         if (lParam == (LPARAM)hwndEdit)
526             switch(HIWORD(wParam))
527             {
528                 case CBN_DROPDOWN:
529                     ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
530                     PrintTextXY("CBN_DROPDOWN notification",NOTIFYX,NOTIFYY,25,srect);
531                     break;
532 
533                 case CBN_CLOSEUP:
534                     ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
535                     PrintTextXY("CBN_CLOSEUP notification",NOTIFYX,NOTIFYY,24,srect);
536                     break;
537 
538                 case CBN_DBLCLK:
539                     ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
540                     PrintTextXY("CBN_DBLCLK notification",NOTIFYX,NOTIFYY,23,srect);
541                     break;
542 
543                 case CBN_EDITCHANGE:
544                     ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
545                     PrintTextXY("CBN_EDITCHANGE notification",NOTIFYX,NOTIFYY,27,srect);
546                     break;
547 
548                 case (WORD)CBN_ERRSPACE:
549                     ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
550                     PrintTextXY("CBN_ERRSPACE notification",NOTIFYX,NOTIFYY,25,srect);
551                     break;
552 
553                 case CBN_KILLFOCUS:
554                     ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
555                     PrintTextXY("CBN_KILLFOCUS notification",NOTIFYX,NOTIFYY,26,srect);
556                     break;
557 
558                 case CBN_EDITUPDATE:
559                     ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
560                     PrintTextXY("CBN_EDITUPDATE notification",NOTIFYX,NOTIFYY,27,srect);
561                     break;
562 
563                 case CBN_SELCHANGE:
564                     ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
565                     PrintTextXY("CBN_SELCHANGE notification",NOTIFYX,NOTIFYY,26,srect);
566                     break;
567 
568                 case CBN_SELENDCANCEL:
569                     ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
570                     PrintTextXY("CBN_SELENDCANCEL notification",NOTIFYX,NOTIFYY,29,srect);
571                     break;
572 
573                 case CBN_SETFOCUS:
574                     ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
575                     PrintTextXY("CBN_SETFOCUS notification",NOTIFYX,NOTIFYY,25,srect);
576                     break;
577 
578                 case CBN_SELENDOK:
579                     ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
580                     PrintTextXY("CBN_SELENDOK notification",NOTIFYX,NOTIFYY,25,srect);
581                     break;
582             }
583 
584         return DefWindowProc ( hwnd, msg, wParam, lParam );
585 
586         case WM_MEASUREITEM:
587             ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
588             PrintTextXY("WM_MEASUREITEM called",NOTIFYX,NOTIFYY,21,srect);
589             break;
590 
591         case WM_COMPAREITEM:
592             ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
593             PrintTextXY("WM_COMPAREITEM called",NOTIFYX,NOTIFYY,21,srect);
594             break;
595 
596         case WM_DRAWITEM:
597             ScrollWindow (hwnd, 0, SCROLLAMOUNT, &srect, &srect);
598             PrintTextXY("WM_DRAWITEM called",NOTIFYX,NOTIFYY,18,srect);
599             break;
600 
601         case WM_SIZE :
602             return 0;
603 
604         case WM_CLOSE:
605             DestroyWindow (g_hwnd);
606             return 0;
607 
608         case WM_QUERYENDSESSION:
609             return 0;
610 
611         case WM_DESTROY:
612             PostQuitMessage(0);
613             return 0;
614         }
615     return DefWindowProc ( hwnd, msg, wParam, lParam );
616     }
617 
618 
619 HWND
620 RegisterAndCreateWindow (HINSTANCE hInst,
621                          const char* className,
622                          const char* title)
623     {
624     WNDCLASSEX wc;
625 
626 
627     g_hInst = hInst;
628 
629     wc.cbSize = sizeof (WNDCLASSEX);
630 
631     wc.lpfnWndProc = WndProc;   /* window procedure */
632     wc.hInstance = hInst;       /* owner of the class */
633 
634     wc.lpszClassName = className;
635     wc.hCursor = LoadCursor ( 0, (LPCTSTR)IDC_ARROW );
636     wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
637     wc.style = CS_HREDRAW | CS_VREDRAW;
638     wc.cbClsExtra = 0;
639     wc.cbWndExtra = 0;
640     wc.hIcon = 0;
641     wc.hIconSm = 0;
642     wc.lpszMenuName = 0;
643 
644     if ( !RegisterClassEx ( &wc ) )
645         return NULL;
646 
647     hwnd = CreateWindowEx (
648         0,          /* dwStyleEx */
649         className,  /* class name */
650         title,      /* window title */
651 
652         WS_OVERLAPPEDWINDOW, /* dwStyle */
653 
654         1,            /* x */
655         1,            /* y */
656         WINDOWWIDTH,  /* width */
657         WINDOWHEIGHT, /* height */
658         NULL,         /* hwndParent */
659         NULL,         /* hMenu */
660         hInst,
661         0
662         );
663 
664     if (!hwnd) return NULL;
665 
666     ShowWindow (hwnd, SW_SHOW);
667     UpdateWindow (hwnd);
668 
669     return hwnd;
670     }
671 
672 int
673 WINAPI
674 WinMain ( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdParam, int cmdShow )
675     {
676     char className [] = "ComboBox Control Test";
677     MSG msg;
678 
679     RegisterAndCreateWindow ( hInst, className, "ComboBox Control Test" );
680 
681     while (GetMessage (&msg, NULL, 0, 0))
682         {
683         TranslateMessage (&msg);
684         DispatchMessage (&msg);
685         }
686     return (int)msg.wParam;
687     }
688