home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / ibm1 / v11n10.arj / DLGDEMO.C < prev    next >
Text File  |  1992-03-08  |  20KB  |  527 lines

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