home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / MULTIPAD.PAK / MDICHILD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  16.7 KB  |  650 lines

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993-1995  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE:   mdichild.c
  9. //
  10. //  PURPOSE:
  11. //    To implement the basic mdi child commands.
  12. //
  13. //  FUNCTIONS:
  14. //    InitMDIChild     - To register the MDI child window class.
  15. //    MDIChildWndProc  - Processes messages for MDI child windows.
  16. //    MsgMCCommand     - Handle the WM_COMMAND messages for mdi children.
  17. //    MsgMCMenuSelect  - Handle the WM_MENUSELECT message for the mdi child
  18. //    MsgMCCreate      - Handle the WM_CREATE message for the MDI child
  19. //    MsgMCSize        - Handle the WM_SIZE message for the MDI child
  20. //    MsgMCSetFocus    - Handle the WM_SETFOCUS message for the MDI child
  21. //    MsgMCClose       - Handle the WM_CLOSE message for the MDI child
  22. //    MsgMCDestroy     - Handle the WM_DESTROY message for the MDI child
  23. //    CmdEdit          - Handle the notification messages for the edit control
  24. //                       contained within the MDI child
  25. //
  26. //  COMMENTS:
  27. //
  28. //
  29. //  SPECIAL INSTRUCTIONS: N/A
  30. //
  31.  
  32. #include <windows.h>            // required for all Windows applications
  33. #include <windowsx.h>
  34. #include "globals.h"            // prototypes specific to this application
  35. #include "mdichild.h"
  36. #include "toolbar.h"
  37. #include "statbar.h"
  38. #include "resource.h"
  39.  
  40. static MSD rgmsd[] =
  41. {
  42.     {WM_SETFOCUS,    MsgMCSetFocus},
  43.     {WM_CREATE,      MsgMCCreate  },
  44.     {WM_COMMAND,     MsgMCCommand },
  45.     {WM_MENUSELECT,  MsgMenuSelect},
  46.     {WM_SIZE,        MsgMCSize    },
  47.     {WM_CLOSE,       MsgMCClose   },
  48.     {WM_DESTROY,     MsgMCDestroy },
  49. };
  50.  
  51. MSDI msdiChild =
  52. {
  53.     sizeof(rgmsd) / sizeof(MSD),
  54.     rgmsd,
  55.     edwpMDIChild
  56. };
  57.  
  58. static CMD rgcmd[] =
  59. {
  60.     {IDC_EDIT,       CmdEdit},
  61. };
  62.  
  63. CMDI cmdiChild =
  64. {
  65.     sizeof(rgcmd) / sizeof(CMD),
  66.     rgcmd,
  67.     edwpMDIChild
  68. };
  69.  
  70. //Module specific globals
  71.  
  72. char   szChildName[] = "MdiChild";
  73. static HANDLE hszEditBuffer = NULL;
  74.  
  75.  
  76. //
  77. //  FUNCTION: InitMDIChild(HINSTANCE)
  78. //
  79. //  PURPOSE: To register the MDI child window class.
  80. //
  81. //  PARAMETERS:
  82. //    hinst - The instance of the application used to register the class.
  83. //
  84. //  RETURN VALUE:
  85. //    TRUE - Succeeded in registering the class.
  86. //    FALSE - Failed to register the class.
  87. //
  88. //  COMMENTS:
  89. //
  90. //
  91.  
  92. BOOL InitMDIChild(HINSTANCE hinst)
  93. {
  94.     WNDCLASSEX wc;
  95.  
  96.     wc.cbSize        = sizeof(WNDCLASSEX);
  97.     wc.style         = 0;
  98.     wc.lpfnWndProc   = (WNDPROC)MDIChildWndProc;
  99.     wc.cbClsExtra    = 0;
  100.     wc.cbWndExtra    = 0;
  101.     wc.hInstance     = hinst;                      // Owner of this class
  102.     wc.hIcon         = LoadIcon(hinst, MAKEINTRESOURCE(IDI_CHILDICON));
  103.     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  104.     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); // Default color
  105.     wc.lpszMenuName  = NULL;
  106.     wc.lpszClassName = szChildName;
  107.     wc.hIconSm       = LoadImage(hInst,            // Load small icon image
  108.                                  MAKEINTRESOURCE(IDI_CHILDICON),
  109.                                  IMAGE_ICON,
  110.                                  16, 16,
  111.                                  0);
  112.  
  113.     if (!RegisterClassEx(&wc))
  114.     {
  115.         //Assume we are running on NT where RegisterClassEx() is
  116.         //not implemented, so let's try calling RegisterClass().
  117.  
  118.         if (!RegisterClass((LPWNDCLASS)&wc.style))
  119.             return FALSE;
  120.     }
  121.  
  122.     return TRUE;
  123. }
  124.  
  125.  
  126. //
  127. //  FUNCTION: MDIChildWndProc(HWND, UINT, WPARAM, LPARAM)
  128. //
  129. //  PURPOSE:  Processes messages for MDI child windows.
  130. //
  131. //  PARAMETERS:
  132. //    hwnd     - window handle
  133. //    uMessage - message number
  134. //    wparam   - additional information (dependant of message number)
  135. //    lparam   - additional information (dependant of message number)
  136. //
  137. //  RETURN VALUE:
  138. //    Depends on the message number.
  139. //
  140. //  COMMENTS:
  141. //    Uses the combination of the message structure defined in mditable.c
  142. //    and the DispMessage function defined in WndProc.c to handle all
  143. //    messages directed to an MDI child window.
  144. //
  145.  
  146. LRESULT CALLBACK MDIChildWndProc(HWND hwnd,
  147.                                  UINT uMessage,
  148.                                  WPARAM wparam,
  149.                                  LPARAM lparam)
  150. {
  151.     return DispMessage( &msdiChild, hwnd, uMessage, wparam, lparam );
  152. }
  153.  
  154.  
  155. //
  156. //  FUNCTION: MsgMCCommand(HWND, UINT, WPARAM, LPARAM)
  157. //
  158. //  PURPOSE: Handle the WM_COMMAND messages for mdi children.
  159. //
  160. //  PARAMETERS:
  161. //    hwnd     - window handle
  162. //    uMessage - message number (Unused)
  163. //    GET_WM_COMMAND_ID(wparam,lparam)   - Command identifier
  164. //    GET_WM_COMMAND_HWND(wparam,lparam) - Control handle
  165. //
  166. //  RETURN VALUE:
  167. //
  168. //  COMMENTS:
  169. //    Uses the combination of the command structure defined in mditable.c
  170. //    and the DispCommand function defined in WndProc.c to handle all
  171. //    commands directed to an MDI child window.
  172. //
  173. //
  174.  
  175. #pragma argsused
  176. LRESULT MsgMCCommand(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  177. {
  178.     return DispCommand(&cmdiChild, hwnd, wparam, lparam);
  179. }
  180.  
  181.  
  182. //
  183. //  FUNCTION: MsgMCCreate(HWND, UINT, WPARAM, LPARAM)
  184. //
  185. //  PURPOSE:
  186. //
  187. //  PARAMETERS:
  188. //    hwnd     - The window handing the message.
  189. //    uMessage - The message number. (unused).
  190. //    wparam   - Message specific data (unused).
  191. //    lparam   - Message specific data (unused).
  192. //
  193. //  RETURN VALUE:
  194. //    
  195. //
  196. //  COMMENTS:
  197. //
  198. //
  199.  
  200. #pragma argsused
  201. LRESULT MsgMCCreate(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  202. {
  203.  
  204.      if (!CreateEditControl(hwnd))
  205.           return -1;
  206.  
  207.      return 0;
  208. }
  209.  
  210.  
  211. //
  212. //  FUNCTION: MsgMCSize(HWND, UINT, WPARAM, LPARAM)
  213. //
  214. //  PURPOSE:  Resize the edit control window within the MDI Child
  215. //
  216. //  PARAMETERS:
  217. //    hwnd     - The window handing the message.
  218. //    uMessage - The message number. (unused).
  219. //    wparam   - Message specific data (unused).
  220. //    lparam   - Message specific data (unused).
  221. //
  222. //  RETURN VALUE:
  223. //    
  224. //
  225. //  COMMENTS:
  226. //    We must call DefMDIChildProc so that if the child is being maximized
  227. //    we'll get the system menu, min, max and close buttons painted properly.
  228. //
  229.  
  230. LRESULT MsgMCSize(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  231. {
  232.     MoveWindow(GetEditWindow(hwnd), 
  233.                0, 0, 
  234.                LOWORD(lparam), HIWORD(lparam), 
  235.                TRUE);
  236.  
  237.     return DefMDIChildProc(hwnd, uMessage, wparam, lparam);
  238. }
  239.  
  240.  
  241. //
  242. //  FUNCTION: MsgMCMenuSelect(HWND, UINT, WPARAM, LPARAM)
  243. //
  244. //  PURPOSE:  
  245. //
  246. //  PARAMETERS:
  247. //    hwnd     - The window handing the message.
  248. //    uMessage - The message number. (unused).
  249. //    wparam   - Message specific data (unused).
  250. //    lparam   - Message specific data (unused).
  251. //
  252. //  RETURN VALUE:
  253. //    
  254. //
  255. //  COMMENTS:
  256. //
  257.  
  258. LRESULT MsgMCMenuSelect(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  259. {
  260.  
  261.      return DefMDIChildProc(hwnd, uMessage, wparam, lparam);
  262. }
  263.  
  264.  
  265. //
  266. //  FUNCTION: MsgMCSetFocus(HWND, UINT, WPARAM, LPARAM)
  267. //
  268. //  PURPOSE:
  269. //    Sets the focus to the edit control window contained within this MDI
  270. //    child window.
  271. //
  272. //  PARAMETERS:
  273. //    hwnd     - The window handing the message.
  274. //    uMessage - The message number. (unused).
  275. //    wparam   - Message specific data (unused).
  276. //    lparam   - Message specific data (unused).
  277. //
  278. //  RETURN VALUE:
  279. //
  280. //
  281. //  COMMENTS:
  282. //
  283.  
  284. #pragma argsused
  285. LRESULT MsgMCSetFocus(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  286. {
  287.      SetFocus(GetEditWindow(NULL));
  288.      return 0;
  289. }
  290.  
  291.  
  292. //
  293. //  FUNCTION: MsgMCClose(HWND, UINT, WPARAM, LPARAM)
  294. //
  295. //  PURPOSE:  Query user to save file before closing window
  296. //
  297. //  PARAMETERS:
  298. //    hwnd - The window handing the message.
  299. //    uMessage - The message number. (unused).
  300. //    wparam - Message specific data (unused).
  301. //    lparam - Message specific data (unused).
  302. //
  303. //  RETURN VALUE:
  304. //    Return 0 if user hits "Cancel" from the query save dialog.  This
  305. //    prevents the MDI child from closing.
  306. //
  307. //  COMMENTS:
  308. //    Call DefMDIChildProc so that the window gets destroyed.
  309. //
  310.  
  311. LRESULT MsgMCClose(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  312. {
  313.     if (QuerySaveFile(hwnd))
  314.         return DefMDIChildProc(hwnd, uMessage, wparam, lparam);
  315.     else
  316.         return 0;
  317. }
  318.  
  319.  
  320. //
  321. //  FUNCTION: MsgMCDestroy(HWND, UINT, WPARAM, LPARAM)
  322. //
  323. //  PURPOSE:
  324. //
  325. //  PARAMETERS:
  326. //    hwnd - The window handing the message.
  327. //    uMessage - The message number. (unused).
  328. //    wparam - Message specific data (unused).
  329. //    lparam - Message specific data (unused).
  330. //
  331. //  RETURN VALUE:
  332. //    Always returns 0 - message handled.
  333. //
  334. //  COMMENTS:
  335. //
  336. //
  337.  
  338. #pragma argsused
  339. LRESULT MsgMCDestroy(HWND hwnd, UINT uMessage, WPARAM wparam, LPARAM lparam)
  340. {
  341.      cOpen -= 1;
  342. // Because we are checking the return value of GetProp(), the function
  343. // failure reported by CodeGuard on the line below can safely be ignored.
  344. // GetProp() is used here and elsewhere in this program to determine if
  345. // a property has been set, and thus failures are expected and constitute
  346. // correct behavior.
  347.      if (GetProp(hwnd, "FilenameSet"))
  348.           RemoveProp(hwnd, "FilenameSet");
  349.  
  350.      return 0;
  351. }
  352.  
  353.  
  354. //
  355. //  FUNCTION: CmdEdit(HWND, WORD, WORD, HWND)
  356. //
  357. //  PURPOSE: Hand edit control notifications.
  358. //
  359. //  PARAMETERS:
  360. //    hwnd     - The window.
  361. //    wCommand - IDC_EXIT (unused)
  362. //    wNotify  - EN_*
  363. //    hwndCtrl - NULL (unused)
  364. //
  365. //  RETURN VALUE:
  366. //    Always returns 0 - command handled.
  367. //
  368. //  COMMENTS:
  369. //    Handle the edit control's out of space error by putting up an
  370. //    "Out of Memory" warning dialog.
  371. //
  372.  
  373. #pragma argsused
  374. LRESULT CmdEdit(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  375. {
  376.     switch (wNotify)
  377.     {
  378.         case EN_ERRSPACE:
  379.             MessageBox(hwnd, 
  380.                        "Out of memory.", 
  381.                        SZDESCRIPTION, 
  382.                        MB_ICONHAND | MB_OK);
  383.             break;
  384.      }
  385.     return 0;
  386. }
  387.  
  388.  
  389. //
  390. //  FUNCTION: CreateMDIChild(LPSTR)
  391. //
  392. //  PURPOSE: Create an MDI child window, setting caption to szFileName
  393. //
  394. //  PARAMETERS:
  395. //    hwnd - The main application window.
  396. //
  397. //  RETURN VALUE:
  398. //    TRUE  - If creation was successful.
  399. //    FALSE - If creation failed.
  400. //
  401. //  COMMENTS:
  402. //
  403.  
  404. BOOL CreateMDIChild(LPSTR szFileName)
  405. {
  406.     HWND hwndChild;
  407.     DWORD dwVersion;
  408.  
  409.     // Create the MDI child window
  410.  
  411.     // Windows NT and Windows 95 present different options for creating
  412.     // an MDI child window.  While using the WM_MDICREATE message will
  413.     // work on both Windows versions, Windows 95 presents a new window
  414.     // style which simplifies the process.  Here the function uses the
  415.     // method apropriate for the system it's running on.
  416.  
  417.     dwVersion = GetVersion();
  418.     if ((dwVersion < 0x80000000) || (LOBYTE(LOWORD(dwVersion)) < 4))
  419.     {
  420.         // This is Windows NT or Win32s, so use the WM_MDICREATE message
  421.         MDICREATESTRUCT mcs;
  422.  
  423.         mcs.szClass = szChildName;      // window class name
  424.         mcs.szTitle = szFileName;       // window title
  425.         mcs.hOwner  = hInst;            // owner
  426.         mcs.x       = CW_USEDEFAULT;    // x position
  427.         mcs.y       = CW_USEDEFAULT;    // y position
  428.         mcs.cx      = CW_USEDEFAULT;    // width
  429.         mcs.cy      = CW_USEDEFAULT;    // height
  430.         mcs.style   = 0;                // window style
  431.         mcs.lParam  = 0;                // lparam
  432.  
  433.         hwndChild = (HWND) SendMessage(hwndMDIClient,
  434.                                        WM_MDICREATE,
  435.                                        0,
  436.                                        (LPARAM)(LPMDICREATESTRUCT) &mcs);
  437.     }
  438.     else
  439.     {
  440.         // This method will only work with Windows 95, not Windows NT or Win32s
  441.         hwndChild = CreateWindowEx(WS_EX_MDICHILD,  // EX window style
  442.                                    szChildName,     // window class name
  443.                                    szFileName,      // window title
  444.                                    0,               // window style
  445.                                    CW_USEDEFAULT,   // x position
  446.                                    CW_USEDEFAULT,   // y position
  447.                                    CW_USEDEFAULT,   // width
  448.                                    CW_USEDEFAULT,   // height
  449.                                    hwndMDIClient,   // parent
  450.                                    NULL,            // menu (child ID)
  451.                                    hInst,           // owner
  452.                                    0);              // lparam
  453.     }
  454.  
  455.     if (hwndChild != NULL)
  456.     {
  457.         ShowWindow(hwndChild, SW_SHOW);
  458.         SetProp(hwndChild, "FilenameSet", 0);
  459.  
  460.         cUntitled += 1;
  461.         cOpen += 1;
  462.         return TRUE;
  463.     }
  464.     else
  465.         return FALSE;
  466. }
  467.  
  468.  
  469. //
  470. //  FUNCTION: CreateEditControl(HWND)
  471. //
  472. //  PURPOSE: Create the edit control with the MDI child as the parent
  473. //
  474. //  PARAMETERS:
  475. //    hwnd - The MDI child window.
  476. //
  477. //  RETURN VALUE:
  478. //    TRUE - If initialization was successful.
  479. //    FALSE - If initialization failed.
  480. //
  481. //  COMMENTS:
  482. //
  483.  
  484. BOOL CreateEditControl(HWND hwndMDIChild)
  485. {
  486.     RECT rc;
  487.     HWND hwndEdit;
  488.  
  489.     GetClientRect(hwndMDIChild, &rc);
  490.  
  491.     hwndEdit = CreateWindow("Edit",
  492.                             NULL,
  493.                             WS_CHILD   | WS_VISIBLE | ES_MULTILINE   |
  494.                             WS_VSCROLL | WS_HSCROLL | ES_AUTOHSCROLL |
  495.                             ES_AUTOVSCROLL | ES_NOHIDESEL,
  496.                             0, 0,
  497.                             (rc.right-rc.left), (rc.bottom-rc.top),
  498.                             hwndMDIChild,
  499.                             (HMENU)IDC_EDIT,           // Child control i.d.
  500.                             hInst,
  501.                             NULL);
  502.  
  503.     if (!hwndEdit)
  504.     {
  505.         DestroyWindow(hwndMDIChild);
  506.         return FALSE;
  507.     }
  508.  
  509.     return TRUE;
  510. }
  511.  
  512.  
  513. //
  514. //  FUNCTION: GetEditWindow(HWND)
  515. //
  516. //  PURPOSE: Return a handle to the current edit control.  The "current"
  517. //           edit control is contained within the active MDI child
  518. //
  519. //  PARAMETERS:
  520. //    hwdnMDIChild - handle to the MDI Child window
  521. //
  522. //  RETURN VALUE:
  523. //    A handle to the current edit control.
  524. //
  525. //  COMMENTS:
  526. //    If hwndMDIChild is NULL on entry, we'll return the handle to the
  527. //    edit control in the active MDI child
  528. //
  529.  
  530. HWND GetEditWindow(HWND hwndMDIChild)
  531. {
  532.     HWND hwndEdit;
  533.     
  534.     if (!hwndMDIChild)
  535.         hwndMDIChild = GetActiveMDIChild();
  536.  
  537.     hwndEdit = GetDlgItem(hwndMDIChild, IDC_EDIT);
  538.  
  539.     return hwndEdit;
  540. }
  541.  
  542.  
  543. //
  544. //  FUNCTION: GetActiveMDIChild(void)
  545. //
  546. //  PURPOSE: Return a handle to the current active MDI child
  547. //
  548. //  PARAMETERS:
  549. //    void
  550. //
  551. //  RETURN VALUE:
  552. //    A handle to the current active MDI child
  553. //
  554. //  COMMENTS:
  555. //    
  556.  
  557. HWND GetActiveMDIChild(void)
  558. {
  559.     HWND hwndMDIChild;
  560.     
  561.     hwndMDIChild = (HWND)SendMessage(hwndMDIClient, 
  562.                                      WM_MDIGETACTIVE, 
  563.                                      0, 0L);
  564.  
  565.     return hwndMDIChild;
  566. }
  567.  
  568.  
  569. //
  570. //  FUNCTION: SetEditText(HWND, hsz)
  571. //
  572. //  PURPOSE: Set the text of the edit control hwnd.
  573. //
  574. //  PARAMETERS:
  575. //    hwnd - The edit control to set.
  576. //    hsz  - A local handle to the text to set.
  577. //
  578. //  RETURN VALUE:
  579. //    NONE
  580. //
  581. //  COMMENTS:
  582. //    
  583. //
  584.  
  585. #pragma argsused
  586. VOID SetEditText(HWND hwnd, HANDLE hsz)
  587. {
  588.      char *sz = LocalLock(hsz);
  589.      SendMessage(GetEditWindow(NULL), WM_SETTEXT, 0, (LPARAM)(LPSTR)sz);
  590.     LocalUnlock(hsz);
  591.     LocalFree(hsz);
  592. }
  593.  
  594.  
  595. //
  596. //  FUNCTION: LockEditText(HWND)
  597. //
  598. //  PURPOSE: Return a handle to the text associated with the edit control.
  599. //
  600. //  PARAMETERS:
  601. //    hwnd - The edit control whose text is to be locked.
  602. //
  603. //  RETURN VALUE:
  604. //    A local buffer containing the text associated with the editor control.
  605. //
  606. //  COMMENTS:
  607. //
  608. //
  609.  
  610. char *LockEditText(HWND hwnd)
  611. {
  612.      INT cbText;
  613.      char *sz;
  614.  
  615.      cbText = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0L) + 1;
  616.      hszEditBuffer = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, cbText);
  617.      if (hszEditBuffer == NULL) return NULL;
  618.      sz = LocalLock(hszEditBuffer);
  619.      if (sz == NULL)
  620.      {
  621.         LocalFree(hszEditBuffer);
  622.         hszEditBuffer = NULL;
  623.         return NULL;
  624.     }
  625.     SendMessage(hwnd, WM_GETTEXT, cbText, (LPARAM)(LPSTR)sz);
  626.     return sz;
  627. }
  628.  
  629.  
  630. //
  631. //  FUNCTION: UnlockEditText(HWND)
  632. //
  633. //  PURPOSE: Return a handle to the text associated with the edit control.
  634. //
  635. //  PARAMETERS:
  636. //    hwnd - The edit control whose text is to be unlocked.
  637. //
  638. //  RETURN VALUE:
  639. //    NONE
  640. //
  641. //  COMMENTS:
  642. //
  643. //
  644.  
  645. VOID UnlockEditText(HWND hwnd)
  646. {
  647.     SetEditText(hwnd, hszEditBuffer);
  648.     hszEditBuffer = NULL;
  649. }
  650.