Added SetLastError() in GetEnvironmentVariableA.
[wine/dcerpc.git] / programs / cmdlgtst / cmdlgtst.c
blob442153adaa4da5f2031e928d9a0609ba2a459c65
1 /*
2 * (c) 1999-2000 Eric Williams. Rights as specified under the WINE
3 * License. Don't hoard code; share it!
4 */
6 /*
7 * One might call this a Commdlg test jig. Its sole function in life
8 * is to call the Commdlg Common Dialogs. The results of a call to
9 * File Open or File Save are printed in the upper left corner;
10 * Font adjusts the font of the printout, and Color adjusts the color
11 * of the background.
15 * Ideally it would also do event logging and be a bit less stupid
16 * about displaying the results of the various requesters. But hey,
17 * it's only a first step. :-)
20 #include <windows.h>
21 #include <commdlg.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include "cmdlgtst.h"
27 * This structure is to set up flag / control associations for the custom
28 * requesters. The ft_id is the id for the control (usually generated
29 * by the system) and the ft_bit is the flag bit which goes into the
30 * settings longword for the various Commdlg structures. It is assumed
31 * that all flags fit in an unsigned long and that all bits are in fact
32 * one bit.
36 * The array of entries is terminated by {IDOK, 0}; the assumption is that
37 * IDOK would never be associated with a dialogbox control (since it's
38 * usually the ID of the OK button}.
41 struct FlagTableEntry {
42 int ft_id;
43 unsigned long ft_bit;
46 #if 0
47 #define FAR
48 #endif
49 #define EXPORT
51 static char menuName[] = "CmdlgtstMenu";
52 static char className[] = "CmdlgtstClass";
53 static char windowName[] = "Cmdlgtst Window";
56 * global hInstance variable. This makes the code non-threadable,
57 * but wotthehell; this is Win32 anyway! (Though it does work
58 * under Win16, if one doesn't run more than one copy at a time.)
61 static HINSTANCE g_hInstance;
64 * global CommDlg data structures for modals. These are placed here
65 * so that the custom dialog boxes can get at them.
68 static PRINTDLG pd;
69 static COLORREF cc_cr[16];
70 static CHOOSECOLOR cc;
71 static LOGFONT cf_lf;
72 static CHOOSEFONT cf;
73 static char ofn_filepat[] = "All Files (*.*)\0*.*\0Only Text Files (*.txt)\0*.txt\0";
74 static char ofn_result[1024];
75 static char ofn_titleresult[128];
76 static OPENFILENAME ofn;
78 /* Stuff for find and replace. These are modeless, so I have to put them here. */
80 static HWND findDialogBox = 0;
81 static UINT findMessageId = 0;
83 static FINDREPLACE frS;
84 static char fromstring[1024], tostring[1024];
86 /* Stuff for the drawing of the window(s). I put them here for convenience. */
88 static COLORREF fgColor = RGB(0, 0, 0); /* not settable */
89 static COLORREF bgColor = RGB(255, 255, 255); /* COLOR dialog */
90 static COLORREF txtColor = RGB(0, 0, 0); /* settable if one enables CF_EFFECTS */
92 /* Utility routines. */
94 void nyi(HWND hWnd)
96 /* "Hi there! I'm not yet implemented!" */
97 MessageBox(hWnd, "Not yet implemented!", "NYI", MB_ICONEXCLAMATION | MB_OK);
100 UINT CALLBACK dummyfnHook(HWND hWnd, UINT msg, UINT wParam, UINT lParam)
103 * If the user specifies something that needs an awfully stupid hook function,
104 * this is the one to use. It's a no-op, and says "I didn't do anything."
107 (void) hWnd;
108 (void) msg;
109 (void) wParam;
110 (void) lParam;
112 printf("dummyfnhook\n"); /* visible under Wine, but Windows probably won't see it! */
114 return 0;
118 * Initialization code. This code simply shoves in predefined
119 * data into the COMMDLG data structures; in the future, I might use
120 * a series of loadable resources, or static initializers; of course,
121 * if Microsoft decides to change the field ordering, I'd be screwed.
124 void mwi_Print(HWND hWnd)
126 pd.lStructSize = sizeof(PRINTDLG);
127 pd.hwndOwner = hWnd;
128 pd.hDevMode = 0;
129 pd.hDevNames = 0;
130 pd.hDC = 0;
131 pd.Flags = 0;
132 pd.nMinPage = 1;
133 pd.nMaxPage = 100;
134 pd.hInstance = g_hInstance;
135 pd.lCustData = 0;
136 pd.lpfnPrintHook = 0;
137 pd.lpfnSetupHook = 0;
138 pd.lpPrintTemplateName = 0;
139 pd.lpSetupTemplateName = 0;
140 pd.hPrintTemplate = 0;
141 pd.hSetupTemplate = 0;
144 void mwi_Color(HWND hWnd)
146 int i;
148 /* there's probably an init call for this, somewhere. */
150 for(i=0;i<16;i++)
151 cc_cr[i] = RGB(0,0,0);
153 cc.lStructSize = sizeof(CHOOSECOLOR);
154 cc.hwndOwner = hWnd;
155 cc.hInstance = g_hInstance;
156 cc.rgbResult = RGB(0,0,0);
157 cc.lpCustColors = cc_cr;
158 cc.Flags = 0;
159 cc.lCustData = 0;
160 cc.lpfnHook = 0;
161 cc.lpTemplateName = 0;
164 void mwi_Font(HWND hWnd)
166 cf.lStructSize = sizeof(CHOOSEFONT);
167 cf.hwndOwner = hWnd;
168 cf.hDC = 0;
169 cf.lpLogFont = &cf_lf;
170 cf.Flags = CF_SCREENFONTS; /* something's needed for display; otherwise it craps out with an error */
171 cf.rgbColors = RGB(0,0,0); /* what is *this* doing here?? */
172 cf.lCustData = 0;
173 cf.lpfnHook = 0;
174 cf.lpTemplateName = 0;
175 cf.hInstance = g_hInstance;
176 cf.lpszStyle = 0;
177 cf.nFontType = 0;
178 cf.nSizeMin = 8;
179 cf.nSizeMax = 72;
181 cf_lf.lfHeight = -18; /* this can be positive or negative, but negative is usually used. */
184 void mwi_File(HWND hWnd)
186 ofn.lStructSize = sizeof(OPENFILENAME);
187 ofn.hwndOwner = hWnd;
188 ofn.hInstance = g_hInstance;
189 ofn.lpstrFilter = (LPSTR) ofn_filepat;
190 ofn.lpstrCustomFilter = 0;
191 ofn.nMaxCustFilter = 0;
192 ofn.nFilterIndex = 0;
193 ofn.lpstrFile = ofn_result;
194 ofn.nMaxFile = sizeof(ofn_result);
195 ofn.lpstrFileTitle = ofn_titleresult;
196 ofn.nMaxFileTitle = sizeof(ofn_titleresult);
197 ofn.lpstrInitialDir = 0;
198 ofn.lpstrTitle = "Open File";
199 ofn.Flags = 0;
200 ofn.nFileOffset = 0;
201 ofn.nFileExtension = 0;
202 ofn.lpstrDefExt = "*";
203 ofn.lCustData = 0;
204 ofn.lpfnHook = 0;
205 ofn.lpTemplateName = 0;
207 ofn_result[0] = '\0';
210 void mwi_FindReplace(HWND hWnd)
212 frS.lStructSize = sizeof(FINDREPLACE);
213 frS.hwndOwner = hWnd;
214 frS.hInstance = g_hInstance;
215 frS.Flags = FR_DOWN;
216 frS.lpstrFindWhat = fromstring;
217 frS.lpstrReplaceWith = tostring;
218 frS.wFindWhatLen = sizeof(fromstring);
219 frS.wReplaceWithLen = sizeof(tostring);
220 frS.lCustData = 0;
221 frS.lpfnHook = 0;
222 frS.lpTemplateName = 0;
224 fromstring[0] = '\0';
225 tostring[0] = '\0';
226 findMessageId = RegisterWindowMessage(FINDMSGSTRING);
229 void mwi_InitAll(HWND hWnd)
231 mwi_Print(hWnd);
232 mwi_Font(hWnd);
233 mwi_Color(hWnd);
234 mwi_File(hWnd);
235 mwi_FindReplace(hWnd);
239 * Various configurations for the window. Ideally, this
240 * would be stored with the window itself, but then, this
241 * isn't the brightest of apps. Wouldn't be hard to set up,
242 * though -- one of the neater functions of Windows, but if
243 * someone decides to load the windows themselves from resources,
244 * there might be a problem.
247 void paintMainWindow(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
249 PAINTSTRUCT ps;
250 RECT rect;
251 HPEN pen;
252 HFONT font;
253 HBRUSH brush;
255 (void) iMessage;
256 (void) wParam;
257 (void) lParam;
259 /* Commence painting! */
261 BeginPaint(hWnd, &ps);
262 GetClientRect(hWnd, (LPRECT) &rect);
264 pen = (HPEN) SelectObject(ps.hdc, CreatePen(0, 0, fgColor));
265 brush = (HBRUSH) SelectObject(ps.hdc, CreateSolidBrush(bgColor));
266 font = (HFONT) SelectObject(ps.hdc, CreateFontIndirect(&cf_lf));
269 * Ideally, we'd only need to draw the exposed bit.
270 * But something in BeginPaint is screwing up the rectangle.
271 * Either that, or Windows is drawing it wrong. AARGH!
272 * Rectangle(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
274 Rectangle(ps.hdc, rect.left, rect.top, rect.right, rect.bottom);
276 /* now draw a couple of lines, just for giggles. */
278 MoveToEx(ps.hdc, rect.left, rect.top, (POINT FAR *) 0);
279 LineTo(ps.hdc, rect.right, rect.bottom);
280 MoveToEx(ps.hdc, rect.left, rect.bottom, (POINT FAR *) 0);
281 LineTo(ps.hdc, rect.right, rect.top);
283 /* draw some text */
285 SetTextAlign(ps.hdc, TA_CENTER|TA_BASELINE);
286 SetTextColor(ps.hdc, txtColor);
287 TextOut(ps.hdc, (rect.left+rect.right)/2, (rect.top+rect.bottom)/2, "Common Dialog Test Page", 23);
289 SetTextAlign(ps.hdc, TA_LEFT|TA_TOP);
290 TextOut(ps.hdc, rect.left+10, rect.top+10, ofn_result, strlen(ofn_result));
291 TextOut(ps.hdc, rect.left+10, rect.top-cf_lf.lfHeight+10, ofn_titleresult, strlen(ofn_titleresult));
294 * set the HDC back to the old pen and brush,
295 * and delete the newly created objects.
298 pen = (HPEN) SelectObject(ps.hdc, pen);
299 DeleteObject(pen);
300 brush = (HBRUSH) SelectObject(ps.hdc, brush);
301 DeleteObject(brush);
302 font = (HFONT) SelectObject(ps.hdc, font);
303 DeleteObject(font);
305 EndPaint(hWnd, &ps);
309 * This function simply returns an error indication. Naturally,
310 * I do not (yet) see an elegant method by which one can convert
311 * the CDERR_xxx return values into something resembling usable text;
312 * consult cderr.h to see what was returned.
315 void mw_checkError(HWND hWnd, BOOL explicitcancel)
317 DWORD errval = CommDlgExtendedError();
318 if(errval) {
319 char errbuf[80];
321 sprintf(errbuf, "CommDlgExtendedError(): error code %ld (0x%lx)", errval, errval);
322 MessageBox(hWnd, errbuf, "Error", MB_ICONEXCLAMATION | MB_OK);
324 else {
325 if(explicitcancel) MessageBox(hWnd, "Nope, user canceled it.", "No", MB_OK);
330 * The actual dialog function calls. These merely wrap the Commdlg
331 * calls, and do something (not so) intelligent with the result.
332 * Ideally, the main window would refresh and take into account the
333 * various values specified in the dialog.
336 void mw_ColorSetup(HWND hWnd)
338 if(ChooseColor(&cc)) {
339 RECT rect;
341 GetClientRect(hWnd, (LPRECT) &rect);
342 InvalidateRect(hWnd, (LPRECT) &rect, FALSE);
343 bgColor = cc.rgbResult;
345 else mw_checkError(hWnd, FALSE);
348 void mw_FontSetup(HWND hWnd)
350 if(ChooseFont(&cf)) {
351 RECT rect;
352 GetClientRect(hWnd, (LPRECT) &rect);
353 InvalidateRect(hWnd, (LPRECT) &rect, FALSE);
354 txtColor = cf.rgbColors;
356 else mw_checkError(hWnd, FALSE);
359 void mw_FindSetup(HWND hWnd)
361 if(findDialogBox == 0) {
362 findDialogBox = FindText(&frS);
363 if(findDialogBox==0) mw_checkError(hWnd,TRUE);
367 void mw_ReplaceSetup(HWND hWnd)
369 if(findDialogBox == 0) {
370 findDialogBox = ReplaceText(&frS);
371 if(findDialogBox==0) mw_checkError(hWnd,TRUE);
375 void mw_OpenSetup(HWND hWnd)
377 if(GetOpenFileName(&ofn)) {
378 RECT rect;
379 GetClientRect(hWnd, (LPRECT) &rect);
380 InvalidateRect(hWnd, (LPRECT) &rect, FALSE);
382 else mw_checkError(hWnd,FALSE);
385 void mw_SaveSetup(HWND hWnd)
387 if(GetSaveFileName(&ofn)) {
388 RECT rect;
389 GetClientRect(hWnd, (LPRECT) &rect);
390 InvalidateRect(hWnd, (LPRECT) &rect, FALSE);
392 else mw_checkError(hWnd,FALSE);
396 * Can't find documentation in Borland for this one. Does it
397 * exist at all, or is it merely a subdialog of Print?
400 void mw_PSetupSetup(HWND hWnd)
402 nyi(hWnd);
405 void mw_PrintSetup(HWND hWnd)
407 if(PrintDlg(&pd)) {
409 * the following are suggested in the Borland documentation,
410 * but aren't that useful until WinE starts to actually
411 * function with respect to printing.
414 #if 0
415 Escape(tmp.hDC, STARTDOC, 8, "Test-Doc", NULL);
416 #endif
418 /* Print text and rectangle */
420 #if 0
421 TextOut(tmp.hDC, 50, 50, "Common Dialog Test Page", 23);
423 Rectangle(tmp.hDC, 50, 90, 625, 105);
424 Escape(tmp.hDC, NEWFRAME, 0, NULL, NULL);
425 Escape(tmp.hDC, ENDDOC, 0, NULL, NULL);
426 DeleteDC(tmp.hDC);
427 #endif
428 if (pd.hDevMode != 0)
429 GlobalFree(pd.hDevMode);
430 if (pd.hDevNames != 0)
431 GlobalFree(pd.hDevNames);
433 pd.hDevMode = 0;
434 pd.hDevNames = 0;
436 MessageBox(hWnd, "Success.", "Yes", MB_OK);
438 else mw_checkError(hWnd,TRUE);
442 * Some support functions for the custom dialog box handlers.
443 * In particular, we have to set things properly, and get the flags back.
446 void mwcd_SetFlags(HWND hWnd, struct FlagTableEntry *table, unsigned long flags)
448 int i;
450 for(i=0; table[i].ft_id != IDOK; i++)
452 CheckDlgButton(hWnd, table[i].ft_id,(table[i].ft_bit & flags) ? 1 : 0);
456 unsigned long mwcd_GetFlags(HWND hWnd, struct FlagTableEntry * table)
458 int i;
459 unsigned long l = 0;
461 for(i=0; table[i].ft_id != IDOK; i++)
463 if(IsDlgButtonChecked(hWnd, table[i].ft_id) == 1)
464 l |= table[i].ft_bit;
467 return l;
471 * These functions are the custom dialog box handlers.
472 * The division of labor may be a tad peculiar; in particular,
473 * the flag tables should probably be in the main functions,
474 * not the handlers. I'll fix that later; this works as of right now.
477 BOOL mwcd_Setup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
478 struct FlagTableEntry * table, unsigned long * flags)
480 (void) lParam;
482 switch(uMsg)
484 case WM_INITDIALOG:
485 /* Set the controls properly. */
487 mwcd_SetFlags(hWnd, table, *flags);
489 return TRUE; /* I would return FALSE if I explicitly called SetFocus(). */
490 /* As usual, Windows is weird. */
492 case WM_COMMAND:
493 switch(wParam) {
494 case IDOK:
495 *flags = mwcd_GetFlags(hWnd, table);
496 EndDialog(hWnd,1);
497 break;
499 case IDCANCEL:
500 EndDialog(hWnd,0);
501 break;
503 case CM_R_HELP:
504 break; /* help? We don't need no steenkin help! */
506 default:
507 break; /* eat the message */
509 return TRUE;
511 default:
512 return FALSE; /* since I don't process this particular message */
516 BOOL CALLBACK mwcd_ColorSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
518 static struct FlagTableEntry flagTable[] = {
519 {I_CC_RGBINIT, CC_RGBINIT},
520 {I_CC_SHOWHELP, CC_SHOWHELP},
521 {I_CC_PREVENTFULLOPEN, CC_PREVENTFULLOPEN},
522 {I_CC_FULLOPEN, CC_FULLOPEN},
523 {I_CC_ENABLETEMPLATEHANDLE, CC_ENABLETEMPLATEHANDLE},
524 {I_CC_ENABLETEMPLATE, CC_ENABLETEMPLATE},
525 {I_CC_ENABLEHOOK, CC_ENABLEHOOK},
526 {IDOK, 0},
529 return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &cc.Flags);
532 BOOL CALLBACK mwcd_FontSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
534 static struct FlagTableEntry flagTable[] = {
535 {I_CF_APPLY, CF_APPLY},
536 {I_CF_ANSIONLY, CF_ANSIONLY},
537 {I_CF_BOTH, CF_BOTH},
538 {I_CF_TTONLY, CF_TTONLY},
539 {I_CF_EFFECTS, CF_EFFECTS},
540 {I_CF_ENABLEHOOK, CF_ENABLEHOOK},
541 {I_CF_ENABLETEMPLATE, CF_ENABLETEMPLATE},
542 {I_CF_ENABLETEMPLATEHANDLE, CF_ENABLETEMPLATEHANDLE},
543 {I_CF_FIXEDPITCHONLY, CF_FIXEDPITCHONLY},
544 {I_CF_INITTOLOGFONTSTRUCT, CF_INITTOLOGFONTSTRUCT},
545 {I_CF_LIMITSIZE, CF_LIMITSIZE},
546 {I_CF_NOFACESEL, CF_NOFACESEL},
547 {I_CF_USESTYLE, CF_USESTYLE},
548 {I_CF_WYSIWYG, CF_WYSIWYG},
549 {I_CF_SHOWHELP, CF_SHOWHELP},
550 {I_CF_SCREENFONTS, CF_SCREENFONTS},
551 {I_CF_SCALABLEONLY, CF_SCALABLEONLY},
552 {I_CF_PRINTERFONTS, CF_PRINTERFONTS},
553 {I_CF_NOVECTORFONTS, CF_NOVECTORFONTS},
554 {I_CF_NOSTYLESEL, CF_NOSTYLESEL},
555 {I_CF_NOSIZESEL, CF_NOSIZESEL},
556 {I_CF_NOOEMFONTS, CF_NOOEMFONTS},
557 {IDOK, 0},
560 return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &cf.Flags);
563 BOOL CALLBACK mwcd_FindSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
566 static struct FlagTableEntry flagTable[] = {
567 {I_FR_DIALOGTERM, FR_DIALOGTERM},
568 {I_FR_DOWN, FR_DOWN},
569 {I_FR_ENABLEHOOK, FR_ENABLEHOOK},
570 {I_FR_ENABLETEMPLATE, FR_ENABLETEMPLATE},
571 {I_FR_ENABLETEMPLATEHANDLE, FR_ENABLETEMPLATEHANDLE},
572 {I_FR_FINDNEXT, FR_FINDNEXT},
573 {I_FR_HIDEMATCHCASE, FR_HIDEMATCHCASE},
574 {I_FR_HIDEWHOLEWORD, FR_HIDEWHOLEWORD},
575 {I_FR_HIDEUPDOWN, FR_HIDEUPDOWN},
576 {I_FR_MATCHCASE, FR_MATCHCASE},
577 {I_FR_NOMATCHCASE, FR_NOMATCHCASE},
578 {I_FR_NOUPDOWN, FR_NOUPDOWN},
579 {I_FR_NOWHOLEWORD, FR_NOWHOLEWORD},
580 {I_FR_REPLACE, FR_REPLACE},
581 {I_FR_REPLACEALL, FR_REPLACEALL},
582 {I_FR_SHOWHELP, FR_SHOWHELP},
583 {I_FR_WHOLEWORD, FR_WHOLEWORD},
584 {IDOK, 0},
587 return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &frS.Flags);
590 BOOL CALLBACK mwcd_PrintSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
592 static struct FlagTableEntry flagTable[] = {
593 {I_PD_ALLPAGES, PD_ALLPAGES},
594 {I_PD_COLLATE, PD_COLLATE},
595 {I_PD_DISABLEPRINTTOFILE, PD_DISABLEPRINTTOFILE},
596 {I_PD_ENABLEPRINTHOOK, PD_ENABLEPRINTHOOK},
597 {I_PD_ENABLEPRINTTEMPLATE, PD_ENABLEPRINTTEMPLATE},
598 {I_PD_ENABLEPRINTTEMPLATEHANDLE, PD_ENABLEPRINTTEMPLATEHANDLE},
599 {I_PD_ENABLESETUPHOOK, PD_ENABLESETUPHOOK},
600 {I_PD_ENABLESETUPTEMPLATE, PD_ENABLESETUPTEMPLATE},
601 {I_PD_ENABLESETUPTEMPLATEHANDLE, PD_ENABLESETUPTEMPLATEHANDLE},
602 {I_PD_HIDEPRINTTOFILE, PD_HIDEPRINTTOFILE},
603 {I_PD_NOPAGENUMS, PD_NOPAGENUMS},
604 {I_PD_NOSELECTION, PD_NOSELECTION},
605 {I_PD_NOWARNING, PD_NOWARNING},
606 {I_PD_PAGENUMS, PD_PAGENUMS},
607 {I_PD_PRINTSETUP, PD_PRINTSETUP},
608 {I_PD_PRINTTOFILE, PD_PRINTTOFILE},
609 {I_PD_RETURNDC, PD_RETURNDC},
610 {I_PD_RETURNDEFAULT, PD_RETURNDEFAULT},
611 {I_PD_RETURNIC, PD_RETURNIC},
612 {I_PD_SELECTION, PD_SELECTION},
613 {I_PD_SHOWHELP, PD_SHOWHELP},
614 {I_PD_USEDEVMODECOPIES, PD_USEDEVMODECOPIES},
615 {IDOK, 0},
618 return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &pd.Flags);
621 BOOL CALLBACK mwcd_FileSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
623 static struct FlagTableEntry flagTable[] = {
624 {I_OFN_ALLOWMULTISELECT, OFN_ALLOWMULTISELECT},
625 {I_OFN_CREATEPROMPT, OFN_CREATEPROMPT},
626 {I_OFN_ENABLEHOOK, OFN_ENABLEHOOK},
627 {I_OFN_ENABLETEMPLATE, OFN_ENABLETEMPLATE},
628 {I_OFN_ENABLETEMPLATEHANDLE, OFN_ENABLETEMPLATEHANDLE},
629 {I_OFN_EXTENSIONDIFFERENT, OFN_EXTENSIONDIFFERENT},
630 {I_OFN_FILEMUSTEXIST, OFN_FILEMUSTEXIST},
631 {I_OFN_HIDEREADONLY, OFN_HIDEREADONLY},
632 {I_OFN_NOCHANGEDIR, OFN_NOCHANGEDIR},
633 {I_OFN_NOREADONLYRETURN, OFN_NOREADONLYRETURN},
634 {I_OFN_NOTESTFILECREATE, OFN_NOTESTFILECREATE},
635 {I_OFN_NOVALIDATE, OFN_NOVALIDATE},
636 {I_OFN_OVERWRITEPROMPT, OFN_OVERWRITEPROMPT},
637 {I_OFN_PATHMUSTEXIST, OFN_PATHMUSTEXIST},
638 {I_OFN_READONLY, OFN_READONLY},
639 {I_OFN_SHAREAWARE, OFN_SHAREAWARE},
640 {I_OFN_SHOWHELP, OFN_SHOWHELP},
641 {IDOK, 0},
644 return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &pd.Flags);
647 BOOL CALLBACK mwcd_About(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
649 (void) wParam;
650 (void) lParam;
652 switch(uMsg) {
653 case WM_INITDIALOG: return TRUE; /* let WINDOWS set the focus. */
654 case WM_COMMAND: EndDialog(hWnd, 0); return TRUE; /* it's our OK button. */
655 default: return FALSE; /* it's something else, let Windows worry about it */
660 * These functions call custom dialog boxes (resource-loaded, if I do this right).
661 * Right now they don't do a heck of a lot, but at some future time
662 * they will muck about with the flags (and be loaded from the flags) of
663 * the CommDlg structures initialized by the mwi_xxx() routines.
666 void mwc_ColorSetup(HWND hWnd)
668 int r = DialogBox(g_hInstance, "Color_Flags_Dialog", hWnd, (DLGPROC) mwcd_ColorSetup);
669 if(r < 0) { MessageBox(hWnd, "Failure opening Color_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
672 void mwc_FontSetup(HWND hWnd)
674 int r = DialogBox(g_hInstance, "Font_Flags_Dialog", hWnd, (DLGPROC) mwcd_FontSetup);
675 if(r < 0) { MessageBox(hWnd, "Failure opening Font_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
678 void mwc_FindReplaceSetup(HWND hWnd)
680 int r = DialogBox(g_hInstance, "Find_Flags_Dialog", hWnd, (DLGPROC) mwcd_FindSetup);
681 if(r < 0) { MessageBox(hWnd, "Failure opening Find_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
684 void mwc_PrintSetup(HWND hWnd)
686 int r = DialogBox(g_hInstance, "Print_Flags_Dialog", hWnd, (DLGPROC) mwcd_PrintSetup);
687 if(r < 0) { MessageBox(hWnd, "Failure opening Print_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
690 void mwc_FileSetup(HWND hWnd)
692 int r = DialogBox(g_hInstance, "File_Flags_Dialog", hWnd, (DLGPROC) mwcd_PrintSetup);
693 if(r < 0) { MessageBox(hWnd, "Failure opening File_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
697 * Main window message dispatcher. Here the messages get chewed up
698 * and spit out. Note the ugly hack for the modeless Find/Replace box;
699 * this looks like it was bolted on with hexhead screws and is now
700 * dangling from Windows like a loose muffler. Sigh.
703 LRESULT CALLBACK EXPORT mainWindowDispatcher(
704 HWND hWnd,
705 UINT uMsg,
706 WPARAM wParam,
707 LPARAM lParam
711 if(uMsg == findMessageId) {
712 FINDREPLACE FAR* lpfr = (FINDREPLACE FAR*) lParam;
713 if(lpfr->Flags & FR_DIALOGTERM) {
714 MessageBox(hWnd, "User closing us down.", "Down", MB_OK);
715 findDialogBox = 0;
717 else if (lpfr->Flags & FR_FINDNEXT) {
718 MessageBox(hWnd, "Finding next occurrence.", "Findnext", MB_OK);
720 else if (lpfr->Flags & FR_REPLACE) {
721 MessageBox(hWnd, "Replacing next occurence.", "Replace", MB_OK);
723 else if (lpfr->Flags & FR_REPLACEALL) {
724 MessageBox(hWnd, "Replacing all occurrences.", "Replace All", MB_OK);
726 else {
727 MessageBox(hWnd, "Eh?", "Eh?", MB_OK);
729 return 1;
731 else switch(uMsg) {
732 case WM_CREATE:
734 * this is always the first message...at least as far as
735 * we are concerned.
737 mwi_InitAll(hWnd);
738 break;
740 case WM_PAINT:
741 /* Well, draw something! */
742 paintMainWindow(hWnd, uMsg, wParam, lParam);
743 break;
745 case WM_DESTROY:
746 /* Uh oh. Eject! Eject! Eject! */
747 PostQuitMessage(0);
748 break;
750 case WM_COMMAND:
751 /* menu or accelerator pressed; do something. */
753 switch(wParam) {
754 case CM_U_EXIT:
755 /* Uh oh. Eject! Eject! Eject! */
756 PostQuitMessage(0);
757 break;
759 /* these actually call the Common Dialogs. */
761 case CM_U_COLOR:
762 mw_ColorSetup(hWnd); return 1;
764 case CM_U_FONT:
765 mw_FontSetup(hWnd); return 1;
767 case CM_U_FIND:
768 mw_FindSetup(hWnd); return 1;
770 case CM_U_REPLACE:
771 mw_ReplaceSetup(hWnd); return 1;
773 case CM_U_OPEN:
774 mw_OpenSetup(hWnd); return 1;
776 case CM_U_SAVE:
777 mw_SaveSetup(hWnd); return 1;
779 case CM_U_PSETUP:
780 mw_PSetupSetup(hWnd); return 1;
782 case CM_U_PRINT:
783 mw_PrintSetup(hWnd); return 1;
786 * these set up various flags and values in the Common Dialog
787 * data structures, which are currently stored in static memory.
788 * The control dialogs themselves are resources as well.
791 case CM_F_FILE:
792 mwc_FileSetup(hWnd); return 1;
794 case CM_F_COLOR:
795 mwc_ColorSetup(hWnd); return 1;
797 case CM_F_FONT:
798 mwc_FontSetup(hWnd); return 1;
800 case CM_F_FINDREPLACE:
801 mwc_FindReplaceSetup(hWnd); return 1;
803 case CM_F_PRINT:
804 mwc_PrintSetup(hWnd); return 1;
806 case CM_H_ABOUT:
807 DialogBox(g_hInstance, "AboutDialog", hWnd, (DLGPROC) mwcd_About);
808 return 1;
809 case CM_H_USAGE:
810 DialogBox(g_hInstance, "UsageDialog", hWnd, (DLGPROC) mwcd_About);
811 /* return value? *What* return value? */
812 return 1;
814 default:
815 nyi(hWnd); return 1;
817 break;
819 default:
820 return DefWindowProc(hWnd, uMsg, wParam, lParam);
822 return 0;
825 /* Class registration. One might call this a Windowsism. */
827 int registerMainWindowClass(HINSTANCE hInstance)
829 WNDCLASS wndClass;
831 wndClass.style = CS_HREDRAW|CS_VREDRAW;
832 wndClass.lpfnWndProc = mainWindowDispatcher;
833 wndClass.cbClsExtra = 0;
834 wndClass.cbWndExtra = 0;
835 wndClass.hInstance = hInstance;
836 #if 0
837 wndClass.hIcon = LoadIcon(hInstance, "whello");
838 wndClass.hCursor = LoadCursor(hInstance, IDC_ARROW);
839 #endif
840 wndClass.hIcon = 0;
841 wndClass.hCursor = 0;
842 wndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
843 wndClass.lpszMenuName = menuName;
844 wndClass.lpszClassName = className;
846 return RegisterClass(&wndClass);
850 * Another Windowsism; this one's not too bad, as it compares
851 * favorably with CreateWindow() in X (mucking about with X Visuals
852 * can get messy; at least here we don't have to worry about that).
855 HWND createMainWindow(HINSTANCE hInstance, int show)
857 HWND hWnd;
859 hWnd = CreateWindow(
860 className, /* classname */
861 windowName, /* windowname/title */
862 WS_OVERLAPPEDWINDOW, /* dwStyle */
863 0, /* x */
864 0, /* y */
865 CW_USEDEFAULT, /* width */
866 CW_USEDEFAULT, /* height */
867 0, /* parent window */
868 0, /* menu */
869 hInstance, /* instance */
870 0 /* passthrough for MDI */
873 if(hWnd==0) return 0;
875 ShowWindow(hWnd, show);
876 UpdateWindow(hWnd);
878 return hWnd;
881 int messageLoop(HINSTANCE hInstance, HWND hWnd)
883 MSG msg;
885 (void) hInstance;
886 (void) hWnd;
888 while(GetMessage(&msg, 0, 0, 0)) {
889 TranslateMessage(&msg);
890 DispatchMessage(&msg);
893 return msg.wParam;
897 * Oh, did we tell you that main() isn't the name of the
898 * thing called in a Win16/Win32 app? And then there are
899 * the lack of argument lists, the necessity (at least in Win16)
900 * of having to deal with class registration exactly once (as the
901 * app may be run again), and some other bizarre holdovers from
902 * Windows 3.x days. But hey, Solitaire still works.
905 int PASCAL WinMain(
906 HINSTANCE hInstance, HINSTANCE hPrevInstance,
907 LPSTR lpszCmdLine, int nCmdShow
910 HWND hWnd;
912 (void) lpszCmdLine;
914 strcpy(ofn_result, "--- not yet set ---");
916 if(hPrevInstance==0) {
917 if(!registerMainWindowClass(hInstance))
918 return -1;
921 g_hInstance = hInstance;
923 hWnd = createMainWindow(hInstance,nCmdShow);
924 if(hWnd == 0)
925 return -1;
927 return messageLoop(hInstance, hWnd);
930 /* And now the end of the program. Enjoy. */
933 * (c) 1999-2000 Eric Williams. Rights as specified under the WINE
934 * License. Don't hoard code; share it!