|
|
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.