|
|
1.1 root 1: /***************************************************************************
2: * *
3: * PROGRAM : MultiPad.c *
4: * *
5: * PURPOSE : To give a multi-Notepad demonstration of the new MDI *
6: * API in Windows 3.0 *
7: * *
8: * FUNCTIONS : WinMain() - Calls the initialization function *
9: * and processes message loop *
10: * *
11: * MPFrameWndProc() - Window function for the "frame" *
12: * window, which controls the menu *
13: * and contains the MDI document *
14: * windows as child windows. *
15: * *
16: * MPMDIChildWndProc() - Window function for the individual *
17: * document windows *
18: * *
19: * InitializeMenu() - Handles enabling/greying of menu *
20: * items according to the app's state.*
21: * *
22: * CloseAllChildren - Destroys all MDI child windows. *
23: * *
24: * CommandHandler() - Processes the "frame" window's *
25: * WM_COMMAND messages. *
26: * *
27: * InstallDlgProc() - Dialog function for the install *
28: * dialog which appears when the *
29: * application is first launched. *
30: * *
31: * AboutDlgProc() - Dialog function for the ubiquitous *
32: * About.. dialog. *
33: * *
34: * SetWrap() - Alters word wrapping in the edit *
35: * control. *
36: * *
37: * MPError() - Flashes an error messagebox. *
38: * *
39: * QueryCloseChild - Prompts for saving current MDI *
40: * child window. *
41: * *
42: * QueryCloseAllChildren() - Asks whether it is OK to close *
43: * down app. *
44: * *
45: ***************************************************************************/
46:
47: #include "multipad.h"
48: #include <string.h>
49: #include <stdio.h>
50: #include "regdb.h"
51:
52: /* global variables used in this module or among more than one module */
53: HANDLE hInst; /* Program instance handle */
54: HANDLE hAccel; /* Main accelerator resource */
55: HWND hwndFrame = NULL; /* Handle to main window */
56: HWND hwndMDIClient = NULL; /* Handle to MDI client */
57: HWND hwndActive = NULL; /* Handle to currently activated child */
58: HWND hwndActiveEdit = NULL; /* Handle to edit control */
59: LONG styleDefault = 0; /* Default style bits for child windows */
60: /* The first window is created maximized */
61: /* to resemble Notepad. Later children */
62: /* are normal windows. */
63: LPSTR lpMenu = IDMULTIPAD; /* Contains the resource id of the */
64: /* current frame menu */
65:
66:
67: /* Forward declarations of helper functions in this module */
68: VOID NEAR PASCAL InitializeMenu (HANDLE);
69: VOID NEAR PASCAL CommandHandler (HWND, UINT, LONG);
70: BOOL NEAR PASCAL SetWrap (HWND,BOOL);
71: BOOL NEAR PASCAL QueryCloseAllChildren ( VOID );
72: INT NEAR PASCAL QueryCloseChild (HWND);
73: LPSTR GetCmdLine( VOID );
74:
75: /****************************************************************************
76: * *
77: * FUNCTION : WinMain(HANDLE, HANDLE, LPSTR, int) *
78: * *
79: * PURPOSE : Creates the "frame" window, does some initialization and *
80: * enters the message loop. *
81: * *
82: ****************************************************************************/
83: int PASCAL WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)
84: HANDLE hInstance; /* current instance */
85: HANDLE hPrevInstance; /* previous instance */
86: LPSTR lpCmdLine; /* command line */
87: int nCmdShow; /* show-window type (open/icon) */
88: {
89: MSG msg;
90:
91: hInst = hInstance;
92:
93: /* If this is the first instance of the app. register window classes */
94: if (!hPrevInstance){
95: if (!InitializeApplication ())
96: return 0;
97: }
98:
99: lpCmdLine = GetCmdLine();
100:
101: /* Create the frame and do other initialization */
102: if (!InitializeInstance (lpCmdLine, nCmdShow))
103: return 0;
104:
105: /* Enter main message loop */
106: while (GetMessage (&msg, NULL, 0, 0)){
107: /* If a keyboard message is for the MDI , let the MDI client
108: * take care of it. Otherwise, check to see if it's a normal
109: * accelerator key (like F3 = find next). Otherwise, just handle
110: * the message as usual.
111: */
112: if ( !TranslateMDISysAccel (hwndMDIClient, &msg) &&
113: !TranslateAccelerator (hwndFrame, hAccel, &msg)){
114: TranslateMessage (&msg);
115: DispatchMessage (&msg);
116: }
117: }
118: return 0;
119: }
120:
121: /****************************************************************************
122: * *
123: * FUNCTION : MPFrameWndProc (hwnd, msg, wParam, lParam ) *
124: * *
125: * PURPOSE : The window function for the "frame" window, which controls *
126: * the menu and encompasses all the MDI child windows. Does *
127: * the major part of the message processing. Specifically, in *
128: * response to: *
129: * *
130: * WM_CREATE : Creates and displays the "frame". *
131: * *
132: * WM_INITMENU : Sets up the state of the menu. *
133: * *
134: * WM_WININICHANGE & : If default printer characteristics*
135: * WM_DEVMODECHANGE have been changed, reinitialises *
136: * printer DC. *
137: * *
138: * WM_COMMAND : Passes control to a command- *
139: * handling function. *
140: * *
141: * WM_CLOSE : Quits the app. if all the child *
142: * windows agree. *
143: * *
144: * WM_QUERYENDSESSION : Checks that all child windows *
145: * agree to quit. *
146: * *
147: * WM_DESTROY : Destroys frame window and quits *
148: * app. *
149: * *
150: ****************************************************************************/
151: LONG APIENTRY MPFrameWndProc (
152: register HWND hwnd,
153: UINT msg,
154: UINT wParam,
155: LONG lParam)
156:
157: {
158: switch (msg){
159: case WM_CREATE:{
160:
161: CLIENTCREATESTRUCT ccs;
162: HDC hdc;
163:
164: /* Find window menu where children will be listed */
165: ccs.hWindowMenu = GetSubMenu (GetMenu(hwnd),WINDOWMENU);
166: ccs.idFirstChild = IDM_WINDOWCHILD;
167:
168: /* Create the MDI client filling the client area */
169: hwndMDIClient = CreateWindow ("mdiclient",
170: NULL,
171: WS_CHILD | WS_CLIPCHILDREN |
172: WS_VSCROLL | WS_HSCROLL,
173: 0,
174: 0,
175: 0,
176: 0,
177: hwnd,
178: (HMENU)0xCAC,
179: hInst,
180: (LPSTR)&ccs);
181:
182:
183: ShowWindow (hwndMDIClient,SW_SHOW);
184:
185: /* Check if printer can be initialized */
186: if (hdc = GetPrinterDC (TRUE)){
187: DeleteDC (hdc);
188: }
189:
190: break;
191: }
192:
193: case WM_INITMENU:
194: /* Set up the menu state */
195: InitializeMenu ((HMENU)wParam);
196: break;
197:
198: case WM_WININICHANGE:
199: case WM_DEVMODECHANGE:{
200:
201: /* If control panel changes default printer characteristics,
202: * reinitialize our printer information...
203: */
204: HDC hdc;
205:
206: if (hdc = GetPrinterDC (TRUE)){
207: DeleteDC (hdc);
208: }
209: break;
210: }
211:
212:
213: case WM_COMMAND:
214: /* Direct all menu selection or accelerator commands to another
215: * function
216: */
217: CommandHandler(hwnd, wParam, lParam);
218: break;
219:
220: case WM_CLOSE:
221: /* don't close if any children cancel the operation */
222: if (!QueryCloseAllChildren ()) break;
223:
224: SaveConfiguration();
225:
226: DestroyWindow (hwnd);
227: break;
228:
229: case WM_QUERYENDSESSION:
230: /* Before session ends, check that all files are saved */
231: return QueryCloseAllChildren ();
232:
233: case WM_DESTROY:
234: PostQuitMessage (0);
235: break;
236:
237: default:
238: /* use DefFrameProc() instead of DefWindowProc() since there
239: * are things that have to be handled differently because of MDI
240: */
241: return DefFrameProc (hwnd,hwndMDIClient,msg,wParam,lParam);
242: }
243: return 0;
244: }
245:
246: /****************************************************************************
247: * *
248: * FUNCTION : MPMDIWndProc ( hwnd, msg, wParam, lParam ) *
249: * *
250: * PURPOSE : The window function for the individual document windows, *
251: * each of which has a "note". Each of these windows contain *
252: * one multi-line edit control filling their client area. *
253: * In response to the following: *
254: * *
255: * WM_CREATE : Creates & diplays an edit control *
256: * and does some initialization. *
257: * *
258: * WM_MDIACTIVATE : Activates/deactivates the child. *
259: * *
260: * WM_SETFOCUS : Sets focus on the edit control. *
261: * *
262: * WM_SIZE : Resizes the edit control. *
263: * *
264: * WM_COMMAND : Processes some of the edit *
265: * commands, saves files and alters *
266: * the edit wrap state. *
267: * *
268: * WM_CLOSE : Closes child if it is ok to do so.*
269: * *
270: * WM_QUERYENDSESSION : Same as above. *
271: * *
272: ****************************************************************************/
273:
274: LONG APIENTRY MPMDIChildWndProc (
275: register HWND hwnd,
276: UINT msg,
277: register UINT wParam,
278: LONG lParam)
279:
280: {
281: HWND hwndEdit;
282:
283: switch (msg){
284: case WM_CREATE:
285: {
286: DWORD dws= WS_CHILD | WS_MAXIMIZE | WS_VISIBLE
287: | WS_VSCROLL | ES_AUTOVSCROLL
288: | ES_MULTILINE;
289:
290: if (!fTextWrapDefault) dws |= WS_HSCROLL | ES_AUTOHSCROLL;
291:
292: /* Create an edit control */
293: hwndEdit = CreateWindow ("edit",
294: NULL,
295: dws,
296: 0,
297: 0,
298: 0,
299: 0,
300: hwnd,
301: (HMENU)ID_EDIT,
302: hInst,
303: NULL);
304:
305: /* Remember the window handle and initialize some window attributes */
306: SetWindowLong (hwnd, GWL_HWNDEDIT, (LONG) hwndEdit);
307: SetWindowWord (hwnd, GWW_CHANGED, FALSE);
308: SetWindowWord (hwnd, GWL_WORDWRAP, (WORD) fTextWrapDefault);
309: SetWindowWord (hwnd, GWW_UNTITLED, TRUE);
310: SetFocus (hwndEdit);
311: break;
312: }
313:
314: case WM_MDIACTIVATE:
315: /* If we're activating this child, remember it */
316: if (GET_WM_MDIACTIVATE_FACTIVATE(hwnd, wParam, lParam)){
317: hwndActive = hwnd;
318: hwndActiveEdit = (HWND)GetWindowLong (hwnd, GWL_HWNDEDIT);
319: }
320: else{
321: hwndActive = NULL;
322: hwndActiveEdit = NULL;
323: }
324: break;
325:
326: case WM_QUERYENDSESSION:
327: /* Prompt to save the child */
328: return !QueryCloseChild (hwnd);
329:
330: case WM_CLOSE:
331: /* If its OK to close the child, do so, else ignore */
332: if (QueryCloseChild (hwnd))
333: goto CallDCP;
334: else
335: break;
336:
337: case WM_SIZE:{
338: RECT rc;
339:
340: /* On creation or resize, size the edit control. */
341: hwndEdit = (HWND)GetWindowLong (hwnd, GWL_HWNDEDIT);
342: GetClientRect (hwnd, &rc);
343: MoveWindow (hwndEdit,
344: rc.left,
345: rc.top,
346: rc.right-rc.left,
347: rc.bottom-rc.top,
348: TRUE);
349: goto CallDCP;
350: }
351:
352: case WM_SETFOCUS:
353: SetFocus ((HWND)GetWindowLong (hwnd, GWL_HWNDEDIT));
354: break;
355:
356: case WM_COMMAND:
357: switch (LOWORD(wParam)){
358: case ID_EDIT:
359: switch (GET_WM_COMMAND_CMD(wParam, lParam)){
360: case EN_CHANGE:
361:
362: /* If the contents of the edit control have changed,
363: set the changed flag
364: */
365: SetWindowWord (hwnd, GWW_CHANGED, TRUE);
366: break;
367:
368: case EN_ERRSPACE:
369: /* If the control is out of space, honk */
370: MessageBeep (0);
371: break;
372:
373: default:
374: goto CallDCP;
375: }
376: break;
377:
378: case IDM_FILESAVE:
379: /* If empty file, ignore save */
380: if ((GetWindowWord(hwnd, GWW_UNTITLED)) && (!ChangeFile(hwnd)))
381: break;
382:
383: /* Save the contents of the edit control and reset the
384: * changed flag
385: */
386: SaveFile (hwnd);
387: SetWindowWord (hwnd, GWW_CHANGED, FALSE);
388: break;
389:
390: case IDM_EDITWRAP: {
391: INT fWrap = GetWindowWord (hwnd, GWL_WORDWRAP);
392:
393: /* Set the wrap state, or report it */
394: if (GET_WM_COMMAND_HWND(wParam, lParam)){
395: fWrap = !fWrap;
396: if(!SetWrap (hwnd, fWrap)){
397: fWrap = !fWrap; /* call failed, restore original fWrap */
398: }
399: }
400:
401: /* return wrap state */
402: return fWrap;
403: }
404:
405: default:
406: goto CallDCP;
407: }
408: break;
409:
410: default:
411: CallDCP:
412: /* Again, since the MDI default behaviour is a little different,
413: * call DefMDIChildProc instead of DefWindowProc()
414: */
415: return DefMDIChildProc (hwnd, msg, wParam, lParam);
416: }
417: return FALSE;
418: }
419:
420:
421: /****************************************************************************
422: * *
423: * FUNCTION : AboutDlgProc ( hwnd, msg, wParam, lParam ) *
424: * *
425: * PURPOSE : Dialog function for the About MultiPad... dialog. *
426: * *
427: ****************************************************************************/
428: BOOL APIENTRY AboutDlgProc (
429: HWND hwnd,
430: register UINT msg,
431: register UINT wParam,
432: LONG lParam)
433: {
434: switch (msg){
435: case WM_INITDIALOG:
436: {
437: PSZ pszInstallName= NULL, pszInstallOrg= NULL;
438:
439: LONG cbName= 0, cbOrg= 0, lResult;
440:
441: DWORD dwType;
442:
443: lResult= RegQueryValueEx(hkGlobal, KEY_VALUE_INSTALL_NAME, NULL,
444: &dwType, NULL, &cbName
445: );
446:
447: if ( lResult == ERROR_SUCCESS && dwType == REG_SZ)
448: if (pszInstallName= _alloca(cbName))
449: if (ERROR_SUCCESS != RegQueryValueEx
450: (hkGlobal, KEY_VALUE_INSTALL_NAME, NULL,
451: &dwType, (LPBYTE) pszInstallName, &cbName
452: )
453: ) pszInstallName= NULL;
454:
455: lResult= RegQueryValueEx(hkGlobal, KEY_VALUE_INSTALL_ORG, NULL,
456: &dwType, NULL, &cbOrg
457: );
458:
459: if ( lResult == ERROR_SUCCESS && dwType == REG_SZ)
460: if (pszInstallOrg= _alloca(cbOrg))
461: if (ERROR_SUCCESS != RegQueryValueEx
462: (hkGlobal, KEY_VALUE_INSTALL_ORG, NULL,
463: &dwType, (LPBYTE) pszInstallOrg, &cbOrg
464: )
465: ) pszInstallOrg= NULL;
466:
467: // Need to setup the "Installed by..." strings in the dialog.
468:
469: if (pszInstallName)
470: SendDlgItemMessage(hwnd, EB_NAME, WM_SETTEXT, 0,
471: (LPARAM) pszInstallName
472: );
473:
474: if (pszInstallOrg)
475: SendDlgItemMessage(hwnd, EB_ORGANIZATION, WM_SETTEXT, 0,
476: (LPARAM) pszInstallOrg
477: );
478:
479: break;
480: }
481:
482: case WM_COMMAND:
483: switch (LOWORD(wParam)){
484: case IDOK:
485: case IDCANCEL:
486: EndDialog(hwnd, 0);
487: break;
488:
489: default:
490: return FALSE;
491: }
492: break;
493:
494: default:
495: return FALSE;
496: }
497:
498: return TRUE;
499: UNREFERENCED_PARAMETER(lParam);
500: }
501:
502: /****************************************************************************
503: * *
504: * FUNCTION : InstallDlgProc ( hwnd, msg, wParam, lParam ) *
505: * *
506: * PURPOSE : Dialog function for Installing RegMpad in the registry *
507: * *
508: ****************************************************************************/
509: BOOL APIENTRY InstallDlgProc (
510: HWND hwnd,
511: register UINT msg,
512: register UINT wParam,
513: LONG lParam)
514: {
515:
516: switch (msg){
517: case WM_INITDIALOG:
518:
519: SetWindowLong(hwnd, DWL_USER, lParam);
520:
521: break;
522:
523: case WM_COMMAND:
524:
525: switch (LOWORD(wParam)){
526: case PB_INSTALL:
527:
528: {
529: PSZ pszNewName, pszNewOrg;
530: int cbName, cbOrg;
531: HWND hwndName, hwndOrg;
532: char *pc, c;
533:
534: BOOL fNameGiven, fOrgGiven;
535:
536: hwndName = GetDlgItem(hwnd, EB_NAME);
537: hwndOrg = GetDlgItem(hwnd, EB_ORGANIZATION);
538:
539: if ( !(cbName = GetWindowTextLength(hwndName))
540: || !(cbOrg = GetWindowTextLength(hwndOrg ))
541: )
542: {
543: MPError(hwnd, MB_OK | MB_ICONHAND,
544: IDS_NEED_NAME_ORG,
545: NULL
546: );
547:
548: break;
549: }
550:
551: pszNewName = _alloca(cbName + 1);
552: pszNewOrg = _alloca(cbOrg + 1);
553:
554: GetWindowText(hwndName, pszNewName, cbName+1);
555: GetWindowText(hwndOrg , pszNewOrg , cbOrg +1);
556:
557: for (fNameGiven= FALSE, pc= pszNewName; c= *pc++; )
558: if (c != ' ')
559: {
560: fNameGiven= TRUE; break;
561: }
562:
563: for (fOrgGiven= FALSE, pc= pszNewOrg; c= *pc++; )
564: if (c != ' ')
565: {
566: fOrgGiven= TRUE; break;
567: }
568:
569: if (!fOrgGiven || !fNameGiven)
570: {
571: MPError(hwnd, MB_OK | MB_ICONHAND,
572: IDS_NEED_NAME_ORG,
573: NULL
574: );
575:
576: break;
577: }
578:
579: if (StoreAppConfig(hwnd,
580: (PSZ) GetWindowLong(hwnd, DWL_USER),
581: pszNewName, pszNewOrg,
582: 1 == IsDlgButtonChecked
583: (hwnd, CB_DEFAULT_WRAP)
584: )
585: ) EndDialog(hwnd, 1);
586:
587: break;
588: }
589:
590:
591: case IDCANCEL:
592: EndDialog(hwnd, 0);
593: break;
594:
595: default:
596: return FALSE;
597: }
598: break;
599:
600: default:
601: return FALSE;
602: }
603:
604: return TRUE;
605: }
606:
607: /****************************************************************************
608: * *
609: * FUNCTION : OptionsDlgProc ( hwnd, msg, wParam, lParam ) *
610: * *
611: * PURPOSE : Dialog function for Setting per-user options *
612: * *
613: ****************************************************************************/
614: BOOL APIENTRY OptionsDlgProc (
615: HWND hwnd,
616: register UINT msg,
617: register UINT wParam,
618: LONG lParam)
619: {
620:
621: switch (msg){
622: case WM_INITDIALOG:
623:
624: CheckDlgButton(hwnd, CB_DEFAULT_WRAP, fTextWrapDefault? 1 : 0);
625:
626: break;
627:
628: case WM_COMMAND:
629:
630: switch (LOWORD(wParam)){
631: case IDOK:
632:
633: fTextWrapDefault= 1 == IsDlgButtonChecked
634: (hwnd, CB_DEFAULT_WRAP);
635:
636: RegSetValueEx(hkPerUser, WORD_WRAP_DEFAULT, 0,
637: REG_DWORD, (LPBYTE) &fTextWrapDefault,
638: sizeof(fTextWrapDefault)
639: );
640:
641: EndDialog(hwnd, 1);
642:
643: break;
644:
645: case IDCANCEL:
646: EndDialog(hwnd, 0);
647: break;
648:
649: default:
650: return FALSE;
651: }
652: break;
653:
654: default:
655: return FALSE;
656: }
657:
658: return TRUE;
659: UNREFERENCED_PARAMETER(lParam);
660: }
661:
662: /****************************************************************************
663: * *
664: * FUNCTION : Initializemenu ( hMenu ) *
665: * *
666: * PURPOSE : Sets up greying, enabling and checking of main menu items *
667: * based on the app's state. *
668: * *
669: ****************************************************************************/
670: VOID NEAR PASCAL InitializeMenu (register HANDLE hmenu)
671: {
672: register WORD status;
673: WORD i;
674: INT j;
675: LONG l;
676:
677: /* Is there any active child to talk to? */
678: if (hwndActiveEdit){
679: /* If edit control can respond to an undo request, enable the
680: * undo selection.
681: */
682: if (SendMessage (hwndActiveEdit, EM_CANUNDO, 0, 0L))
683:
684: status = MF_ENABLED;
685: else
686: status = MF_GRAYED;
687: EnableMenuItem (hmenu, IDM_EDITUNDO, status);
688:
689: /* If edit control is non-empty, allow cut/copy/clear */
690: l = (LONG)SendMessage(hwndActiveEdit, EM_GETSEL, 0, 0);
691:
692:
693: status = (WORD) ((HIWORD(l) == LOWORD(l)) ? MF_GRAYED : MF_ENABLED);
694: EnableMenuItem (hmenu, IDM_EDITCUT, status);
695: EnableMenuItem (hmenu, IDM_EDITCOPY, status);
696: EnableMenuItem (hmenu, IDM_EDITCLEAR, status);
697:
698: status=MF_GRAYED;
699: /* If the clipboard contains some CF_TEXT data, allow paste */
700: if (OpenClipboard (hwndFrame)){
701: UINT wFmt = 0;
702:
703: while (wFmt = EnumClipboardFormats (wFmt))
704: if (wFmt == CF_TEXT){
705: status = MF_ENABLED;
706: break;
707: }
708:
709: CloseClipboard ();
710: }
711: EnableMenuItem (hmenu, IDM_EDITPASTE, status);
712:
713: /* Set the word wrap state for the window */
714: if ((WORD) SendMessage(hwndActive, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_EDITWRAP, 0, 0)))
715: status = MF_CHECKED;
716: else
717: status = MF_UNCHECKED;
718: CheckMenuItem (hmenu, IDM_EDITWRAP, status);
719:
720: /* Enable search menu items only if there is a search string */
721: if (*szSearch)
722: status = MF_ENABLED;
723: else
724: status = MF_GRAYED;
725: EnableMenuItem (hmenu, IDM_SEARCHNEXT, status);
726: EnableMenuItem (hmenu, IDM_SEARCHPREV, status);
727:
728: /* Enable File/Print only if a printer is available */
729: status = (WORD) (iPrinter ? MF_ENABLED : MF_GRAYED);
730: EnableMenuItem (hmenu, IDM_FILEPRINT, status);
731:
732: /* select all and wrap toggle always enabled */
733: status = MF_ENABLED;
734: EnableMenuItem(hmenu, IDM_EDITSELECT, status);
735: EnableMenuItem(hmenu, IDM_EDITWRAP, status);
736: EnableMenuItem(hmenu, IDM_SEARCHFIND, status);
737: }
738: else {
739: /* There are no active child windows */
740: status = MF_GRAYED;
741:
742: /* No active window, so disable everything */
743: for (i = IDM_EDITFIRST; i <= IDM_EDITLAST; i++)
744: EnableMenuItem (hmenu, i, status);
745:
746: CheckMenuItem (hmenu, IDM_EDITWRAP, MF_UNCHECKED);
747:
748: for (i = IDM_SEARCHFIRST; i <= IDM_SEARCHLAST; i++)
749: EnableMenuItem (hmenu, i, status);
750:
751: EnableMenuItem (hmenu, IDM_FILEPRINT, status);
752:
753: }
754:
755: /* The following menu items are enabled if there is an active window */
756: EnableMenuItem (hmenu, IDM_FILESAVE, status);
757: EnableMenuItem (hmenu, IDM_FILESAVEAS, status);
758: EnableMenuItem (hmenu, IDM_WINDOWTILE, status);
759: EnableMenuItem (hmenu, IDM_WINDOWCASCADE, status);
760: EnableMenuItem (hmenu, IDM_WINDOWICONS, status);
761: EnableMenuItem (hmenu, IDM_WINDOWCLOSEALL, status);
762:
763: /* Allow printer setup only if printer driver supports device initialization */
764: if (iPrinter < 2)
765: status = MF_GRAYED;
766: EnableMenuItem ( hmenu, IDM_FILESETUP, status);
767: UNREFERENCED_PARAMETER(j);
768:
769: }
770:
771: /****************************************************************************
772: * *
773: * FUNCTION : CloseAllChildren () *
774: * *
775: * PURPOSE : Destroys all MDI child windows. *
776: * *
777: ****************************************************************************/
778: VOID NEAR PASCAL CloseAllChildren ()
779: {
780: register HWND hwndT;
781:
782: /* hide the MDI client window to avoid multiple repaints */
783: ShowWindow(hwndMDIClient,SW_HIDE);
784:
785: /* As long as the MDI client has a child, destroy it */
786: while ( hwndT = GetWindow (hwndMDIClient, GW_CHILD)){
787:
788: /* Skip the icon title windows */
789: while (hwndT && GetWindow (hwndT, GW_OWNER))
790: hwndT = GetWindow (hwndT, GW_HWNDNEXT);
791:
792: if (!hwndT)
793: break;
794:
795: SendMessage (hwndMDIClient, WM_MDIDESTROY, (UINT)hwndT, 0L);
796: }
797: }
798:
799: /****************************************************************************
800: * *
801: * FUNCTION : CommandHandler () *
802: * *
803: * PURPOSE : Processes all "frame" WM_COMMAND messages. *
804: * *
805: ****************************************************************************/
806: VOID NEAR PASCAL CommandHandler (
807: register HWND hwnd,
808: register UINT wParam,
809: LONG lParam)
810:
811: {
812: switch (LOWORD(wParam)){
813: case IDM_FILENEW:
814: /* Add a new, empty MDI child */
815: AddFile (NULL);
816: break;
817:
818: case IDM_FILEOPEN:
819: MyReadFile (hwnd);
820: break;
821:
822: case IDM_FILESAVE:
823:
824: // If the window hasn't been given a name yet, we treat
825: // The File/Save command as File/Save As...
826:
827: if (!GetWindowWord(hwndActive, GWW_UNTITLED))
828: {
829: /* Save the active child MDI */
830: SendMessage(hwndActive, WM_COMMAND,
831: GET_WM_COMMAND_MPS(IDM_FILESAVE, 0, 0)
832: );
833: break;
834: }
835:
836: case IDM_FILESAVEAS:
837: /* Save active child MDI under another name */
838: if (ChangeFile (hwndActive))
839: SendMessage(hwndActive, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_FILESAVE, 0, 0));
840: break;
841:
842: case IDM_FILEPRINT:
843: /* Print the active child MDI */
844: PrintFile (hwndActive);
845: break;
846:
847: case IDM_FILESETUP:
848: /* Set up the printer environment for this app */
849: GetInitializationData (hwnd);
850: break;
851:
852: case IDM_FILEMENU:{
853:
854: /* lengthen / shorten the size of the MDI menu */
855: HMENU hMenu;
856: HMENU hWindowMenu;
857: INT i;
858:
859: if (lpMenu == IDMULTIPAD){
860: lpMenu = IDMULTIPAD2;
861: i = SHORTMENU;
862: }
863: else{
864: lpMenu = IDMULTIPAD;
865: i = WINDOWMENU;
866: }
867:
868: hMenu = LoadMenu (hInst, lpMenu);
869: hWindowMenu = GetSubMenu (hMenu, i);
870:
871: /* Set the new menu */
872: hMenu = (HMENU)SendMessage (hwndMDIClient,
873: WM_MDISETMENU,
874: (UINT)hMenu,
875: (LONG)hWindowMenu);
876:
877: DestroyMenu (hMenu);
878: DrawMenuBar (hwndFrame);
879: break;
880: }
881:
882: case IDM_FILEEXIT:
883: /* Close Multipad */
884: SendMessage (hwnd, WM_CLOSE, 0, 0L);
885: break;
886:
887: case IDM_HELPABOUT:{
888:
889: DialogBox(hInst, (LPSTR)IDD_ABOUT, hwnd, AboutDlgProc);
890: break;
891: }
892:
893: /* The following are edit commands. Pass these off to the active
894: * child's edit control window.
895: */
896: case IDM_EDITCOPY:
897: SendMessage (hwndActiveEdit, WM_COPY, 0, 0L);
898: break;
899:
900: case IDM_EDITPASTE:
901: SendMessage (hwndActiveEdit, WM_PASTE, 0, 0L);
902: break;
903:
904: case IDM_EDITCUT:
905: SendMessage (hwndActiveEdit, WM_CUT, 0, 0L);
906: break;
907:
908: case IDM_EDITCLEAR:
909: SendMessage (hwndActiveEdit, EM_REPLACESEL, 0,( LONG)(LPSTR)"");
910: break;
911:
912: case IDM_EDITSELECT:
913: SendMessage(hwndActiveEdit, EM_SETSEL, GET_EM_SETSEL_MPS(0, 0xe000));
914: break;
915:
916: case IDM_EDITUNDO:
917: SendMessage (hwndActiveEdit, EM_UNDO, 0, 0L);
918: break;
919:
920: case IDM_EDITWRAP:
921: SendMessage(hwndActive, WM_COMMAND, GET_WM_COMMAND_MPS(IDM_EDITWRAP, 1, 0));
922: break;
923:
924: case IDM_OPTIONS:
925: DialogBox(hInst, (LPSTR)DLG_PER_USER_CONFIG, hwnd, OptionsDlgProc);
926: break;
927:
928: case IDM_SEARCHFIND:
929: /* Put up the find dialog box */
930: Find ();
931: break;
932:
933: case IDM_SEARCHNEXT:
934: /* Find next occurence */
935: FindNext ();
936: break;
937:
938: case IDM_SEARCHPREV:
939: /* Find previous occurence */
940: FindPrev ();
941: break;
942:
943: /* The following are window commands - these are handled by the
944: * MDI Client.
945: */
946: case IDM_WINDOWTILE:
947: /* Tile MDI windows */
948: SendMessage (hwndMDIClient, WM_MDITILE, 0, 0L);
949: break;
950:
951: case IDM_WINDOWCASCADE:
952: /* Cascade MDI windows */
953: SendMessage (hwndMDIClient, WM_MDICASCADE, 0, 0L);
954: break;
955:
956: case IDM_WINDOWICONS:
957: /* Auto - arrange MDI icons */
958: SendMessage (hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
959: break;
960:
961: case IDM_WINDOWCLOSEALL:
962: /* Abort operation if something is not saved */
963: if (!QueryCloseAllChildren())
964: break;
965:
966: CloseAllChildren();
967:
968: /* Show the window since CloseAllChilren() hides the window
969: * for fewer repaints.
970: */
971: ShowWindow( hwndMDIClient, SW_SHOW);
972:
973: break;
974:
975: default:
976: /*
977: * This is essential, since there are frame WM_COMMANDS generated
978: * by the MDI system for activating child windows via the
979: * window menu.
980: */
981: DefFrameProc(hwnd, hwndMDIClient, WM_COMMAND, wParam, lParam);
982: }
983: }
984: /****************************************************************************
985: * *
986: * FUNCTION : SetWrap () *
987: * *
988: * PURPOSE : Changes the word wrapping in an edit control. Since this *
989: * cannot be done by direct means, the function creates a new *
990: * edit control, moves data from the old control to the new *
991: * control and destroys the original control. Note that the *
992: * function assumes that the child being modified is currently*
993: * active. * *
994: * *
995: ****************************************************************************/
996:
997: BOOL NEAR PASCAL SetWrap(
998: HWND hwnd,
999: BOOL fWrap)
1000:
1001: {
1002: LONG dws;
1003: HANDLE hT;
1004: HANDLE hTT;
1005: HWND hwndOld;
1006: HWND hwndNew;
1007: RECT rc;
1008:
1009: /* Change word wrap mode */
1010: SetWindowLong (hwnd, GWL_WORDWRAP, fWrap);
1011:
1012: /* Create the appropriate window style, adding a horizontal scroll
1013: * facility if wrapping is not present.
1014: */
1015: dws = WS_CHILD | WS_VSCROLL | ES_AUTOVSCROLL | ES_MULTILINE;
1016: if (!fWrap)
1017: dws |= WS_HSCROLL | ES_AUTOHSCROLL;
1018:
1019: /* Create a new child window */
1020: hwndNew = CreateWindow ( "edit",
1021: NULL,
1022: dws,
1023: 0,
1024: SW_SHOW,
1025: 0,
1026: 0,
1027: hwnd,
1028: (HMENU)ID_EDIT,
1029: hInst,
1030: NULL);
1031:
1032: /* Get handle to current edit control */
1033: hwndOld = (HWND)GetWindowLong (hwnd, GWL_HWNDEDIT);
1034:
1035: /* Get the data handle of the old control */
1036: hT = (HANDLE)SendMessage (hwndOld, EM_GETHANDLE, 0, 0L);
1037:
1038: /* Create a dummy data handle and make it the handle to
1039: * the old edit control( hT still references the text of
1040: * old control).
1041: */
1042: hTT = LocalAlloc (LHND, 0);
1043: if(!hTT){
1044: MessageBox(hwnd, "<SetWrap> Not enough memory. Can't Change Wrap Mode!", NULL, MB_OK | MB_ICONHAND);
1045: return(FALSE);
1046: }
1047:
1048: SendMessage (hwndOld, EM_SETHANDLE, (UINT)hTT, 0L);
1049:
1050: /* Make the new window the window of interest and destroy the
1051: * old control.
1052: */
1053: SetWindowLong (hwnd, GWL_HWNDEDIT, (LONG)hwndNew);
1054: hwndActiveEdit = hwndNew;
1055: DestroyWindow (hwndOld);
1056:
1057: /* Cause the window to be properly sized */
1058: SendMessage (hwnd, WM_SIZE, 0, 0L);
1059:
1060: /* Free the new window's old data handle and set it to
1061: * hT (text of old edit control)
1062: */
1063: LocalFree ((HANDLE)SendMessage (hwndNew, EM_GETHANDLE, 0, 0L));
1064: SendMessage (hwndNew, EM_SETHANDLE, (UINT)hT, 0L);
1065:
1066: ShowWindow (hwndNew, SW_SHOW);
1067:
1068: /* Set focus to the new edit control */
1069: SetFocus (hwndNew);
1070:
1071: UNREFERENCED_PARAMETER(rc);
1072: }
1073:
1074:
1075: /****************************************************************************
1076: * *
1077: * FUNCTION : MPError ( hwnd, flags, id, ...) *
1078: * *
1079: * PURPOSE : Flashes a Message Box to the user. The format string is *
1080: * taken from the STRINGTABLE. *
1081: * *
1082: * RETURNS : Returns value returned by MessageBox() to the caller. *
1083: * *
1084: ****************************************************************************/
1085: SHORT MPError(
1086: HWND hwnd,
1087: WORD bFlags,
1088: WORD id,
1089: char *psz )
1090: {
1091: CHAR sz[160];
1092: CHAR szFmt[128];
1093:
1094: LoadString (hInst, id, szFmt, sizeof (szFmt));
1095: sprintf (sz, szFmt, psz );
1096: LoadString (hInst, (WORD)IDS_APPNAME, (LPSTR)szFmt, sizeof (szFmt));
1097: return( (SHORT)MessageBox (hwnd, sz, szFmt, bFlags));
1098: UNREFERENCED_PARAMETER(hwnd);
1099: }
1100:
1101:
1102: /****************************************************************************
1103: * *
1104: * FUNCTION : QueryCloseAllChildren() *
1105: * *
1106: * PURPOSE : Asks the child windows if it is ok to close up app. Nothing*
1107: * is destroyed at this point. The z-order is not changed. *
1108: * *
1109: * RETURNS : TRUE - If all children agree to the query. *
1110: * FALSE- If any one of them disagrees. *
1111: * *
1112: ****************************************************************************/
1113:
1114: BOOL NEAR PASCAL QueryCloseAllChildren()
1115: {
1116: register HWND hwndT;
1117:
1118: for ( hwndT = GetWindow (hwndMDIClient, GW_CHILD);
1119: hwndT;
1120: hwndT = GetWindow (hwndT, GW_HWNDNEXT) ){
1121:
1122: /* Skip if an icon title window */
1123: if (GetWindow (hwndT, GW_OWNER))
1124: continue;
1125:
1126: if (SendMessage (hwndT, WM_QUERYENDSESSION, 0, 0L))
1127: return FALSE;
1128: }
1129: return TRUE;
1130: }
1131:
1132: /****************************************************************************
1133: * *
1134: * FUNCTION : QueryCloseChild (hwnd) *
1135: * *
1136: * PURPOSE : If the child MDI is unsaved, allow the user to save, not *
1137: * save, or cancel the close operation. *
1138: * *
1139: * RETURNS : TRUE - if user chooses save or not save, or if the file *
1140: * has not changed. *
1141: * FALSE - otherwise. *
1142: * *
1143: ****************************************************************************/
1144:
1145: BOOL NEAR PASCAL QueryCloseChild(register HWND hwnd)
1146: {
1147: CHAR sz [MAX_PATH];
1148: register INT i;
1149:
1150: /* Return OK if edit control has not changed. */
1151: if (!GetWindowWord (hwnd, GWW_CHANGED))
1152: return TRUE;
1153:
1154: GetWindowText (hwnd, sz, sizeof(sz));
1155:
1156: /* Ask user whether to save / not save / cancel */
1157: i = MPError (hwnd,
1158: MB_YESNOCANCEL|MB_ICONQUESTION,IDS_CLOSESAVE,
1159: (LPSTR)sz);
1160:
1161: switch (i){
1162: case IDYES:
1163: /* User wants file saved */
1164: if ( !GetWindowWord(hwnd, GWW_UNTITLED)
1165: || ChangeFile(hwnd)
1166: ) SaveFile(hwnd);
1167:
1168: break;
1169:
1170: case IDNO:
1171: /* User doesn't want file saved */
1172: break;
1173:
1174: default:
1175: /* We couldn't do the messagebox, or not ok to close */
1176: return FALSE;
1177: }
1178: return TRUE;
1179: }
1180:
1181:
1182: LPSTR GetCmdLine( VOID )
1183: {
1184: LPSTR lpCmdLine, lpT;
1185:
1186: lpCmdLine = GetCommandLine();
1187:
1188: // on Win32, lpCmdLine's first string includes its own name, remove this
1189: // to make it exactly like the windows command line.
1190:
1191: if (*lpCmdLine) {
1192: lpT = strchr(lpCmdLine, ' '); // skip self name
1193: if (lpT) {
1194: lpCmdLine = lpT;
1195: while (*lpCmdLine == ' ') {
1196: lpCmdLine++; // skip spaces to end or first cmd
1197: }
1198: } else {
1199: lpCmdLine += strlen(lpCmdLine); // point to NULL
1200: }
1201: }
1202: return(lpCmdLine);
1203: }
1204:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.