| // (c) 1999 Eric Williams. Rights as specified under the WINE | |
| // License. Don't hoard code; share it! | |
| // | |
| // One might call this a Commdlg test jig. Its sole function in life | |
| // is to call the Commdlg Common Dialogs; at present it doesn't even | |
| // do anything horribly interesting with the results. | |
| // Ideally it would also do event logging and be a bit less stupid | |
| // about displaying the results of the various requesters. But hey, | |
| // it's only a first step. :-) | |
| #include <windows.h> | |
| #include <commdlg.h> | |
| #include <stdio.h> | |
| #include "cmdlgtst.h" | |
| // This structure is to set up flag / control associations for the custom | |
| // requesters. The ft_id is the id for the control (usually generated | |
| // by the system) and the ft_bit is the flag bit which goes into the | |
| // settings longword for the various Commdlg structures. It is assumed | |
| // that all flags fit in an unsigned long and that all bits are in fact | |
| // one bit. | |
| // The array of entries is terminated by {IDOK, 0}; the assumption is that | |
| // IDOK would never be associated with a dialogbox control (since it's | |
| // usually the ID of the OK button}. | |
| struct FlagTableEntry { | |
| int ft_id; | |
| unsigned long ft_bit; | |
| }; | |
| // #ifdef __WINE_WINDOWS_H | |
| // #define EXPORT | |
| // #define HWND HWND32 | |
| // int ctx_debug = 0; | |
| // #else | |
| // #define EXPORT _export | |
| // #endif | |
| //#define FAR | |
| #define EXPORT | |
| static char menuName[] = "TestCommdlgMenu"; | |
| static char className[] = "TestCommdlg"; | |
| static char windowName[] = "TestCommdlg Window"; | |
| // global hInstance variable. This makes the code non-threadable, | |
| // but wotthehell; this is Win32 anyway! (Though it does work | |
| // under Win16, if one doesn't run more than one copy at a time.) | |
| static HINSTANCE g_hInstance; | |
| // global CommDlg data structures for modals. These are placed here | |
| // so that the custom dialog boxes can get at them. | |
| static PRINTDLG pd; | |
| static COLORREF cc_cr[16]; | |
| static CHOOSECOLOR cc; | |
| static LOGFONT cf_lf; | |
| static CHOOSEFONT cf; | |
| static char ofn_filepat[] = "All Files (*.*)\0*.*\0Only Text Files (*.txt)\0*.txt\0"; | |
| static char ofn_result[1024]; | |
| static OPENFILENAME ofn; | |
| // Stuff for find and replace. These are modeless, so I have to put them here. | |
| static HWND findDialogBox = 0; | |
| static UINT findMessageId = 0; | |
| static int findDialogBoxInit = 0; | |
| static int findDialogStructInit = 0; | |
| static FINDREPLACE frS; | |
| static char fromstring[1024], tostring[1024]; | |
| // Stuff for the drawing of the window(s). I put them here for convenience. | |
| static COLORREF fgColor = RGB(0, 0, 0); // not settable | |
| static COLORREF bgColor = RGB(255, 255, 255); | |
| static COLORREF txtColor = RGB(0, 0, 0); | |
| // Utility routines. Currently there is only one, and it's a nasty | |
| // reminder that I'm not done yet. | |
| void nyi(HWND hWnd) | |
| { | |
| MessageBox(hWnd, "Not yet implemented!", "NYI", MB_ICONEXCLAMATION | MB_OK); | |
| } | |
| // Initial initialization code. This code simply shoves in predefined | |
| // data into the COMMDLG data structures; in the future, I might use | |
| // a series of loadable resources, or static initializers; of course, | |
| // if Microsoft decides to change the field ordering, I'd be screwed. | |
| void mwi_Print(HWND hWnd) | |
| { | |
| pd.lStructSize = sizeof(PRINTDLG); | |
| pd.hwndOwner = hWnd; | |
| pd.hDevMode = 0; | |
| pd.hDevNames = 0; | |
| pd.hDC = 0; | |
| pd.Flags = 0; | |
| pd.nMinPage = 1; | |
| pd.nMaxPage = 100; | |
| pd.hInstance = 0; | |
| pd.lCustData = 0; | |
| pd.lpfnPrintHook = 0; | |
| pd.lpfnSetupHook = 0; | |
| pd.lpPrintTemplateName = 0; | |
| pd.lpSetupTemplateName = 0; | |
| pd.hPrintTemplate = 0; | |
| pd.hSetupTemplate = 0; | |
| } | |
| void mwi_Color(HWND hWnd) | |
| { | |
| int i; | |
| // there's probably an init call for this, somewhere. | |
| for(i=0;i<16;i++) | |
| cc_cr[i] = RGB(0,0,0); | |
| cc.lStructSize = sizeof(CHOOSECOLOR); | |
| cc.hwndOwner = hWnd; | |
| cc.hInstance = 0; | |
| cc.rgbResult = RGB(0,0,0); | |
| cc.lpCustColors = cc_cr; | |
| cc.Flags = 0; | |
| cc.lCustData = 0; | |
| cc.lpfnHook = 0; | |
| cc.lpTemplateName = 0; | |
| } | |
| void mwi_Font(HWND hWnd) | |
| { | |
| cf.lStructSize = sizeof(CHOOSEFONT); | |
| cf.hwndOwner = hWnd; | |
| cf.hDC = 0; | |
| cf.lpLogFont = &cf_lf; | |
| cf.Flags = 0; | |
| cf.rgbColors = RGB(0,0,0); // what is *this* doing here?? | |
| cf.lCustData = 0; | |
| cf.lpfnHook = 0; | |
| cf.lpTemplateName = 0; | |
| cf.hInstance = 0; | |
| cf.lpszStyle = 0; | |
| cf.nFontType = 0; | |
| cf.nSizeMin = 8; | |
| cf.nSizeMax = 72; | |
| } | |
| void mwi_File(HWND hWnd) | |
| { | |
| ofn.lStructSize = sizeof(OPENFILENAME); | |
| ofn.hwndOwner = hWnd; | |
| ofn.hInstance = 0; | |
| ofn.lpstrFilter = (LPSTR) ofn_filepat; | |
| ofn.lpstrCustomFilter = 0; | |
| ofn.nMaxCustFilter = 0; | |
| ofn.nFilterIndex = 0; | |
| ofn.lpstrFile = ofn_result; | |
| ofn.nMaxFile = sizeof(ofn_result); | |
| ofn.lpstrFileTitle = 0; | |
| ofn.nMaxFileTitle = 0; | |
| ofn.lpstrInitialDir = 0; | |
| ofn.lpstrTitle = "Open File"; | |
| ofn.Flags = 0; | |
| ofn.nFileOffset = 0; | |
| ofn.nFileExtension = 0; | |
| ofn.lpstrDefExt = "*"; | |
| ofn.lCustData = 0; | |
| ofn.lpfnHook = 0; | |
| ofn.lpTemplateName = 0; | |
| ofn_result[0] = '\0'; | |
| } | |
| void mwi_FindReplace(HWND hWnd) | |
| { | |
| frS.lStructSize = sizeof(FINDREPLACE); | |
| frS.hwndOwner = hWnd; | |
| frS.hInstance = 0; | |
| frS.Flags = FR_DOWN; | |
| frS.lpstrFindWhat = fromstring; | |
| frS.lpstrReplaceWith = tostring; | |
| frS.wFindWhatLen = sizeof(fromstring); | |
| frS.wReplaceWithLen = sizeof(tostring); | |
| frS.lCustData = 0; | |
| frS.lpfnHook = 0; | |
| frS.lpTemplateName = 0; | |
| fromstring[0] = '\0'; | |
| tostring[0] = '\0'; | |
| findMessageId = RegisterWindowMessage(FINDMSGSTRING); | |
| } | |
| void mwi_InitAll(HWND hWnd) | |
| { | |
| mwi_Print(hWnd); | |
| mwi_Font(hWnd); | |
| mwi_Color(hWnd); | |
| mwi_File(hWnd); | |
| mwi_FindReplace(hWnd); | |
| } | |
| // Various configurations for the window. Ideally, this | |
| // would be stored with the window itself, but then, this | |
| // isn't the brightest of apps. Wouldn't be hard to set up, | |
| // though -- one of the neater functions of Windows, but if | |
| // someone decides to load the windows themselves from resources, | |
| // there might be a problem. | |
| void paintMainWindow(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) | |
| { | |
| PAINTSTRUCT ps; | |
| RECT rect; | |
| HPEN pen; | |
| HFONT font; | |
| HBRUSH brush; | |
| // Commence painting! | |
| BeginPaint(hWnd, &ps); | |
| GetClientRect(hWnd, (LPRECT) &rect); | |
| pen = (HPEN) SelectObject(ps.hdc, CreatePen(0, 0, fgColor)); | |
| brush = (HBRUSH) SelectObject(ps.hdc, CreateSolidBrush(bgColor)); | |
| font = (HFONT) SelectObject(ps.hdc, CreateFontIndirect(&cf_lf)); | |
| // only need to draw the exposed bit. | |
| Rectangle(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom); | |
| // now draw a couple of lines, just for giggles. | |
| MoveToEx(ps.hdc, rect.left, rect.top, (POINT FAR *) 0); | |
| LineTo(ps.hdc, rect.right, rect.bottom); | |
| MoveToEx(ps.hdc, rect.left, rect.bottom, (POINT FAR *) 0); | |
| LineTo(ps.hdc, rect.right, rect.top); | |
| // draw some text | |
| SetTextAlign(ps.hdc, TA_CENTER|TA_BASELINE); | |
| SetTextColor(ps.hdc, txtColor); | |
| TextOut(ps.hdc, (rect.left+rect.right)/2, (rect.top+rect.bottom)/2, "Common Dialog Test Page", 23); | |
| SetTextAlign(ps.hdc, TA_LEFT|TA_TOP); | |
| TextOut(ps.hdc, rect.left, rect.top, ofn_result, strlen(ofn_result)); | |
| // set the HDC back to the old pen and brush, | |
| // and delete the newly created objects. | |
| pen = (HPEN) SelectObject(ps.hdc, pen); | |
| DeleteObject(pen); | |
| brush = (HBRUSH) SelectObject(ps.hdc, brush); | |
| DeleteObject(brush); | |
| font = (HFONT) SelectObject(ps.hdc, font); | |
| DeleteObject(font); | |
| EndPaint(hWnd, &ps); | |
| } | |
| // This function simply returns an error indication. Naturally, | |
| // I do not (yet) see an elegant method by which one can convert | |
| // the CDERR_xxx return values into something resembling usable text; | |
| // consult cderr.h to see what was returned. | |
| void mw_checkError(HWND hWnd, BOOL explicitcancel) | |
| { | |
| DWORD errval = CommDlgExtendedError(); | |
| if(errval) { | |
| char errbuf[80]; | |
| sprintf(errbuf, "CommDlgExtendedError(): error code %ld (0x%lx)", errval, errval); | |
| MessageBox(hWnd, errbuf, "Error", MB_ICONEXCLAMATION | MB_OK); | |
| } | |
| else { | |
| if(explicitcancel) MessageBox(hWnd, "Nope, user canceled it.", "No", MB_OK); | |
| } | |
| } | |
| // The actual dialog function calls. These merely wrap the Commdlg | |
| // calls, and do something (not so) intelligent with the result. | |
| // Ideally, the main window would refresh and take into account the | |
| // various values specified in the dialog. | |
| void mw_ColorSetup(HWND hWnd) | |
| { | |
| if(ChooseColor(&cc)) { | |
| RECT rect; | |
| GetClientRect(hWnd, (LPRECT) &rect); | |
| InvalidateRect(hWnd, (LPRECT) &rect, FALSE); | |
| bgColor = cc.rgbResult; | |
| } | |
| else mw_checkError(hWnd, FALSE); | |
| } | |
| void mw_FontSetup(HWND hWnd) | |
| { | |
| if(ChooseFont(&cf)) { | |
| RECT rect; | |
| GetClientRect(hWnd, (LPRECT) &rect); | |
| InvalidateRect(hWnd, (LPRECT) &rect, FALSE); | |
| txtColor = cf.rgbColors; | |
| } | |
| else mw_checkError(hWnd, FALSE); | |
| } | |
| void mw_FindSetup(HWND hWnd) | |
| { | |
| if(findDialogBox == 0) { | |
| findDialogBox = FindText(&frS); | |
| if(findDialogBox==0) mw_checkError(hWnd,TRUE); | |
| } | |
| } | |
| void mw_ReplaceSetup(HWND hWnd) | |
| { | |
| if(findDialogBox == 0) { | |
| findDialogBox = ReplaceText(&frS); | |
| if(findDialogBox==0) mw_checkError(hWnd,TRUE); | |
| } | |
| } | |
| void mw_OpenSetup(HWND hWnd) | |
| { | |
| if(GetOpenFileName(&ofn)) { | |
| RECT rect; | |
| GetClientRect(hWnd, (LPRECT) &rect); | |
| InvalidateRect(hWnd, (LPRECT) &rect, FALSE); | |
| } | |
| else mw_checkError(hWnd,FALSE); | |
| } | |
| void mw_SaveSetup(HWND hWnd) | |
| { | |
| if(GetSaveFileName(&ofn)) { | |
| RECT rect; | |
| GetClientRect(hWnd, (LPRECT) &rect); | |
| InvalidateRect(hWnd, (LPRECT) &rect, FALSE); | |
| } | |
| else mw_checkError(hWnd,FALSE); | |
| } | |
| // Can't find documentation in Borland for this one. Does it | |
| // exist at all, or is it merely a subdialog of Print? | |
| void mw_PSetupSetup(HWND hWnd) | |
| { | |
| nyi(hWnd); | |
| } | |
| void mw_PrintSetup(HWND hWnd) | |
| { | |
| if(PrintDlg(&pd)) { | |
| // the following are suggested in the Borland documentation, | |
| // but aren't that useful until WinE starts to actually | |
| // function with respect to printing. | |
| // Escape(tmp.hDC, STARTDOC, 8, "Test-Doc", NULL); | |
| /* Print text and rectangle */ | |
| // TextOut(tmp.hDC, 50, 50, "Common Dialog Test Page", 23); | |
| // Rectangle(tmp.hDC, 50, 90, 625, 105); | |
| // Escape(tmp.hDC, NEWFRAME, 0, NULL, NULL); | |
| // Escape(tmp.hDC, ENDDOC, 0, NULL, NULL); | |
| // DeleteDC(tmp.hDC); | |
| if (pd.hDevMode != NULL) | |
| GlobalFree(pd.hDevMode); | |
| if (pd.hDevNames != NULL) | |
| GlobalFree(pd.hDevNames); | |
| pd.hDevMode = 0; | |
| pd.hDevNames = 0; | |
| MessageBox(hWnd, "Success.", "Yes", MB_OK); | |
| } | |
| else mw_checkError(hWnd,TRUE); | |
| } | |
| // Some support functions for the custom dialog box handlers. | |
| // In particular, we have to set things properly, and get the flags back. | |
| void mwcd_SetFlags(HWND hWnd, struct FlagTableEntry *table, unsigned long flags) | |
| { | |
| int i; | |
| for(i=0; table[i].ft_id != IDOK; i++) | |
| { | |
| CheckDlgButton(hWnd, table[i].ft_id,(table[i].ft_bit & flags) ? 1 : 0); | |
| } | |
| } | |
| unsigned long mwcd_GetFlags(HWND hWnd, struct FlagTableEntry * table) | |
| { | |
| int i; | |
| unsigned long l = 0; | |
| for(i=0; table[i].ft_id != IDOK; i++) | |
| { | |
| if(IsDlgButtonChecked(hWnd, table[i].ft_id) == 1) | |
| l |= table[i].ft_bit; | |
| } | |
| return l; | |
| } | |
| // These functions are the custom dialog box handlers. | |
| // The division of labor may be a tad peculiar; in particular, | |
| // the flag tables should probably be in the main functions, | |
| // not the handlers. I'll fix that later; this works as of right now. | |
| BOOL mwcd_Setup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, | |
| struct FlagTableEntry * table, unsigned long * flags) | |
| { | |
| switch(uMsg) | |
| { | |
| case WM_INITDIALOG: | |
| // Set the controls properly. | |
| mwcd_SetFlags(hWnd, table, *flags); | |
| return TRUE; // I would return FALSE if I explicitly called SetFocus(). | |
| // As usual, Windows is weird. | |
| case WM_COMMAND: | |
| switch(wParam) { | |
| case IDOK: | |
| *flags = mwcd_GetFlags(hWnd, table); | |
| EndDialog(hWnd,1); | |
| break; | |
| case IDCANCEL: | |
| EndDialog(hWnd,0); | |
| break; | |
| case CM_R_HELP: | |
| break; // help? We don't need no steenkin help! | |
| default: | |
| break; // eat the message | |
| } | |
| return TRUE; | |
| default: | |
| return FALSE; // since I don't process this particular message | |
| } | |
| } | |
| BOOL CALLBACK mwcd_ColorSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | |
| { | |
| static struct FlagTableEntry flagTable[] = { | |
| {I_CC_RGBINIT, CC_RGBINIT}, | |
| {I_CC_SHOWHELP, CC_SHOWHELP}, | |
| {I_CC_PREVENTFULLOPEN, CC_PREVENTFULLOPEN}, | |
| {I_CC_FULLOPEN, CC_FULLOPEN}, | |
| {I_CC_ENABLETEMPLATEHANDLE, CC_ENABLETEMPLATEHANDLE}, | |
| {I_CC_ENABLETEMPLATE, CC_ENABLETEMPLATE}, | |
| {I_CC_ENABLEHOOK, CC_ENABLEHOOK}, | |
| {IDOK, 0}, | |
| }; | |
| return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &cc.Flags); | |
| } | |
| BOOL CALLBACK mwcd_FontSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | |
| { | |
| static struct FlagTableEntry flagTable[] = { | |
| {I_CF_APPLY, CF_APPLY}, | |
| {I_CF_ANSIONLY, CF_ANSIONLY}, | |
| {I_CF_BOTH, CF_BOTH}, | |
| {I_CF_TTONLY, CF_TTONLY}, | |
| {I_CF_EFFECTS, CF_EFFECTS}, | |
| {I_CF_ENABLEHOOK, CF_ENABLEHOOK}, | |
| {I_CF_ENABLETEMPLATE, CF_ENABLETEMPLATE}, | |
| {I_CF_ENABLETEMPLATEHANDLE, CF_ENABLETEMPLATEHANDLE}, | |
| {I_CF_FIXEDPITCHONLY, CF_FIXEDPITCHONLY}, | |
| {I_CF_INITTOLOGFONTSTRUCT, CF_INITTOLOGFONTSTRUCT}, | |
| {I_CF_LIMITSIZE, CF_LIMITSIZE}, | |
| {I_CF_NOFACESEL, CF_NOFACESEL}, | |
| {I_CF_USESTYLE, CF_USESTYLE}, | |
| {I_CF_WYSIWYG, CF_WYSIWYG}, | |
| {I_CF_SHOWHELP, CF_SHOWHELP}, | |
| {I_CF_SCREENFONTS, CF_SCREENFONTS}, | |
| {I_CF_SCALABLEONLY, CF_SCALABLEONLY}, | |
| {I_CF_PRINTERFONTS, CF_PRINTERFONTS}, | |
| {I_CF_NOVECTORFONTS, CF_NOVECTORFONTS}, | |
| {I_CF_NOSTYLESEL, CF_NOSTYLESEL}, | |
| {I_CF_NOSIZESEL, CF_NOSIZESEL}, | |
| {I_CF_NOOEMFONTS, CF_NOOEMFONTS}, | |
| {IDOK, 0}, | |
| }; | |
| return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &cf.Flags); | |
| } | |
| BOOL CALLBACK mwcd_FindSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | |
| { | |
| static struct FlagTableEntry flagTable[] = { | |
| {I_FR_DIALOGTERM, FR_DIALOGTERM}, | |
| {I_FR_DOWN, FR_DOWN}, | |
| {I_FR_ENABLEHOOK, FR_ENABLEHOOK}, | |
| {I_FR_ENABLETEMPLATE, FR_ENABLETEMPLATE}, | |
| {I_FR_ENABLETEMPLATEHANDLE, FR_ENABLETEMPLATEHANDLE}, | |
| {I_FR_FINDNEXT, FR_FINDNEXT}, | |
| {I_FR_HIDEMATCHCASE, FR_HIDEMATCHCASE}, | |
| {I_FR_HIDEWHOLEWORD, FR_HIDEWHOLEWORD}, | |
| {I_FR_HIDEUPDOWN, FR_HIDEUPDOWN}, | |
| {I_FR_MATCHCASE, FR_MATCHCASE}, | |
| {I_FR_NOMATCHCASE, FR_NOMATCHCASE}, | |
| {I_FR_NOUPDOWN, FR_NOUPDOWN}, | |
| {I_FR_NOWHOLEWORD, FR_NOWHOLEWORD}, | |
| {I_FR_REPLACE, FR_REPLACE}, | |
| {I_FR_REPLACEALL, FR_REPLACEALL}, | |
| {I_FR_SHOWHELP, FR_SHOWHELP}, | |
| {I_FR_WHOLEWORD, FR_WHOLEWORD}, | |
| {IDOK, 0}, | |
| }; | |
| return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &frS.Flags); | |
| } | |
| BOOL CALLBACK mwcd_PrintSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | |
| { | |
| static struct FlagTableEntry flagTable[] = { | |
| {I_PD_ALLPAGES, PD_ALLPAGES}, | |
| {I_PD_COLLATE, PD_COLLATE}, | |
| {I_PD_DISABLEPRINTTOFILE, PD_DISABLEPRINTTOFILE}, | |
| {I_PD_ENABLEPRINTHOOK, PD_ENABLEPRINTHOOK}, | |
| {I_PD_ENABLEPRINTTEMPLATE, PD_ENABLEPRINTTEMPLATE}, | |
| {I_PD_ENABLEPRINTTEMPLATEHANDLE, PD_ENABLEPRINTTEMPLATEHANDLE}, | |
| {I_PD_ENABLESETUPHOOK, PD_ENABLESETUPHOOK}, | |
| {I_PD_ENABLESETUPTEMPLATE, PD_ENABLESETUPTEMPLATE}, | |
| {I_PD_ENABLESETUPTEMPLATEHANDLE, PD_ENABLESETUPTEMPLATEHANDLE}, | |
| {I_PD_HIDEPRINTTOFILE, PD_HIDEPRINTTOFILE}, | |
| {I_PD_NOPAGENUMS, PD_NOPAGENUMS}, | |
| {I_PD_NOSELECTION, PD_NOSELECTION}, | |
| {I_PD_NOWARNING, PD_NOWARNING}, | |
| {I_PD_PAGENUMS, PD_PAGENUMS}, | |
| {I_PD_PRINTSETUP, PD_PRINTSETUP}, | |
| {I_PD_PRINTTOFILE, PD_PRINTTOFILE}, | |
| {I_PD_RETURNDC, PD_RETURNDC}, | |
| {I_PD_RETURNDEFAULT, PD_RETURNDEFAULT}, | |
| {I_PD_RETURNIC, PD_RETURNIC}, | |
| {I_PD_SELECTION, PD_SELECTION}, | |
| {I_PD_SHOWHELP, PD_SHOWHELP}, | |
| {I_PD_USEDEVMODECOPIES, PD_USEDEVMODECOPIES}, | |
| {IDOK, 0}, | |
| }; | |
| return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &pd.Flags); | |
| } | |
| BOOL CALLBACK mwcd_FileSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | |
| { | |
| static struct FlagTableEntry flagTable[] = { | |
| {I_OFN_ALLOWMULTISELECT, OFN_ALLOWMULTISELECT}, | |
| {I_OFN_CREATEPROMPT, OFN_CREATEPROMPT}, | |
| {I_OFN_ENABLEHOOK, OFN_ENABLEHOOK}, | |
| {I_OFN_ENABLETEMPLATE, OFN_ENABLETEMPLATE}, | |
| {I_OFN_ENABLETEMPLATEHANDLE, OFN_ENABLETEMPLATEHANDLE}, | |
| {I_OFN_EXTENSIONDIFFERENT, OFN_EXTENSIONDIFFERENT}, | |
| {I_OFN_FILEMUSTEXIST, OFN_FILEMUSTEXIST}, | |
| {I_OFN_HIDEREADONLY, OFN_HIDEREADONLY}, | |
| {I_OFN_NOCHANGEDIR, OFN_NOCHANGEDIR}, | |
| {I_OFN_NOREADONLYRETURN, OFN_NOREADONLYRETURN}, | |
| {I_OFN_NOTESTFILECREATE, OFN_NOTESTFILECREATE}, | |
| {I_OFN_NOVALIDATE, OFN_NOVALIDATE}, | |
| {I_OFN_OVERWRITEPROMPT, OFN_OVERWRITEPROMPT}, | |
| {I_OFN_PATHMUSTEXIST, OFN_PATHMUSTEXIST}, | |
| {I_OFN_READONLY, OFN_READONLY}, | |
| {I_OFN_SHAREAWARE, OFN_SHAREAWARE}, | |
| {I_OFN_SHOWHELP, OFN_SHOWHELP}, | |
| {IDOK, 0}, | |
| }; | |
| return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &pd.Flags); | |
| } | |
| BOOL CALLBACK mwcd_About(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) | |
| { | |
| switch(uMsg) { | |
| case WM_INITDIALOG: return TRUE; // let WINDOWS set the focus. | |
| case WM_COMMAND: EndDialog(hWnd, 0); return TRUE; // it's our OK button. | |
| default: return FALSE; // it's something else, let Windows worry about it | |
| } | |
| } | |
| // These functions call custom dialog boxes (resource-loaded, if I do this right). | |
| // Right now they don't do a heck of a lot, but at some future time | |
| // they will muck about with the flags (and be loaded from the flags) of | |
| // the CommDlg structures initialized by the mwi_xxx() routines. | |
| void mwc_ColorSetup(HWND hWnd) | |
| { | |
| int r = DialogBox(g_hInstance, "Color_Flags_Dialog", hWnd, (DLGPROC) mwcd_ColorSetup); | |
| if(r < 0) { MessageBox(hWnd, "Failure opening Color_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); } | |
| } | |
| void mwc_FontSetup(HWND hWnd) | |
| { | |
| int r = DialogBox(g_hInstance, "Font_Flags_Dialog", hWnd, (DLGPROC) mwcd_FontSetup); | |
| if(r < 0) { MessageBox(hWnd, "Failure opening Font_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); } | |
| } | |
| void mwc_FindReplaceSetup(HWND hWnd) | |
| { | |
| int r = DialogBox(g_hInstance, "Find_Flags_Dialog", hWnd, (DLGPROC) mwcd_FindSetup); | |
| if(r < 0) { MessageBox(hWnd, "Failure opening Find_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); } | |
| } | |
| void mwc_PrintSetup(HWND hWnd) | |
| { | |
| int r = DialogBox(g_hInstance, "Print_Flags_Dialog", hWnd, (DLGPROC) mwcd_PrintSetup); | |
| if(r < 0) { MessageBox(hWnd, "Failure opening Print_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); } | |
| } | |
| void mwc_FileSetup(HWND hWnd) | |
| { | |
| int r = DialogBox(g_hInstance, "File_Flags_Dialog", hWnd, (DLGPROC) mwcd_PrintSetup); | |
| if(r < 0) { MessageBox(hWnd, "Failure opening File_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); } | |
| } | |
| // Main window message dispatcher. Here the messages get chewed up | |
| // and spit out. Note the ugly hack for the modeless Find/Replace box; | |
| // this looks like it was bolted on with hexhead screws and is now | |
| // dangling from Windows like a loose muffler. Sigh. | |
| LRESULT CALLBACK EXPORT mainWindowDispatcher( | |
| HWND hWnd, | |
| UINT uMsg, | |
| WPARAM wParam, | |
| LPARAM lParam | |
| ) | |
| { | |
| if(uMsg == findMessageId) { | |
| FINDREPLACE FAR* lpfr = (FINDREPLACE FAR*) lParam; | |
| if(lpfr->Flags & FR_DIALOGTERM) { | |
| MessageBox(hWnd, "User closing us down.", "Down", MB_OK); | |
| findDialogBox = 0; | |
| } | |
| else if (lpfr->Flags & FR_FINDNEXT) { | |
| MessageBox(hWnd, "Finding next occurrence.", "Findnext", MB_OK); | |
| } | |
| else if (lpfr->Flags & FR_REPLACE) { | |
| MessageBox(hWnd, "Replacing next occurence.", "Replace", MB_OK); | |
| } | |
| else if (lpfr->Flags & FR_REPLACEALL) { | |
| MessageBox(hWnd, "Replacing all occurrences.", "Replace All", MB_OK); | |
| } | |
| else { | |
| MessageBox(hWnd, "Eh?", "Eh?", MB_OK); | |
| } | |
| return 1; | |
| } | |
| else switch(uMsg) { | |
| case WM_CREATE: | |
| // this is always the first message...at least as far as | |
| // we are concerned. | |
| mwi_InitAll(hWnd); | |
| break; | |
| case WM_PAINT: | |
| // Well, draw something! | |
| paintMainWindow(hWnd, uMsg, wParam, lParam); | |
| break; | |
| case WM_DESTROY: | |
| // Uh oh. Eject! Eject! Eject! | |
| PostQuitMessage(0); | |
| break; | |
| case WM_COMMAND: | |
| // menu or accelerator pressed; do something. | |
| switch(wParam) { | |
| case CM_U_EXIT: | |
| // Uh oh. Eject! Eject! Eject! | |
| PostQuitMessage(0); | |
| break; | |
| // these actually call the Common Dialogs. | |
| case CM_U_COLOR: | |
| mw_ColorSetup(hWnd); return 1; | |
| case CM_U_FONT: | |
| mw_FontSetup(hWnd); return 1; | |
| case CM_U_FIND: | |
| mw_FindSetup(hWnd); return 1; | |
| case CM_U_REPLACE: | |
| mw_ReplaceSetup(hWnd); return 1; | |
| case CM_U_OPEN: | |
| mw_OpenSetup(hWnd); return 1; | |
| case CM_U_SAVE: | |
| mw_SaveSetup(hWnd); return 1; | |
| case CM_U_PSETUP: | |
| mw_PSetupSetup(hWnd); return 1; | |
| case CM_U_PRINT: | |
| mw_PrintSetup(hWnd); return 1; | |
| // these set up various flags and values in the Common Dialog | |
| // data structures, which are currently stored in static memory. | |
| // The control dialogs themselves are resources as well. | |
| case CM_F_FILE: | |
| mwc_FileSetup(hWnd); return 1; | |
| case CM_F_COLOR: | |
| mwc_ColorSetup(hWnd); return 1; | |
| case CM_F_FONT: | |
| mwc_FontSetup(hWnd); return 1; | |
| case CM_F_FINDREPLACE: | |
| mwc_FindReplaceSetup(hWnd); return 1; | |
| case CM_F_PRINT: | |
| mwc_PrintSetup(hWnd); return 1; | |
| case CM_H_ABOUT: | |
| DialogBox(g_hInstance, "AboutDialog", hWnd, (DLGPROC) mwcd_About); | |
| case CM_H_USAGE: | |
| DialogBox(g_hInstance, "UsageDialog", hWnd, (DLGPROC) mwcd_About); | |
| // return value? *What* return value? | |
| return 1; | |
| default: | |
| nyi(hWnd); return 1; | |
| } | |
| break; | |
| default: | |
| return DefWindowProc(hWnd, uMsg, wParam, lParam); | |
| } | |
| return 0; | |
| } | |
| // Class registration. One might call this a Windowsism. | |
| int registerMainWindowClass(HINSTANCE hInstance) | |
| { | |
| WNDCLASS wndClass; | |
| wndClass.style = CS_HREDRAW|CS_VREDRAW; | |
| wndClass.lpfnWndProc = mainWindowDispatcher; | |
| wndClass.cbClsExtra = 0; | |
| wndClass.cbWndExtra = 0; | |
| wndClass.hInstance = hInstance; | |
| //wndClass.hIcon = LoadIcon(hInstance, "whello"); | |
| //wndClass.hCursor = LoadCursor(hInstance, IDC_ARROW); | |
| wndClass.hIcon = 0; | |
| wndClass.hCursor = 0; | |
| wndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); | |
| wndClass.lpszMenuName = menuName; | |
| wndClass.lpszClassName = className; | |
| return RegisterClass(&wndClass); | |
| } | |
| // Another Windowsism; this one's not too bad, as it compares | |
| // favorably with CreateWindow() in X (mucking about with X Visuals | |
| // can get messy; at least here we don't have to worry about that). | |
| HWND createMainWindow(HINSTANCE hInstance, int show) | |
| { | |
| HWND hWnd; | |
| hWnd = CreateWindow( | |
| className, // classname | |
| windowName, // windowname/title | |
| WS_OVERLAPPEDWINDOW, // dwStyle | |
| 0, //x | |
| 0, //y | |
| CW_USEDEFAULT, //width | |
| CW_USEDEFAULT, //height | |
| 0, // parent window | |
| 0, // menu | |
| hInstance, // instance | |
| 0 // passthrough for MDI | |
| ); | |
| if(hWnd==0) return 0; | |
| ShowWindow(hWnd, show); | |
| UpdateWindow(hWnd); | |
| return hWnd; | |
| } | |
| int messageLoop(HINSTANCE hInstance, HWND hWnd) | |
| { | |
| MSG msg; | |
| while(GetMessage(&msg, 0, 0, 0)) { | |
| TranslateMessage(&msg); | |
| DispatchMessage(&msg); | |
| } | |
| return msg.wParam; | |
| } | |
| // Oh, did we tell you that main() isn't the name of the | |
| // thing called in a Win16/Win32 app? And then there are | |
| // the lack of argument lists, the necessity (at least in Win16) | |
| // of having to deal with class registration exactly once (as the | |
| // app may be run again), and some other bizarre holdovers from | |
| // Windows 3.x days. But hey, Solitaire still works. | |
| int PASCAL WinMain( | |
| HINSTANCE hInstance, HINSTANCE hPrevInstance, | |
| LPSTR lpszCmdLine, int nCmdShow | |
| ) | |
| { | |
| HWND hWnd; | |
| strcpy(ofn_result, "--- not yet set ---"); | |
| if(hPrevInstance==0) { | |
| if(!registerMainWindowClass(hInstance)) | |
| return -1; | |
| } | |
| g_hInstance = hInstance; | |
| hWnd = createMainWindow(hInstance,nCmdShow); | |
| if(hWnd == 0) | |
| return -1; | |
| return messageLoop(hInstance, hWnd); | |
| } | |
| // And now the end of the program. Enjoy. | |
| // (c) 1999 Eric Williams. Rights as specified under the WINE | |
| // License. Don't hoard code; share it! | |