| /* |
| * Copyright (c) 1999-2000 Eric Williams. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| /* |
| * One might call this a Commdlg test jig. Its sole function in life |
| * is to call the Commdlg Common Dialogs. The results of a call to |
| * File Open or File Save are printed in the upper left corner; |
| * Font adjusts the font of the printout, and Color adjusts the color |
| * of the background. |
| */ |
| |
| /* |
| * 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. :-) |
| */ |
| |
| #define NONAMELESSUNION |
| #define NONAMELESSSTRUCT |
| |
| #include <windows.h> |
| #include <commdlg.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include "cmdlgtst.h" |
| |
| #include <wine/debug.h> |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(cmdlgtst); |
| |
| /* |
| * 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; |
| }; |
| |
| #define EXPORT |
| |
| static const char menuName[] = "CmdlgtstMenu"; |
| static const char className[] = "CmdlgtstClass"; |
| static const char windowName[] = "Cmdlgtst 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 PAGESETUPDLG psd; |
| static PRINTDLG pd; |
| static COLORREF cc_cr[16]; |
| static CHOOSECOLOR cc; |
| static LOGFONT cf_lf; |
| static CHOOSEFONT cf; |
| static const char ofn_filepat[] = "All Files (*.*)\0*.*\0Only Text Files (*.txt)\0*.txt\0"; |
| static char ofn_result[1024]; |
| static char ofn_titleresult[128]; |
| 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 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); /* COLOR dialog */ |
| static COLORREF txtColor = RGB(0, 0, 0); /* settable if one enables CF_EFFECTS */ |
| |
| /* Utility routines. */ |
| |
| static void nyi(HWND hWnd) |
| { |
| /* "Hi there! I'm not yet implemented!" */ |
| MessageBox(hWnd, "Not yet implemented!", "NYI", MB_ICONEXCLAMATION | MB_OK); |
| } |
| |
| #if 0 |
| static UINT CALLBACK dummyfnHook(HWND hWnd, UINT msg, UINT wParam, UINT lParam) |
| { |
| /* |
| * If the user specifies something that needs an awfully stupid hook function, |
| * this is the one to use. It's a no-op, and says "I didn't do anything." |
| */ |
| |
| (void) hWnd; |
| (void) msg; |
| (void) wParam; |
| (void) lParam; |
| |
| WINE_TRACE("dummyfnhook\n"); /* visible under Wine, but Windows probably won't see it! */ |
| |
| return 0; |
| } |
| #endif |
| |
| /* |
| * 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. |
| */ |
| |
| static 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 = g_hInstance; |
| pd.lCustData = 0; |
| pd.lpfnPrintHook = 0; |
| pd.lpfnSetupHook = 0; |
| pd.lpPrintTemplateName = 0; |
| pd.lpSetupTemplateName = 0; |
| pd.hPrintTemplate = 0; |
| pd.hSetupTemplate = 0; |
| } |
| |
| static void mwi_PageSetup(HWND hWnd) |
| { |
| ZeroMemory(&psd, sizeof(PAGESETUPDLG)); |
| psd.lStructSize = sizeof(PAGESETUPDLG); |
| psd.hwndOwner = hWnd; |
| |
| } |
| |
| static 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 = (HWND)g_hInstance; /* Should be an HINSTANCE but MS made a typo */ |
| cc.rgbResult = RGB(0,0,0); |
| cc.lpCustColors = cc_cr; |
| cc.Flags = 0; |
| cc.lCustData = 0; |
| cc.lpfnHook = 0; |
| cc.lpTemplateName = 0; |
| } |
| |
| static void mwi_Font(HWND hWnd) |
| { |
| cf.lStructSize = sizeof(CHOOSEFONT); |
| cf.hwndOwner = hWnd; |
| cf.hDC = 0; |
| cf.lpLogFont = &cf_lf; |
| cf.Flags = CF_SCREENFONTS; /* something's needed for display; otherwise it craps out with an error */ |
| cf.rgbColors = RGB(0,0,0); /* what is *this* doing here?? */ |
| cf.lCustData = 0; |
| cf.lpfnHook = 0; |
| cf.lpTemplateName = 0; |
| cf.hInstance = g_hInstance; |
| cf.lpszStyle = 0; |
| cf.nFontType = 0; |
| cf.nSizeMin = 8; |
| cf.nSizeMax = 72; |
| |
| cf_lf.lfHeight = -18; /* this can be positive or negative, but negative is usually used. */ |
| } |
| |
| static void mwi_File(HWND hWnd) |
| { |
| ofn.lStructSize = sizeof(OPENFILENAME); |
| ofn.hwndOwner = hWnd; |
| ofn.hInstance = g_hInstance; |
| ofn.lpstrFilter = ofn_filepat; |
| ofn.lpstrCustomFilter = 0; |
| ofn.nMaxCustFilter = 0; |
| ofn.nFilterIndex = 0; |
| ofn.lpstrFile = ofn_result; |
| ofn.nMaxFile = sizeof(ofn_result); |
| ofn.lpstrFileTitle = ofn_titleresult; |
| ofn.nMaxFileTitle = sizeof(ofn_titleresult); |
| 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'; |
| } |
| |
| static void mwi_FindReplace(HWND hWnd) |
| { |
| frS.lStructSize = sizeof(FINDREPLACE); |
| frS.hwndOwner = hWnd; |
| frS.hInstance = g_hInstance; |
| 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); |
| } |
| |
| static void mwi_InitAll(HWND hWnd) |
| { |
| mwi_Print(hWnd); |
| mwi_Font(hWnd); |
| mwi_Color(hWnd); |
| mwi_File(hWnd); |
| mwi_FindReplace(hWnd); |
| mwi_PageSetup(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. |
| */ |
| |
| static void paintMainWindow(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) |
| { |
| PAINTSTRUCT ps; |
| RECT rect; |
| HPEN pen; |
| HFONT font; |
| HBRUSH brush; |
| |
| (void) iMessage; |
| (void) wParam; |
| (void) lParam; |
| |
| /* 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)); |
| |
| /* |
| * Ideally, we'd only need to draw the exposed bit. |
| * But something in BeginPaint is screwing up the rectangle. |
| * Either that, or Windows is drawing it wrong. AARGH! |
| * Rectangle(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom); |
| */ |
| Rectangle(ps.hdc, rect.left, rect.top, rect.right, rect.bottom); |
| |
| /* now draw a couple of lines, just for giggles. */ |
| |
| MoveToEx(ps.hdc, rect.left, rect.top, (POINT *) 0); |
| LineTo(ps.hdc, rect.right, rect.bottom); |
| MoveToEx(ps.hdc, rect.left, rect.bottom, (POINT *) 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+10, rect.top+10, ofn_result, strlen(ofn_result)); |
| TextOut(ps.hdc, rect.left+10, rect.top-cf_lf.lfHeight+10, ofn_titleresult, strlen(ofn_titleresult)); |
| |
| /* |
| * 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. |
| */ |
| |
| static void mw_checkError(HWND hWnd, BOOL explicitcancel) |
| { |
| DWORD errval = CommDlgExtendedError(); |
| if(errval) { |
| char errbuf[80]; |
| |
| sprintf(errbuf, "CommDlgExtendedError(): error code %d (0x%x)", 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. |
| */ |
| |
| static 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); |
| } |
| |
| static 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); |
| } |
| |
| static void mw_FindSetup(HWND hWnd) |
| { |
| if(findDialogBox == 0) { |
| findDialogBox = FindText(&frS); |
| if(findDialogBox==0) mw_checkError(hWnd,TRUE); |
| } |
| } |
| |
| static void mw_ReplaceSetup(HWND hWnd) |
| { |
| if(findDialogBox == 0) { |
| findDialogBox = ReplaceText(&frS); |
| if(findDialogBox==0) mw_checkError(hWnd,TRUE); |
| } |
| } |
| |
| static void mw_OpenSetup(HWND hWnd) |
| { |
| if(GetOpenFileName(&ofn)) { |
| RECT rect; |
| GetClientRect(hWnd, (LPRECT) &rect); |
| InvalidateRect(hWnd, (LPRECT) &rect, FALSE); |
| } |
| else mw_checkError(hWnd,FALSE); |
| } |
| |
| static 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? |
| */ |
| |
| static void mw_PSetupSetup(HWND hWnd) |
| { |
| nyi(hWnd); |
| } |
| |
| static 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. |
| */ |
| |
| #if 0 |
| Escape(tmp.hDC, STARTDOC, 8, "Test-Doc", NULL); |
| #endif |
| |
| /* Print text and rectangle */ |
| |
| #if 0 |
| 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); |
| #endif |
| if (pd.hDevMode != 0) |
| GlobalFree(pd.hDevMode); |
| if (pd.hDevNames != 0) |
| GlobalFree(pd.hDevNames); |
| |
| pd.hDevMode = 0; |
| pd.hDevNames = 0; |
| |
| MessageBox(hWnd, "Success.", "Yes", MB_OK); |
| } |
| else mw_checkError(hWnd,TRUE); |
| } |
| |
| #define OF(fn, fi, fl) \ |
| if(dm->dmFields & fl){ \ |
| WINE_TRACE(" %s =%hd\n", (fn), dm->fi); \ |
| } else \ |
| WINE_TRACE(" %s NOT SET!\n", fn); |
| |
| |
| static void mw_PageSetup(HWND hWnd) |
| { |
| DEVMODEA *dm; |
| DEVNAMES *dn; |
| CHAR tmplnm[30] = "PAGESETUPDLGORD_CSTM"; |
| |
| if(psd.Flags & PSD_ENABLEPAGESETUPTEMPLATE) |
| psd.lpPageSetupTemplateName = tmplnm; |
| psd.hInstance = g_hInstance; |
| |
| if(PageSetupDlg(&psd)){ |
| dm = GlobalLock(psd.hDevMode); |
| if(dm) { |
| WINE_TRACE("dm != NULL\nDEVMODEA struct:\n"); |
| WINE_TRACE(" dmDeviceName ='%s'\n", dm->dmDeviceName); |
| WINE_TRACE(" dmSpecVersion =%#x\n", dm->dmSpecVersion); |
| WINE_TRACE(" dmDriverVersion =%#x\n", dm->dmDriverVersion); |
| WINE_TRACE(" dmSize =%#x\n", dm->dmSize); |
| WINE_TRACE(" dmDriverExtra =%#x\n", dm->dmDriverExtra); |
| WINE_TRACE(" dmFields =%#x\n", dm->dmFields); |
| OF("dmOrientation", u1.s1.dmOrientation, DM_ORIENTATION) |
| OF("dmPaperSize", u1.s1.dmPaperSize, DM_PAPERSIZE); |
| OF("dmPaperLength", u1.s1.dmPaperLength, DM_PAPERLENGTH); |
| OF("dmPaperWidth", u1.s1.dmPaperWidth, DM_PAPERWIDTH); |
| OF("dmScale", u1.s1.dmScale, DM_SCALE); |
| OF("dmCopies", u1.s1.dmCopies, DM_COPIES); |
| OF("dmDefaultSource", u1.s1.dmDefaultSource,DM_DEFAULTSOURCE); |
| OF("dmPrintQuality", u1.s1.dmPrintQuality, DM_PRINTQUALITY); |
| if(dm->dmFields & DM_POSITION) |
| WINE_TRACE(" dmPosition(%d, %d)\n", dm->u1.s2.dmPosition.x, dm->u1.s2.dmPosition.y); |
| else |
| WINE_TRACE(" dmPosition NOT SET!\n"); |
| OF("dmColor", dmColor, DM_COLOR); |
| OF("dmDuplex", dmDuplex, DM_DUPLEX); |
| OF("dmYResolution", dmYResolution, DM_YRESOLUTION); |
| OF("dmTTOption", dmTTOption, DM_TTOPTION); |
| OF("dmCollate", dmCollate, DM_COLLATE); |
| if(dm->dmFields & DM_FORMNAME) |
| WINE_TRACE(" dmFormName = '%s'\n", dm->dmFormName); |
| else |
| WINE_TRACE(" dmFormName NOT SET!\n"); |
| if(dm->dmFields & DM_ICMMETHOD) |
| WINE_TRACE(" dmICMMethod = %#x\n", dm->dmICMMethod); |
| else |
| WINE_TRACE(" dmICMMethod NOT SET!\n"); |
| |
| GlobalUnlock(psd.hDevMode); |
| } |
| else |
| WINE_TRACE("dm == NULL\n"); |
| |
| WINE_TRACE("\nPAGESETUPDLG struct\n"); |
| WINE_TRACE(" ptPaperSize(%d, %d)\n", psd.ptPaperSize.x, psd.ptPaperSize.y); |
| WINE_TRACE(" rtMargin(%d, %d, %d, %d)\n", |
| psd.rtMargin.left, psd.rtMargin.top, psd.rtMargin.right, psd.rtMargin.bottom); |
| |
| WINE_TRACE("\nDEVNAMES struct\n"); |
| dn = GlobalLock(psd.hDevNames); |
| if(dn){ |
| WINE_TRACE(" wDriverOffset='%s'\n", ((char*)dn+dn->wDriverOffset)); |
| WINE_TRACE(" wDeviceOffset='%s'\n", ((char*)dn+dn->wDeviceOffset)); |
| WINE_TRACE(" wOutputOffset='%s'\n", ((char*)dn+dn->wOutputOffset)); |
| WINE_TRACE(" wDefault ='%s'\n", ((char*)dn+dn->wDefault)); |
| GlobalUnlock(psd.hDevNames); |
| }else |
| WINE_TRACE(" dn == NULL!\n"); |
| WINE_TRACE("End.\n"); |
| |
| if (psd.hDevMode != NULL) |
| GlobalFree(psd.hDevMode); |
| if (psd.hDevNames != NULL) |
| GlobalFree(psd.hDevNames); |
| if (psd.hPageSetupTemplate != NULL) |
| GlobalFree(psd.hPageSetupTemplate); |
| |
| psd.hDevMode = NULL; |
| psd.hDevNames = NULL; |
| psd.hPageSetupTemplate = NULL; |
| |
| MessageBox(hWnd, "Success.", "Yes", MB_OK); |
| } mw_checkError(hWnd, FALSE); |
| } |
| |
| /********************************************************************************************************/ |
| /* |
| * Some support functions for the custom dialog box handlers. |
| * In particular, we have to set things properly, and get the flags back. |
| */ |
| |
| static void mwcd_SetFlags(HWND hWnd, struct FlagTableEntry *table, DWORD 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); |
| } |
| } |
| |
| static DWORD 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. |
| */ |
| |
| static INT_PTR mwcd_Setup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, |
| struct FlagTableEntry * table, DWORD* flags) |
| { |
| (void) lParam; |
| |
| 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 */ |
| } |
| } |
| |
| static INT_PTR 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); |
| } |
| |
| static INT_PTR 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); |
| } |
| |
| static INT_PTR 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); |
| } |
| |
| static INT_PTR 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); |
| } |
| |
| static INT_PTR CALLBACK mwcd_PageSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) |
| { |
| static struct FlagTableEntry flagTable[] = { |
| {I_PSD_DEFAULTMINMARGINS, PSD_DEFAULTMINMARGINS}, |
| {I_PSD_DISABLEMARGINS, PSD_DISABLEMARGINS}, |
| {I_PSD_DISABLEORIENTATION, PSD_DISABLEORIENTATION}, |
| {I_PSD_DISABLEPAGEPAINTING, PSD_DISABLEPAGEPAINTING}, |
| {I_PSD_DISABLEPAPER, PSD_DISABLEPAPER}, |
| {I_PSD_DISABLEPRINTER, PSD_DISABLEPRINTER}, |
| {I_PSD_ENABLEPAGEPAINTHOOK, PSD_ENABLEPAGEPAINTHOOK}, |
| {I_PSD_ENABLEPAGESETUPHOOK, PSD_ENABLEPAGESETUPHOOK}, |
| {I_PSD_ENABLEPAGESETUPTEMPLATE, PSD_ENABLEPAGESETUPTEMPLATE}, |
| {I_PSD_ENABLEPAGESETUPTEMPLATEHANDLE, PSD_ENABLEPAGESETUPTEMPLATEHANDLE}, |
| {I_PSD_INHUNDREDTHSOFMILLIMETERS, PSD_INHUNDREDTHSOFMILLIMETERS}, |
| {I_PSD_INTHOUSANDTHSOFINCHES, PSD_INTHOUSANDTHSOFINCHES}, |
| {I_PSD_INWININIINTLMEASURE, PSD_INWININIINTLMEASURE}, |
| {I_PSD_MARGINS, PSD_MARGINS}, |
| {I_PSD_MINMARGINS, PSD_MINMARGINS}, |
| {I_PSD_NONETWORKBUTTON, PSD_NONETWORKBUTTON}, |
| {I_PSD_NOWARNING, PSD_NOWARNING}, |
| {I_PSD_RETURNDEFAULT, PSD_RETURNDEFAULT}, |
| {I_PSD_SHOWHELP, PSD_SHOWHELP}, |
| {IDOK, 0} |
| }; |
| |
| return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &psd.Flags); |
| } |
| |
| static INT_PTR 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, &ofn.Flags); |
| } |
| |
| static INT_PTR CALLBACK mwcd_About(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) |
| { |
| (void) wParam; |
| (void) 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. |
| */ |
| |
| static void mwc_ColorSetup(HWND hWnd) |
| { |
| int r = DialogBox(g_hInstance, "Color_Flags_Dialog", hWnd, mwcd_ColorSetup); |
| if(r < 0) { MessageBox(hWnd, "Failure opening Color_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); } |
| } |
| |
| static void mwc_FontSetup(HWND hWnd) |
| { |
| int r = DialogBox(g_hInstance, "Font_Flags_Dialog", hWnd, mwcd_FontSetup); |
| if(r < 0) { MessageBox(hWnd, "Failure opening Font_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); } |
| } |
| |
| static void mwc_FindReplaceSetup(HWND hWnd) |
| { |
| int r = DialogBox(g_hInstance, "Find_Flags_Dialog", hWnd, mwcd_FindSetup); |
| if(r < 0) { MessageBox(hWnd, "Failure opening Find_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); } |
| } |
| |
| static void mwc_PrintSetup(HWND hWnd) |
| { |
| int r = DialogBox(g_hInstance, "Print_Flags_Dialog", hWnd, mwcd_PrintSetup); |
| if(r < 0) { MessageBox(hWnd, "Failure opening Print_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); } |
| } |
| |
| static void mwc_PageSetup(HWND hWnd) |
| { |
| int r = DialogBox(g_hInstance, "PageSetup_Flags_Dialog", hWnd, mwcd_PageSetup); |
| if(r < 0) { MessageBox(hWnd, "Failure opening PageSetup_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); } |
| } |
| |
| static void mwc_FileSetup(HWND hWnd) |
| { |
| int r = DialogBox(g_hInstance, "File_Flags_Dialog", hWnd, mwcd_FileSetup); |
| 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. |
| */ |
| |
| static LRESULT CALLBACK EXPORT mainWindowDispatcher( |
| HWND hWnd, |
| UINT uMsg, |
| WPARAM wParam, |
| LPARAM lParam |
| ) |
| { |
| |
| if(uMsg == findMessageId) { |
| FINDREPLACE * lpfr = (FINDREPLACE *) 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 occurrence.", "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; |
| |
| case CM_U_PAGESETUP: |
| mw_PageSetup(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_F_PAGESETUP: |
| mwc_PageSetup(hWnd); return 1; |
| |
| case CM_H_ABOUT: |
| DialogBox(g_hInstance, "AboutDialog", hWnd, mwcd_About); |
| return 1; |
| case CM_H_USAGE: |
| DialogBox(g_hInstance, "UsageDialog", hWnd, 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. */ |
| |
| static int registerMainWindowClass(HINSTANCE hInstance) |
| { |
| WNDCLASS wndClass; |
| |
| wndClass.style = CS_HREDRAW|CS_VREDRAW; |
| wndClass.lpfnWndProc = mainWindowDispatcher; |
| wndClass.cbClsExtra = 0; |
| wndClass.cbWndExtra = 0; |
| wndClass.hInstance = hInstance; |
| #if 0 |
| wndClass.hIcon = LoadIcon(hInstance, "whello"); |
| wndClass.hCursor = LoadCursor(hInstance, IDC_ARROW); |
| #endif |
| 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). |
| */ |
| |
| static 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; |
| } |
| |
| static int messageLoop(HINSTANCE hInstance, HWND hWnd) |
| { |
| MSG msg; |
| |
| (void) hInstance; |
| (void) hWnd; |
| |
| 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; |
| |
| (void) lpszCmdLine; |
| |
| 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-2000 Eric Williams. Rights as specified under the WINE |
| * License. Don't hoard code; share it! |
| */ |