home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol11n11.zip / DLGDEMO2.ZIP / DLGDEMO2.C next >
Text File  |  1992-03-24  |  22KB  |  592 lines

  1. //
  2. // DLGDEMO2 - Notepad Clone #2 demonstrating use of Win 3.1 Common Dialogs
  3. // Copyright (C) 1992 Ray Duncan
  4. // Ziff Davis Publishing Co. * PC Magazine
  5. //
  6.  
  7. #define WIN31
  8. #define dim(x) (sizeof(x) / sizeof(x[0]))   // returns no. of elements
  9. #define EXENAMESIZE 256                     // max length of path+filename
  10. #define BUFSIZE 65520                       // max length of file data
  11.  
  12. #include "string.h"
  13. #include "windows.h"
  14. #include "commdlg.h"
  15. #include "dlgdemo2.h"
  16.  
  17. HANDLE hInst;                               // module instance handle
  18. HWND hFrame;                                // handle for frame window
  19. HWND hEdit;                                 // handle for edit window
  20. char szFileName[EXENAMESIZE+1];             // name of current file 
  21. char szTemp[EXENAMESIZE+1];                 // filename scratch buffer
  22. int hFile;                                  // handle for current file
  23. HANDLE hBuff;                               // handle for file I/O buffer
  24. LPSTR lpBuff;                               // far pointer to file buffer
  25. DWORD dwColor = RGB(0, 0, 0);               // user-selected colorref
  26.  
  27. char szShortAppName[] = "DlgDemo";          // short application name
  28. char szAppName[] = "Common Dialog Demo #2"; // long application name
  29. char szMenuName[] = "DlgDemoMenu";          // name of menu resource
  30. char szDefName[] = "UNTITLED";              // default filename
  31. char szDefExt[] = "TXT";                    // default extension
  32.  
  33. char *szFilter[] = {                        // filters for Open and
  34.     "ASCII Text (*.TXT)", "*.TXT",          // SaveAs common dialogs
  35.     "All Files (*.*)", "*.*",
  36.     "" };
  37.  
  38. struct decodeWord {                         // structure associates
  39.     WORD Code;                              // messages or menu IDs
  40.     LONG (*Fxn)(HWND, WORD, WORD, LONG); }; // with a function
  41.  
  42. //
  43. // Table of window messages supported by FrameWndProc()
  44. // and the functions which correspond to each message.
  45. //
  46. struct decodeWord messages[] = {
  47.     WM_CREATE, DoCreate,
  48.     WM_INITMENU, DoInitMenu,
  49.     WM_SETFOCUS, DoSetFocus,
  50.     WM_SIZE, DoSize,
  51.     WM_COMMAND, DoCommand,
  52.     WM_DESTROY, DoDestroy, 
  53.     WM_CTLCOLOR, DoSetColor,
  54.     } ;
  55.  
  56. //
  57. // Table of menubar item IDs and their corresponding functions.
  58. //
  59. struct decodeWord menuitems[] = {
  60.     IDM_NEW, DoMenuNew,
  61.     IDM_OPEN, DoMenuOpen,
  62.     IDM_SAVE, DoMenuSave,
  63.     IDM_SAVEAS, DoMenuSaveAs,
  64.     IDM_EXIT, DoMenuExit, 
  65.     IDM_UNDO, DoMenuUndo,
  66.     IDM_CUT, DoMenuCut,
  67.     IDM_COPY, DoMenuCopy,
  68.     IDM_PASTE, DoMenuPaste,
  69.     IDM_DELETE, DoMenuDelete, 
  70.     IDM_FONT, DoMenuFont,
  71.     IDM_COLOR, DoMenuColor,
  72.     } ;
  73.  
  74. //
  75. // WinMain -- entry point for this application from Windows.
  76. //
  77. int PASCAL WinMain(HANDLE hInstance,
  78.     HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
  79. {
  80.     MSG msg;
  81.  
  82.     hInst = hInstance;                      // save this instance handle
  83.  
  84.     if(!hPrevInstance)                      // if first instance,
  85.         if(!InitApplication(hInstance))     // register window class
  86.             return(FALSE);                  // exit if couldn't register
  87.  
  88.     if(!InitInstance(hInstance, nCmdShow))  // create this instance's window
  89.         return(FALSE);                      // exit if create failed
  90.  
  91.     while(GetMessage(&msg, NULL, 0, 0))     // while message != WM_QUIT
  92.     {
  93.         TranslateMessage(&msg);             // translate virtual key codes
  94.         DispatchMessage(&msg);              // dispatch message to window
  95.     }
  96.  
  97.     TermInstance(hInstance);                // clean up for this instance
  98.     return(msg.wParam);                     // return code = WM_QUIT value
  99. }
  100.  
  101. //
  102. // InitApplication --- global initialization code for this application.
  103. //
  104. BOOL InitApplication(HANDLE hInstance)
  105. {
  106.     WNDCLASS  wc;
  107.  
  108.     // set parameters for frame window class
  109.     wc.style = CS_HREDRAW|CS_VREDRAW;       // class style
  110.     wc.lpfnWndProc = FrameWndProc;          // class callback function
  111.     wc.cbClsExtra = 0;                      // extra per-class data
  112.     wc.cbWndExtra = 0;                      // extra per-window data
  113.     wc.hInstance = hInstance;               // handle of class owner
  114.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);     // default icon
  115.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);       // default cursor
  116.     wc.hbrBackground = GetStockObject(WHITE_BRUSH); // background color 
  117.     wc.lpszMenuName =  szMenuName;          // name of menu resource
  118.     wc.lpszClassName = szShortAppName;      // name of window class
  119.  
  120.     return(RegisterClass(&wc));             // register class, return status
  121. }
  122.  
  123. //
  124. // InitInstance --- instance initialization code for this application.
  125. //
  126. BOOL InitInstance(HANDLE hInstance, WORD nCmdShow)
  127. {
  128.     hFrame = CreateWindow(                  // create frame window
  129.         szShortAppName,                     // window class name
  130.         szAppName,                          // text for title bar
  131.         WS_OVERLAPPEDWINDOW,                // window style
  132.         CW_USEDEFAULT, CW_USEDEFAULT,       // default position
  133.         CW_USEDEFAULT, CW_USEDEFAULT,       // default size
  134.         NULL,                               // no parent window
  135.         NULL,                               // use class default menu
  136.         hInstance,                          // window owner
  137.         NULL);                              // unused pointer
  138.  
  139.     if(!hFrame) return(FALSE);              // error, can't create window
  140.  
  141.     hBuff = GlobalAlloc(GMEM_MOVEABLE, BUFSIZE);    // allocate memory
  142.     if(!hBuff)                                      // abort if no memory
  143.     {
  144.         MessageBox(hFrame, "Can't allocate memory!", szAppName, 
  145.             MB_ICONSTOP|MB_OK);
  146.         return(0);
  147.     }
  148.  
  149.     lpBuff = GlobalLock(hBuff);             // get far pointer to memory
  150.  
  151.     ShowWindow(hFrame, nCmdShow);           // make frame window visible
  152.     UpdateWindow(hFrame);                   // force WM_PAINT message
  153.     SendMessage(hFrame, WM_COMMAND,         // force new (empty) file by 
  154.         IDM_NEW, 0L);                       // simulating File-New command
  155.     return(TRUE);                           // return success flag
  156. }
  157.  
  158. //
  159. // TermInstance -- instance termination code for this application.
  160. //
  161. BOOL TermInstance(HANDLE hinstance)
  162. {
  163.     GlobalUnlock(hBuff);                    // unlock the memory buffer
  164.     GlobalFree(hBuff);                      // release the buffer
  165.     return(TRUE);                           // return success flag
  166. }
  167.  
  168. //
  169. // FrameWndProc --- callback function for application frame window.
  170. //
  171. LONG FAR PASCAL FrameWndProc(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  172. {
  173.     int i;                                  // scratch variable
  174.  
  175.     for(i = 0; i < dim(messages); i++)      // decode window message and
  176.     {                                       // run corresponding function
  177.         if(wMsg == messages[i].Code)
  178.             return((*messages[i].Fxn)(hWnd, wMsg, wParam, lParam));
  179.     }
  180.  
  181.     return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  182. }
  183.  
  184. //
  185. // DoCreate -- process WM_CREATE message for frame window by
  186. // creating a multiline edit control that will fill the frame window.
  187. // 
  188. LONG DoCreate(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  189. {
  190.     hEdit = CreateWindow("edit",            // class name
  191.                 NULL,                       // text for title bar 
  192.                 WS_CHILD|WS_VISIBLE|WS_HSCROLL|     
  193.                 WS_VSCROLL|WS_BORDER|ES_LEFT|ES_MULTILINE| 
  194.                 ES_AUTOHSCROLL|ES_AUTOVSCROLL,  // window style
  195.                 0, 0,                       // window position
  196.                 0, 0,                       // window size
  197.                 hWnd,                       // parent window
  198.                 IDE_MLE,                    // edit control ID
  199.                 hInst,                      // window owner
  200.                 NULL);                      // unused pointer
  201.     return(0);
  202. }
  203.  
  204. //
  205. // DoSetFocus -- process WM_SETFOCUS message for frame window.
  206. // 
  207. LONG DoSetFocus(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  208. {
  209.     SetFocus(hEdit);                        // toss the focus to 
  210.     return(0);                              // multiline edit control
  211. }
  212.  
  213. //
  214. // DoSize -- process WM_SIZE message for frame window by resizing
  215. // the multiline edit control to completely fill the client area.
  216. // 
  217. LONG DoSize(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  218. {
  219.     MoveWindow(hEdit, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
  220.     return(0);
  221. }
  222.  
  223. //
  224. // DoCommand -- process WM_COMMAND message for frame window by
  225. // decoding the menubar item with the menuitems[] array, then
  226. // running the corresponding function to process the command.
  227. // 
  228. LONG DoCommand(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  229. {
  230.     int i;                                  // scratch variable
  231.  
  232.     if((wParam == IDE_MLE) && (HIWORD(lParam) == EN_ERRSPACE))
  233.     {
  234.         MessageBox(hWnd, "Out of memory!", "Common Dialog Demo", 
  235.             MB_OK | MB_ICONSTOP);
  236.         return(0);
  237.     }
  238.  
  239.     for(i = 0; i < dim(menuitems); i++)     // decode menu command and
  240.     {                                       // run corresponding function
  241.         if(wParam == menuitems[i].Code)
  242.             return((*menuitems[i].Fxn)(hWnd, wMsg, wParam, lParam));
  243.     }
  244.  
  245.     return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  246. }
  247.  
  248. //
  249. // DoDestroy -- process WM_DESTROY message for frame window.
  250. // 
  251. LONG DoDestroy(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  252. {
  253.     PostQuitMessage(0);                     // force WM_QUIT message to
  254.     return(0);                              // terminate the event loop
  255. }
  256.  
  257. //
  258. // DoSetColor -- process WM_CTLCOLOR message for edit window.
  259. // 
  260. LONG DoSetColor(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  261. {
  262.     SetTextColor((HDC) wParam, dwColor);    // set text color from results
  263.     return(GetStockObject(WHITE_BRUSH));    // return background brush handle
  264. }
  265.  
  266. //
  267. // DoInitMenu - initialize the items on menu bar according to the 
  268. // state of the multiline edit control.  If nothing is selected, the 
  269. // edit-cut/copy/delete items are greyed out.  If nothing has 
  270. // been changed since the last file read or write, the file-save item
  271. // is greyed out.  If no text is in the clipboard, the edit-paste
  272. // item is greyed out.
  273. //
  274. LONG DoInitMenu(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  275. {
  276.     LONG selection;
  277.     
  278.     selection = SendMessage(hEdit, EM_GETSEL, 0, 0);
  279.  
  280.     if(HIWORD(selection) != LOWORD(selection))          // set cut/copy/
  281.     {                                                   // delete status
  282.         EnableMenuItem(wParam, IDM_CUT, MF_ENABLED);    
  283.         EnableMenuItem(wParam, IDM_COPY, MF_ENABLED);   
  284.         EnableMenuItem(wParam, IDM_DELETE, MF_ENABLED); 
  285.     }
  286.     else
  287.     {
  288.         EnableMenuItem(wParam, IDM_CUT, MF_GRAYED); 
  289.         EnableMenuItem(wParam, IDM_COPY, MF_GRAYED);    
  290.         EnableMenuItem(wParam, IDM_DELETE, MF_GRAYED);  
  291.     }
  292.  
  293.     if(SendMessage(hEdit, EM_CANUNDO, 0, 0))            // set undo status
  294.         EnableMenuItem(wParam, IDM_UNDO, MF_ENABLED);   
  295.     else
  296.         EnableMenuItem(wParam, IDM_UNDO, MF_GRAYED);    
  297.  
  298.     if(IsClipboardFormatAvailable(CF_TEXT))             // set paste status
  299.         EnableMenuItem(wParam, IDM_PASTE, MF_ENABLED);  
  300.     else
  301.         EnableMenuItem(wParam, IDM_PASTE, MF_GRAYED);   
  302.  
  303.     if(SendMessage(hEdit, EM_GETMODIFY, 0, 0))          // set save status
  304.         EnableMenuItem(wParam, IDM_SAVE, MF_ENABLED);   
  305.     else
  306.         EnableMenuItem(wParam, IDM_SAVE, MF_GRAYED);    
  307.     
  308.     return(0);
  309. }
  310.  
  311. //
  312. // DoMenuNew -- process File-New command from menu bar.
  313. // 
  314. LONG DoMenuNew(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  315. {
  316.     QueryWriteFile(hEdit);                  // check for dirty buffer
  317.     NewFile(hEdit);                         // empty the text window
  318.     return(0);
  319. }
  320.  
  321. //
  322. // DoMenuOpen -- process File-Open command from menu bar.
  323. //
  324. LONG DoMenuOpen(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  325. {
  326.     OPENFILENAME ofn;                       // used by common dialogs
  327.  
  328.     QueryWriteFile(hEdit);                  // check for dirty buffer
  329.  
  330.     szTemp[0]  = '\0';                      // init filename buffer
  331.  
  332.     ofn.lStructSize = sizeof(OPENFILENAME); // length of structure
  333.     ofn.hwndOwner = hWnd;                   // handle for owner window
  334.     ofn.lpstrFilter = szFilter[0];          // address of filter list
  335.     ofn.lpstrCustomFilter = NULL;           // custom filter buffer address
  336.     ofn.nFilterIndex = 1;                   // use *.TXT filter
  337.     ofn.lpstrFile = szTemp;                 // buffer for path+filename
  338.     ofn.nMaxFile = EXENAMESIZE;             // length of buffer
  339.     ofn.lpstrFileTitle = NULL;              // buffer for filename only
  340.     ofn.lpstrInitialDir = NULL;             // initial directory for dialog
  341.     ofn.lpstrTitle = NULL;                  // title for dialog box
  342.     ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  343.     ofn.lpstrDefExt = NULL;                 // default extension 
  344.  
  345.     if(GetOpenFileName(&ofn))               // display open dialog, 
  346.         ReadFile(hEdit);                    // read data from file
  347.  
  348.     return(0);
  349. }
  350.  
  351. //
  352. // DoMenuSave -- Process File-Save command from menu bar.  If
  353. // filename is default (UNTITLED), ask user for a different one.
  354. //
  355. LONG DoMenuSave(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  356. {
  357.     int hFile;                              // scratch file handle
  358.  
  359.     if(strcmp(szFileName, szDefName) == 0)  // if default name, use SaveAs
  360.         SendMessage(hFrame, WM_COMMAND, IDM_SAVEAS, 0);
  361.     else
  362.         WriteFile(hEdit);                   // otherwise write data to file
  363.  
  364.     return(0);
  365. }
  366.  
  367. //
  368. // DoMenuSaveAs -- process File-SaveAs command from menu bar.
  369. // 
  370. LONG DoMenuSaveAs(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  371. {
  372.     OPENFILENAME ofn;                       // used by common dialogs
  373.  
  374.     strcpy(szTemp, szFileName);             // get default filename
  375.  
  376.     ofn.lStructSize = sizeof(OPENFILENAME); // length of structure
  377.     ofn.hwndOwner = hWnd;                   // handle of owner window
  378.     ofn.lpstrFilter = szFilter[0];          // address of filter list
  379.     ofn.lpstrCustomFilter = NULL;           // custom filter buffer address
  380.     ofn.nFilterIndex = 1L;                  // use *.TXT filter
  381.     ofn.lpstrFile = szTemp;                 // buffer for path+filename
  382.     ofn.nMaxFile = EXENAMESIZE;             // size of buffer
  383.     ofn.lpstrFileTitle = NULL;              // buffer for filename only
  384.     ofn.lpstrInitialDir = NULL;             // initial directory for dialog
  385.     ofn.lpstrTitle = NULL;                  // title for dialog box
  386.     ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOTESTFILECREATE;
  387.     ofn.lpstrDefExt = szDefExt;             // default extension
  388.  
  389.     if(GetSaveFileName(&ofn))               // display save-as dialog,
  390.         WriteFile(hEdit);                   // write data to file
  391.  
  392.     return(0);                          
  393. }
  394.  
  395. //
  396. // DoMenuExit -- process File-Exit command from menu bar.
  397. // 
  398. LONG DoMenuExit(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  399. {
  400.     QueryWriteFile(hEdit);                  // check for dirty buffer
  401.     SendMessage (hWnd, WM_CLOSE, 0, 0L);    // send window close message    
  402.     return(0);                              // to shut down the app
  403. }
  404.  
  405. //
  406. // DoMenuUndo -- process Edit-Undo command from menu bar.
  407. // 
  408. LONG DoMenuUndo(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  409. {
  410.     SendMessage(hEdit, WM_UNDO, 0, 0);      // tell the edit control
  411.     return(0);
  412. }
  413.  
  414. //
  415. // DoMenuCut -- process Edit-Cut command from menu bar.
  416. // 
  417. LONG DoMenuCut(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  418. {
  419.     SendMessage(hEdit, WM_CUT, 0, 0);       // tell the edit control
  420.     return(0);
  421. }
  422.  
  423. //
  424. // DoMenuCopy -- process Edit-Copy command from menu bar.
  425. // 
  426. LONG DoMenuCopy(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  427. {
  428.     SendMessage(hEdit, WM_COPY, 0, 0);      // tell the edit control
  429.     return(0);
  430. }
  431.  
  432. //
  433. // DoMenuPaste -- process Edit-Paste command from menu bar.
  434. // 
  435. LONG DoMenuPaste(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  436. {
  437.     SendMessage(hEdit, WM_PASTE, 0, 0);     // tell the edit control
  438.     return(0);
  439. }
  440.  
  441. //
  442. // DoMenuDelete -- process Edit-Delete command from menu bar.
  443. // 
  444. LONG DoMenuDelete(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  445. {
  446.     SendMessage(hEdit, WM_CLEAR, 0, 0);     // tell the edit control
  447.     return(0);
  448. }
  449.  
  450. //
  451. // DoMenuFont -- process Font command from menu bar.
  452. // 
  453. LONG DoMenuFont(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  454. {
  455.     LOGFONT lf;                             // logical font data structure
  456.     CHOOSEFONT chf;                         // font dialog data structure
  457.     HFONT hfont;                            // logical font handle
  458.  
  459.     chf.lStructSize = sizeof(CHOOSEFONT);   // size of structure    
  460.     chf.hwndOwner = hWnd;                   // window handle of owner
  461.     chf.lpLogFont = &lf;                    // logical font structure
  462.     chf.Flags = CF_SCREENFONTS|CF_EFFECTS;  // option flags
  463.     chf.rgbColors = RGB(0,0,0);             // default color = black
  464.  
  465.     if(ChooseFont(&chf))                    // display ChooseFont dialog    
  466.     {
  467.         hfont = CreateFontIndirect(&lf);    // save font handle, then send 
  468.         SendMessage(hEdit, WM_SETFONT, hfont, TRUE);  // it to edit control
  469.     }
  470.  
  471.     return(0);
  472. }
  473.  
  474. //
  475. // DoMenuColor -- process Color command from menu bar.
  476. // 
  477. LONG DoMenuColor(HWND hWnd, WORD wMsg, WORD wParam, LONG lParam)
  478. {
  479.     CHOOSECOLOR chc;                        // color dialog data structure
  480.     DWORD dwCustColors[16];                 // array of custom colorrefs
  481.     int i;                                  // scratch variable
  482.  
  483.     for(i = 0; i < 16; i++)                 // init custom colors to white
  484.         dwCustColors[i] = RGB(255, 255, 255);
  485.  
  486.     chc.lStructSize = sizeof(CHOOSECOLOR);  // size of structure
  487.     chc.hwndOwner = hWnd;                   // window handle of owner
  488.     chc.rgbResult = dwColor;                // initial color to select
  489.     chc.lpCustColors = dwCustColors;        // addr of custom color array
  490.     chc.Flags = CC_FULLOPEN | CC_RGBINIT;   // option flags
  491.  
  492.     if(ChooseColor(&chc))                   // display ChooseColor dialog
  493.     {
  494.         dwColor = chc.rgbResult;            // save new text color
  495.         InvalidateRect(hEdit, NULL, TRUE);  // then force edit window to
  496.         UpdateWindow(hEdit);                // be redrawn with new color
  497.     }
  498.  
  499.     return(0);
  500. }
  501.  
  502. //
  503. // NewFile -- set empty text window with default filename.
  504. //
  505. VOID NewFile(HANDLE hEdit)
  506. {
  507.     lpBuff[0] = '\0';                       // empty the edit control
  508.     SetWindowText(hEdit, lpBuff);           // put text into window
  509.     strcpy(szFileName, szDefName);          // set default filename
  510.     SetWindowCaption(szFileName);           // update title bar
  511.     SendMessage(hEdit, EM_SETMODIFY, 0, 0); // clear change flag
  512. }
  513.  
  514. //
  515. // ReadFile -- read text from specified file to window, close file.
  516. //
  517. VOID ReadFile(HANDLE hEdit)
  518. {
  519.     int length;                             // scratch variable
  520.     int hFile;                              // scratch file handle
  521.  
  522.     hFile = _lopen(szTemp, OF_READ);        // try and open the file
  523.     if(hFile == -1)                         // bail out if no such file
  524.     {
  525.         MessageBox(hFrame, "Can't open file!", szAppName, MB_ICONSTOP|MB_OK);
  526.         return;
  527.     }
  528.  
  529.     strcpy(szFileName, szTemp);             // save new filename
  530.     length = _lread(hFile, lpBuff, BUFSIZE);    // read the file
  531.     lpBuff[length] = '\0';                  // make text ASCIIZ
  532.     SetWindowText(hEdit, lpBuff);           // put text into window
  533.     _lclose(hFile);                         // close the file
  534.     SetWindowCaption(szFileName);           // update title bar
  535.     SendMessage(hEdit, EM_SETMODIFY, 0, 0); // clear change flag
  536. }
  537.  
  538. //
  539. // WriteFile -- write text from specified window to file, close file.
  540. //
  541. VOID WriteFile(HANDLE hEdit)
  542. {
  543.     int length;                             // scratch variable
  544.     int hFile;                              // scratch file handle
  545.  
  546.     hFile = _lcreat(szTemp, 0);             // try and create the file
  547.     if(hFile == -1)                         // bail out if create failed
  548.     {
  549.         MessageBox(hFrame, "Can't create file!", szAppName, 
  550.             MB_ICONSTOP|MB_OK);
  551.         return;
  552.     }
  553.  
  554.     strcpy(szFileName, szTemp);             // save new filename
  555.     length = GetWindowTextLength(hEdit);    // chars in edit control
  556.     GetWindowText(hEdit, lpBuff, length+1); // retrieve text
  557.     _lwrite(hFile, lpBuff, length);         // write text to file
  558.     _lclose(hFile);                         // close the file
  559.     SetWindowCaption(szFileName);           // update title bar
  560.     SendMessage(hEdit, EM_SETMODIFY, 0, 0); // clear change flag
  561. }
  562.  
  563. //
  564. // QueryWriteFile -- check if buffer has been changed, and if
  565. // so prompt the user to write the file to disk.  
  566. //
  567. VOID QueryWriteFile(HANDLE hEdit)
  568. {
  569.     if(SendMessage(hEdit, EM_GETMODIFY, 0, 0))  // was buffer changed?
  570.     {
  571.         if(MessageBox(hFrame, "File has been changed.  Write file?", 
  572.             szAppName, MB_ICONQUESTION|MB_YESNO) == IDYES)
  573.         {
  574.             SendMessage(hFrame, WM_COMMAND, IDM_SAVEAS, 0);
  575.         }
  576.     }
  577. }
  578.  
  579. //
  580. // SetWindowCaption -- concatenate the filename with the application
  581. // name, then update the frame window's title bar.
  582. //
  583. VOID SetWindowCaption(char * szFilename)
  584. {
  585.     char szTemp[EXENAMESIZE+1];             // filename scratch buffer
  586.  
  587.     strcpy(szTemp, szAppName);              // get application name
  588.     strcat(szTemp, " - ");                  // add separator
  589.     strcat(szTemp, szFileName);             // add filename
  590.     SetWindowText(hFrame, szTemp);          // put result into title bar
  591. }
  592.