|
|
1.1 ! root 1: /* ! 2: OLE SERVER DEMO ! 3: SrvrDemo.c ! 4: ! 5: This file contains the window handlers, and various initialization and ! 6: utility functions. ! 7: ! 8: (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved ! 9: */ ! 10: ! 11: ! 12: #define SERVERONLY ! 13: #include <windows.h> ! 14: #include <ole.h> ! 15: ! 16: #include "srvrdemo.h" ! 17: ! 18: /* Global variable definitions */ ! 19: ! 20: HWND hwndMain = NULL; ! 21: ! 22: // Since this is a not an MDI app, there can be only one server and one doc. ! 23: SRVR srvrMain; ! 24: DOC docMain; ! 25: CHAR szClient[cchFilenameMax]; ! 26: CHAR szClientDoc[cchFilenameMax]; ! 27: ! 28: // Has the user made changes to the document? ! 29: BOOL fDocChanged = FALSE; ! 30: ! 31: // Is this the first instance of this application currently running? ! 32: BOOL fFirstInstance = TRUE; ! 33: ! 34: // This flag is used when OleRevokeServerDoc returns OLE_WAIT_FOR_RELEASE, ! 35: // and we must wait until DocRelease is called. ! 36: BOOL fWaitingForDocRelease = FALSE; ! 37: ! 38: // This flag is used when OleRevokeServer returns OLE_WAIT_FOR_RELEASE, ! 39: // and we must wait until SrvrRelease is called. ! 40: BOOL fWaitingForSrvrRelease = FALSE; ! 41: ! 42: // This flag is set to TRUE after an application has called OleBlockServer ! 43: // and now wishes to unblock the queued messages. See WinMain. ! 44: // Server Demo never sets fUnblock to TRUE because it never calls ! 45: // OleBlockServer. ! 46: BOOL fUnblock = FALSE; ! 47: ! 48: // Set this to FALSE if you want to guarantee that the server will not revoke ! 49: // itself when SrvrRelease is called. This is used in the IDM_NEW case and ! 50: // the IDM_OPEN case (in OpenDoc). ! 51: BOOL fRevokeSrvrOnSrvrRelease = TRUE; ! 52: ! 53: // Version number, which is stored in the native data. ! 54: VERSION version = 1; ! 55: ! 56: HBRUSH hbrColor[chbrMax]; ! 57: ! 58: // Clipboard formats ! 59: OLECLIPFORMAT cfObjectLink; ! 60: OLECLIPFORMAT cfOwnerLink; ! 61: OLECLIPFORMAT cfNative; ! 62: ! 63: // Method tables. ! 64: OLESERVERDOCVTBL docvtbl; ! 65: OLEOBJECTVTBL objvtbl; ! 66: OLESERVERVTBL srvrvtbl; ! 67: ! 68: HANDLE hInst; ! 69: HANDLE hAccelTable; ! 70: HMENU hMainMenu = NULL; ! 71: ! 72: // Window dimensions saved in private profile. ! 73: static struct ! 74: { ! 75: INT nX; ! 76: INT nY; ! 77: INT nWidth; ! 78: INT nHeight; ! 79: } dimsSaved, dimsCurrent; ! 80: ! 81: ! 82: static enum ! 83: { ! 84: // Corresponds to the order of the menus in the .rc file. ! 85: menuposFile, ! 86: menuposEdit, ! 87: menuposColor, ! 88: menuposObject ! 89: }; ! 90: ! 91: ! 92: // Static functions. ! 93: static VOID DeleteInstance (VOID); ! 94: static BOOL ExitApplication (BOOL); ! 95: static VOID GetWord (LPSTR *plpszSrc, LPSTR lpszDst); ! 96: static BOOL InitApplication( HANDLE hInstance); ! 97: static BOOL InitInstance (HANDLE hInstance); ! 98: static BOOL ProcessCmdLine (LPSTR,HWND); ! 99: static VOID SaveDimensions (VOID); ! 100: static VOID SkipBlanks (LPSTR *plpsz); ! 101: static VOID UpdateObjMenus (VOID); ! 102: static BOOL FailedUpdate(HWND); ! 103: ! 104: /* WinMain ! 105: * ------- ! 106: * ! 107: * Standard windows entry point ! 108: * ! 109: * CUSTOMIZATION: None ! 110: * ! 111: */ ! 112: int WinMain( ! 113: HANDLE hInstance, ! 114: HANDLE hPrevInstance, ! 115: LPSTR lpCmdLine, ! 116: INT nCmdShow ! 117: ){ ! 118: MSG msg; ! 119: ! 120: if (!InitApplication(hInstance)) ! 121: return FALSE; ! 122: ! 123: msg.wParam = FALSE; ! 124: ! 125: if (!InitInstance(hInstance)) ! 126: goto errRtn; ! 127: ! 128: if (!InitServer (hwndMain, hInstance)) ! 129: goto errRtn; ! 130: ! 131: if (!ProcessCmdLine(lpCmdLine,hwndMain)) ! 132: { ! 133: ExitApplication(FALSE); ! 134: goto errRtn; ! 135: } ! 136: ! 137: for (;;) ! 138: { ! 139: // Your application should set fUnblock to TRUE when it decides ! 140: // to unblock. ! 141: if (fUnblock) ! 142: { ! 143: BOOL fMoreMsgs = TRUE; ! 144: while (fMoreMsgs) ! 145: { ! 146: OleUnblockServer (srvrMain.lhsrvr, &fMoreMsgs); ! 147: } ! 148: // We have taken care of all the messages in the OLE queue ! 149: fUnblock = FALSE; ! 150: } ! 151: ! 152: if (!GetMessage(&msg, NULL, NULL, NULL)) ! 153: break; ! 154: if( !TranslateAccelerator(hwndMain, hAccelTable, &msg)) ! 155: { ! 156: TranslateMessage(&msg); ! 157: DispatchMessage(&msg); ! 158: } ! 159: } ! 160: ! 161: ! 162: errRtn: ! 163: ! 164: DeleteInstance (); ! 165: return (msg.wParam); ! 166: } ! 167: ! 168: ! 169: ! 170: /* InitApplication ! 171: * --------------- ! 172: * ! 173: * Initialize the application - register the window classes ! 174: * ! 175: * HANDLE hInstance ! 176: * ! 177: * RETURNS: TRUE if classes are properly registered. ! 178: * FALSE otherwise ! 179: * ! 180: * CUSTOMIZATION: Re-implement ! 181: * ! 182: */ ! 183: static BOOL InitApplication( HANDLE hInstance ) ! 184: { ! 185: WNDCLASS wc; ! 186: ! 187: wc.lpszClassName = "MainClass"; ! 188: wc.lpfnWndProc = (WNDPROC)MainWndProc; ! 189: wc.style = NULL; ! 190: wc.cbClsExtra = 4; ! 191: wc.cbWndExtra = 0; ! 192: wc.hInstance = hInstance; ! 193: wc.hIcon = LoadIcon(hInstance, "DocIcon"); ! 194: wc.hCursor = LoadCursor(NULL, IDC_ARROW); ! 195: wc.hbrBackground = GetStockObject(WHITE_BRUSH); ! 196: wc.lpszMenuName = "MainMenu"; ! 197: ! 198: if (!RegisterClass(&wc)) ! 199: return FALSE; ! 200: ! 201: wc.lpszClassName = "ObjClass"; ! 202: wc.lpfnWndProc = (WNDPROC)ObjWndProc; ! 203: wc.hIcon = NULL; ! 204: wc.cbWndExtra = cbWindExtra; ! 205: wc.lpszMenuName = NULL; ! 206: wc.hCursor = LoadCursor(NULL, IDC_CROSS); ! 207: ! 208: if (!RegisterClass(&wc)) ! 209: return FALSE; ! 210: ! 211: return TRUE; ! 212: } ! 213: ! 214: ! 215: ! 216: /* InitInstance ! 217: * ------------ ! 218: * ! 219: * Create brushes used by the program, the main window, and ! 220: * do any other per-instance initialization. ! 221: * ! 222: * HANDLE hInstance ! 223: * ! 224: * RETURNS: TRUE if successful ! 225: * FALSE otherwise. ! 226: * ! 227: * CUSTOMIZATION: Re-implement ! 228: * ! 229: */ ! 230: static BOOL InitInstance (HANDLE hInstance) ! 231: { ! 232: LONG rglColor [chbrMax] = ! 233: { ! 234: 0x000000ff, // Red ! 235: 0x0000ff00, // Green ! 236: 0x00ff0000, // Blue ! 237: 0x00ffffff, // White ! 238: 0x00808080, // Gray ! 239: 0x00ffff00, // Cyan ! 240: 0x00ff00ff, // Magenta ! 241: 0x0000ffff // Yellow ! 242: }; ! 243: ! 244: ! 245: INT iColor; ! 246: ! 247: hInst = hInstance; ! 248: ! 249: // Initialize the method tables. ! 250: InitVTbls (); ! 251: ! 252: // Initialize the brushes used. ! 253: for (iColor = 0; iColor < chbrMax; iColor++) ! 254: hbrColor[iColor] = CreateSolidBrush (rglColor[iColor]); ! 255: ! 256: // Register clipboard formats. ! 257: cfObjectLink= RegisterClipboardFormat ("ObjectLink"); ! 258: cfOwnerLink = RegisterClipboardFormat ("OwnerLink"); ! 259: cfNative = RegisterClipboardFormat ("Native"); ! 260: ! 261: hAccelTable = LoadAccelerators(hInst, "Accelerators"); ! 262: // hMainMenu = LoadMenu(hInst, "MainMenu"); ! 263: ! 264: ! 265: hwndMain = CreateWindow( ! 266: "MainClass", ! 267: szAppName, ! 268: WS_OVERLAPPEDWINDOW, ! 269: CW_USEDEFAULT, CW_USEDEFAULT, ! 270: 3*OBJECT_WIDTH, 3*OBJECT_HEIGHT, ! 271: NULL, ! 272: NULL, ! 273: hInstance, ! 274: NULL ! 275: ); ! 276: ! 277: ! 278: if (!hwndMain) ! 279: return FALSE; ! 280: ! 281: szClient[0] = NULL; ! 282: lstrcpy (szClientDoc, "Client Document"); ! 283: ! 284: // Initialize global variables with LOGPIXELSX and LOGPIXELSY ! 285: ! 286: return TRUE; ! 287: ! 288: } ! 289: ! 290: ! 291: ! 292: /* DeleteInstance ! 293: * -------------- ! 294: * ! 295: * Deallocate the VTables, and the brushes created for this instance ! 296: * ! 297: * ! 298: * CUSTOMIZATION: The call to FreeVTbls must remain. ! 299: * ! 300: */ ! 301: static VOID DeleteInstance (VOID) ! 302: { ! 303: INT i; ! 304: ! 305: for (i = 0; i < chbrMax; i++) ! 306: DeleteObject (hbrColor[i]); ! 307: ! 308: } ! 309: ! 310: ! 311: ! 312: /* ExitApplication ! 313: * --------------- ! 314: * ! 315: * Handles the WM_CLOSE and WM_COMMAND/IDM_EXIT messages. ! 316: * ! 317: * RETURNS: TRUE if application should really terminate ! 318: * FALSE if not ! 319: * ! 320: * ! 321: * CUSTOMIZATION: None ! 322: * ! 323: */ ! 324: static BOOL ExitApplication (BOOL fUpdateLater) ! 325: { ! 326: ! 327: if (fUpdateLater) ! 328: { ! 329: // The non-standard OLE client did not accept the update ! 330: // when we requested it, so we are sending the client ! 331: // OLE_CLOSED now that we are closing the document. ! 332: SendDocMsg (OLE_CLOSED); ! 333: } ! 334: ! 335: if (StartRevokingServer() == OLE_WAIT_FOR_RELEASE) ! 336: Wait (&fWaitingForSrvrRelease); ! 337: /* SrvrRelease will not necessarily post a WM_QUIT message. ! 338: If the document is not embedded, SrvrRelease by itself does ! 339: not cause the application to terminate. But now we want it to. ! 340: */ ! 341: if (docMain.doctype != doctypeEmbedded) ! 342: PostQuitMessage(0); ! 343: SaveDimensions(); ! 344: return TRUE; ! 345: } ! 346: ! 347: ! 348: ! 349: /* MainWndProc ! 350: * ----------- ! 351: * ! 352: * Main window message handler. ! 353: * ! 354: * ! 355: * CUSTOMIZATION: Remove the color menu and the object menu entirely. ! 356: * Add handlers for your application's menu items and any ! 357: * Windows messages your application needs to handle. ! 358: * The handlers for the menu items that involve OLE ! 359: * can be added to, but no logic should be removed. ! 360: * ! 361: * ! 362: */ ! 363: LONG APIENTRY MainWndProc ! 364: (HWND hwnd, UINT message, DWORD wParam, LONG lParam ) ! 365: { ! 366: LPOBJ lpobj; ! 367: ! 368: switch (message) ! 369: { ! 370: case WM_COMMAND: ! 371: { ! 372: WORD wID = LOWORD(wParam); ! 373: ! 374: if (fWaitingForDocRelease) ! 375: { ! 376: ErrorBox ("Waiting for a document to be revoked.\n\rPlease wait."); ! 377: return NULL; ! 378: } ! 379: ! 380: switch (wID) ! 381: { ! 382: case IDM_EXIT: ! 383: SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L); ! 384: break; ! 385: ! 386: case IDM_ABOUT: ! 387: DialogBox(hInst, "AboutBox", hwnd, (DLGPROC)About); ! 388: break; ! 389: ! 390: case IDM_NEW: ! 391: { ! 392: BOOL fUpdateLater; ! 393: OLESTATUS olestatus; ! 394: ! 395: if (SaveChangesOption (&fUpdateLater) == IDCANCEL) ! 396: break; ! 397: else if (fUpdateLater) ! 398: SendDocMsg (OLE_CLOSED); ! 399: ! 400: // We want to revoke the doc but not the server, so if ! 401: // SrvrRelease is called, do not revoke server. ! 402: fRevokeSrvrOnSrvrRelease = FALSE; ! 403: ! 404: if ((olestatus = RevokeDoc()) > OLE_WAIT_FOR_RELEASE) ! 405: { ! 406: ErrorBox ("Serious Error: Cannot revoke document."); ! 407: break; ! 408: } ! 409: else if (olestatus == OLE_WAIT_FOR_RELEASE) ! 410: Wait (&fWaitingForDocRelease); ! 411: ! 412: fRevokeSrvrOnSrvrRelease = TRUE; ! 413: ! 414: if (!CreateNewDoc (NULL, "(Untitled)", doctypeNew)) ! 415: { ! 416: ErrorBox ("Serious Error: Cannot create new document."); ! 417: break; ! 418: } ! 419: // Your application need not create a default object. ! 420: CreateNewObj (FALSE); ! 421: EmbeddingModeOff(); ! 422: break; ! 423: } ! 424: case IDM_OPEN: ! 425: OpenDoc(); ! 426: UpdateObjMenus(); ! 427: break; ! 428: ! 429: case IDM_SAVE: ! 430: SaveDoc(); ! 431: break; ! 432: ! 433: case IDM_SAVEAS: ! 434: if (!SaveDocAs ()) ! 435: break; ! 436: if (docMain.doctype != doctypeEmbedded) ! 437: EmbeddingModeOff(); ! 438: break; ! 439: ! 440: case IDM_UPDATE: ! 441: switch (OleSavedServerDoc (docMain.lhdoc)) ! 442: { ! 443: case OLE_ERROR_CANT_UPDATE_CLIENT: ! 444: if (!FailedUpdate(hwnd)) ! 445: ExitApplication(TRUE); ! 446: break; ! 447: case OLE_OK: ! 448: break; ! 449: default: ! 450: ErrorBox ("Serious Error: Cannot update."); ! 451: } ! 452: break; ! 453: ! 454: /* Color menu */ ! 455: ! 456: case IDM_RED: ! 457: case IDM_GREEN: ! 458: case IDM_BLUE: ! 459: case IDM_WHITE: ! 460: case IDM_GRAY: ! 461: case IDM_CYAN: ! 462: case IDM_MAGENTA: ! 463: case IDM_YELLOW: ! 464: lpobj = SelectedObject(); ! 465: lpobj->native.idmColor = wID; ! 466: // Recolor the object on the screen. ! 467: InvalidateRect (lpobj->hwnd, (LPRECT)NULL, TRUE); ! 468: UpdateWindow (lpobj->hwnd); ! 469: fDocChanged = TRUE; ! 470: if (docMain.doctype == doctypeFromFile) ! 471: // If object is linked, update it in client now. ! 472: SendObjMsg (lpobj, OLE_CHANGED); ! 473: break; ! 474: ! 475: /* Edit menu */ ! 476: ! 477: case IDM_COPY: ! 478: CutOrCopyObj (TRUE); ! 479: break; ! 480: ! 481: case IDM_CUT: ! 482: CutOrCopyObj (FALSE); ! 483: // Fall through. ! 484: ! 485: case IDM_DELETE: ! 486: RevokeObj (SelectedObject()); ! 487: DestroyWindow (SelectedObjectWindow()); ! 488: UpdateObjMenus(); ! 489: break; ! 490: ! 491: /* Object menu */ ! 492: ! 493: case IDM_NEXTOBJ: ! 494: lpobj = SelectedObject(); ! 495: /* The 1 in the second parameter puts the current window ! 496: at the bottom of the current window list. */ ! 497: SetWindowPos(lpobj->hwnd, (HANDLE)1, 0,0,0,0, ! 498: SWP_NOMOVE | SWP_NOSIZE); ! 499: break; ! 500: ! 501: case IDM_NEWOBJ: ! 502: lpobj = CreateNewObj (TRUE); ! 503: BringWindowToTop(lpobj->hwnd); ! 504: break; ! 505: ! 506: default: ! 507: ErrorBox ("Unknown Command."); ! 508: break; ! 509: } ! 510: break; ! 511: } ! 512: ! 513: case WM_NCCALCSIZE: ! 514: if (!IsIconic(hwnd) && !IsZoomed(hwnd)) ! 515: { ! 516: dimsCurrent.nX = ((LPRECT)lParam)->left; ! 517: dimsCurrent.nWidth = ((LPRECT)lParam)->right - dimsCurrent.nX; ! 518: dimsCurrent.nY = ((LPRECT)lParam)->top; ! 519: dimsCurrent.nHeight = ((LPRECT)lParam)->bottom - dimsCurrent.nY; ! 520: } ! 521: return DefWindowProc(hwnd, message, wParam, lParam); ! 522: break; ! 523: ! 524: case WM_QUERYENDSESSION: ! 525: { ! 526: BOOL fUpdateLater; ! 527: ! 528: if (SaveChangesOption(&fUpdateLater) == IDCANCEL) ! 529: return FALSE; ! 530: ! 531: if (fUpdateLater) ! 532: { ! 533: // The non-standard OLE client did not accept the update ! 534: // when we requested it, so we are sending the client ! 535: // OLE_CLOSED now that we are closing the document. ! 536: SendDocMsg (OLE_CLOSED); ! 537: } ! 538: return TRUE; ! 539: } ! 540: ! 541: case WM_CLOSE: ! 542: { ! 543: BOOL fUpdateLater; ! 544: ! 545: if (SaveChangesOption(&fUpdateLater) != IDCANCEL) ! 546: ExitApplication(fUpdateLater); ! 547: break; ! 548: } ! 549: ! 550: default: ! 551: return DefWindowProc(hwnd, message, wParam, lParam); ! 552: } ! 553: return NULL; ! 554: } ! 555: ! 556: ! 557: ! 558: /* About ! 559: * ----- ! 560: * ! 561: * "About Box" dialog handler. ! 562: * ! 563: * CUSTOMIZATION: None ! 564: * ! 565: */ ! 566: BOOL APIENTRY About (HWND hDlg, UINT message, DWORD wParam, LONG lParam) ! 567: { ! 568: switch (message) ! 569: { ! 570: case WM_INITDIALOG: ! 571: return TRUE; ! 572: ! 573: case WM_COMMAND: ! 574: { ! 575: WORD wID = LOWORD(wParam); ! 576: ! 577: if (wID == IDOK || wID == IDCANCEL) ! 578: { ! 579: EndDialog(hDlg, TRUE); ! 580: return TRUE; ! 581: } ! 582: break; ! 583: } ! 584: } ! 585: return FALSE; ! 586: } ! 587: ! 588: ! 589: ! 590: ! 591: /* ObjWndProc ! 592: * ---------- ! 593: * ! 594: * Message handler for the object windows. ! 595: * ! 596: * ! 597: * CUSTOMIZATION: Server Demo specific ! 598: * ! 599: */ ! 600: LONG APIENTRY ObjWndProc ! 601: (HWND hwnd, UINT message, DWORD wParam, LONG lParam) ! 602: { ! 603: static BOOL fCapture = FALSE; ! 604: static struct {RECT rect; POINT pt;} drag; ! 605: static RECT rectMain; ! 606: ! 607: switch (message) ! 608: { ! 609: case WM_CREATE: ! 610: { ! 611: LPOBJ lpobj; ! 612: LPCREATESTRUCT lpcs; ! 613: // The call to CreateWindow puts lpobj into lpCreateParams ! 614: lpcs = (LPCREATESTRUCT) lParam; ! 615: lpobj = (LPOBJ) lpcs->lpCreateParams; ! 616: // Associate the window just created with the object. ! 617: lpobj->hwnd = hwnd; ! 618: /* Store pointer to object in the window structure. */ ! 619: SetWindowLong(hwnd, ibLpobj, (LONG) lpobj); ! 620: UpdateObjMenus (); ! 621: break; ! 622: } ! 623: case WM_SIZE: ! 624: { ! 625: RECT rect; ! 626: if (fWaitingForDocRelease) ! 627: { ! 628: ErrorBox ("Waiting for a document to be revoked.\n\rPlease wait."); ! 629: return NULL; ! 630: } ! 631: // Get coordinates of object relative to main window's client area. ! 632: GetWindowRect (hwnd, (LPRECT)&rect); ! 633: ScreenToClient (hwndMain, (LPPOINT)&rect); ! 634: ScreenToClient (hwndMain, (LPPOINT)&rect.right); ! 635: SizeObj (hwnd, rect, TRUE); ! 636: // Fall through. ! 637: } ! 638: case WM_PAINT: ! 639: PaintObj (hwnd); ! 640: break; ! 641: ! 642: case WM_LBUTTONDOWN: ! 643: if (fWaitingForDocRelease) ! 644: { ! 645: ErrorBox ("Waiting for a document to be revoked.\n\rPlease wait."); ! 646: return NULL; ! 647: } ! 648: BringWindowToTop (hwnd); ! 649: ! 650: GetWindowRect (hwnd, (LPRECT) &drag.rect); ! 651: ScreenToClient (hwndMain, (LPPOINT)&drag.rect.left); ! 652: ScreenToClient (hwndMain, (LPPOINT)&drag.rect.right); ! 653: ! 654: drag.pt.x = LOWORD(lParam); ! 655: drag.pt.y = HIWORD(lParam); ! 656: ! 657: // Convert drag.pt to the main window's client coordinates. ! 658: ClientToScreen (hwnd, (LPPOINT)&drag.pt); ! 659: ScreenToClient (hwndMain, (LPPOINT)&drag.pt); ! 660: ! 661: // Remember the coordinates of the main window so we do not drag ! 662: // an object outside the main window. ! 663: GetClientRect (hwndMain, (LPRECT) &rectMain); ! 664: ! 665: SetCapture (hwnd); ! 666: fCapture = TRUE; ! 667: break; ! 668: ! 669: case WM_MOUSEMOVE: ! 670: { ! 671: HDC hdc; ! 672: POINT pt; ! 673: ! 674: if (!fCapture) ! 675: break; ! 676: ! 677: fDocChanged = TRUE; ! 678: pt.x = LOWORD(lParam); ! 679: pt.y = HIWORD(lParam); ! 680: ! 681: // Convert pt to the main window's client coordinates. ! 682: ClientToScreen (hwnd, (LPPOINT)&pt); ! 683: ScreenToClient (hwndMain, (LPPOINT)&pt); ! 684: ! 685: if (!PtInRect (&rectMain, pt)) ! 686: break; ! 687: ! 688: hdc = GetDC(hwndMain); ! 689: ! 690: // Erase old drag rectangle ! 691: InvertRect (hdc, (LPRECT)&drag.rect); ! 692: ! 693: // Update drag.rect ! 694: OffsetRect (&drag.rect, pt.x - drag.pt.x, pt.y - drag.pt.y); ! 695: ! 696: // Update drag.pt ! 697: drag.pt.x = pt.x; ! 698: drag.pt.y = pt.y; ! 699: ! 700: // Show new drag rectangle ! 701: InvertRect (hdc, (LPRECT)&drag.rect); ! 702: ReleaseDC (hwndMain, hdc); ! 703: break; ! 704: } ! 705: ! 706: case WM_LBUTTONUP: ! 707: { ! 708: LPOBJ lpobj; ! 709: if (!fCapture) ! 710: return TRUE; ! 711: ! 712: fCapture = FALSE; ! 713: ReleaseCapture (); ! 714: ! 715: MoveWindow (hwnd, drag.rect.left, drag.rect.top, ! 716: drag.rect.right - drag.rect.left, ! 717: drag.rect.bottom - drag.rect.top, TRUE); ! 718: InvalidateRect (hwnd, (LPRECT)NULL, TRUE); ! 719: lpobj = HwndToLpobj (hwnd); ! 720: lpobj->native.nX = drag.rect.left; ! 721: lpobj->native.nY = drag.rect.top; ! 722: break; ! 723: } ! 724: case WM_DESTROY: ! 725: DestroyObj (hwnd); ! 726: return DefWindowProc(hwnd, message, wParam, lParam); ! 727: ! 728: default: ! 729: return DefWindowProc(hwnd, message, wParam, lParam); ! 730: } ! 731: return NULL; ! 732: } ! 733: ! 734: ! 735: ! 736: /* DeviceToHiMetric ! 737: * ---------------- ! 738: * ! 739: * Converts a point from device units to HiMetric units. ! 740: * This function is designed to be generic enough to be reused. ! 741: * ! 742: * HWND hwnd - The window whose display context is to be used ! 743: * LPPOINT lppt - The point to be converted. ! 744: * ! 745: * CUSTOMIZATION: None ! 746: * ! 747: */ ! 748: VOID DeviceToHiMetric (HWND hwnd, LPPOINT lppt) ! 749: { ! 750: HDC hdc = GetDC(hwnd); ! 751: ! 752: SetMapMode(hdc, MM_HIMETRIC); ! 753: DPtoLP (hdc, lppt, 1); ! 754: ! 755: lppt->y *= -1; ! 756: ! 757: ReleaseDC(hwnd,hdc); ! 758: ! 759: } ! 760: ! 761: ! 762: /* UpdateFileMenu ! 763: * -------------- ! 764: * ! 765: * Updates the "Update <Client doc>" and "Exit & Return to <Client doc>" ! 766: * with the currently set client document name ! 767: * ! 768: * CUSTOMIZATION: Re-implement ! 769: * ! 770: */ ! 771: VOID UpdateFileMenu (INT iSaveUpdateId) ! 772: { ! 773: CHAR str[cchFilenameMax]; ! 774: HMENU hMenu = GetMenu(hwndMain); ! 775: ! 776: /* Change File menu so it contains "Update" instead of "Save". */ ! 777: ! 778: lstrcpy (str, "&Update "); ! 779: lstrcat (str, szClientDoc); ! 780: ModifyMenu(hMenu, iSaveUpdateId, MF_BYCOMMAND|MF_STRING, IDM_UPDATE, str); ! 781: ! 782: /* Change File menu so it contains "Exit & Return to <client doc>" */ ! 783: /* instead of just "Exit" */ ! 784: ! 785: lstrcpy (str, "E&xit && Return to "); ! 786: lstrcat (str, szClientDoc); ! 787: ModifyMenu(hMenu, IDM_EXIT, MF_BYCOMMAND|MF_STRING, IDM_EXIT, str); ! 788: } ! 789: ! 790: ! 791: ! 792: /* EmbeddingModeOn ! 793: * --------------- ! 794: * ! 795: * Do whatever is necessary for the application to start "embedding mode." ! 796: * ! 797: * CUSTOMIZATION: Re-implement ! 798: * ! 799: */ ! 800: VOID EmbeddingModeOn(VOID) ! 801: { ! 802: HMENU hMenu = GetMenu(hwndMain); ! 803: ! 804: UpdateFileMenu (IDM_SAVE); ! 805: ! 806: /* Change File menu so it contains "Save Copy As..." instead of */ ! 807: /* "Save As..." */ ! 808: ModifyMenu(hMenu, IDM_SAVEAS, MF_BYCOMMAND|MF_STRING, IDM_SAVEAS, ! 809: "Save Copy As.."); ! 810: ! 811: /* In embedded mode, the user can edit only the embedded object, not ! 812: create new ones. */ ! 813: EnableMenuItem(hMenu, menuposObject, MF_BYPOSITION | MF_GRAYED); ! 814: EnableMenuItem(hMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED); ! 815: EnableMenuItem(hMenu, IDM_DELETE, MF_BYCOMMAND | MF_GRAYED); ! 816: DrawMenuBar (hwndMain); ! 817: } ! 818: ! 819: ! 820: ! 821: ! 822: /* EmbeddingModeOff ! 823: * ---------------- ! 824: * ! 825: * Do whatever is necessary for the application to end "embedding mode." ! 826: * ! 827: * CUSTOMIZATION: Re-implement ! 828: * ! 829: */ ! 830: VOID EmbeddingModeOff (VOID) ! 831: { ! 832: HMENU hMenu = GetMenu(hwndMain); ! 833: ! 834: /* Change File menu so it contains "Save" instead of "Update". */ ! 835: ModifyMenu(hMenu, IDM_UPDATE, MF_BYCOMMAND | MF_STRING, IDM_SAVE, "&Save"); ! 836: /* Change File menu so it contains "Exit & Return to <client doc>" */ ! 837: /* instead of just "Exit" */ ! 838: ModifyMenu(hMenu, IDM_EXIT, MF_BYCOMMAND | MF_STRING, IDM_EXIT, "E&xit"); ! 839: ! 840: /* Change File menu so it contains "Save As..." instead of */ ! 841: /* "Save Copy As..." */ ! 842: ModifyMenu(hMenu, IDM_SAVEAS, MF_BYCOMMAND|MF_STRING, IDM_SAVEAS, ! 843: "Save As.."); ! 844: ! 845: /* In non-embedded mode, the user can create new objects. */ ! 846: EnableMenuItem(hMenu, menuposObject, MF_BYPOSITION | MF_ENABLED); ! 847: ! 848: lstrcpy (szClientDoc, "Client Document"); ! 849: DrawMenuBar (hwndMain); ! 850: } ! 851: ! 852: ! 853: ! 854: /* ErrorBox ! 855: * -------- ! 856: * ! 857: * char *szMessage - String to display inside message box. ! 858: * ! 859: * CUSTOMIZATION: Server Demo specific ! 860: * ! 861: */ ! 862: VOID ErrorBox (CHAR *szMessage) ! 863: { ! 864: MessageBox (hwndMain, szMessage, szAppName, MB_OK); ! 865: } ! 866: ! 867: ! 868: ! 869: /* GetWord ! 870: * ------- ! 871: * ! 872: * LPSTR *plpszSrc - Pointer to a pointer to a source string ! 873: * LPSTR lpszDst - Pointer to destination buffer ! 874: * ! 875: * Will copy one space-terminated or null-terminated word from the source ! 876: * string to the destination buffer. ! 877: * When done, *plpszSrc will point to the character after the word. ! 878: * ! 879: * CUSTOMIZATION: Server Demo specific ! 880: * ! 881: */ ! 882: static VOID GetWord (LPSTR *plpszSrc, LPSTR lpszDst) ! 883: { ! 884: INT i = 0; ! 885: while (**plpszSrc && **plpszSrc != ' ') ! 886: { ! 887: lpszDst[i++] = *(*plpszSrc)++; ! 888: } ! 889: lpszDst[i] = '\0'; ! 890: } ! 891: ! 892: ! 893: ! 894: /* HiMetricToDevice ! 895: * ---------------- ! 896: * ! 897: * Converts a point from HiMetric units to device units. ! 898: * This function is designed to be generic enough to be reused. ! 899: * ! 900: * HWND hwnd - The window whose display context is to be used ! 901: * LPPOINT lppt - The point to be converted. ! 902: * ! 903: * CUSTOMIZATION: None ! 904: * ! 905: */ ! 906: VOID HiMetricToDevice (HWND hwnd, LPPOINT lppt) ! 907: { ! 908: HDC hdc = GetDC(hwnd); ! 909: ! 910: SetMapMode(hdc, MM_HIMETRIC); ! 911: ! 912: LPtoDP (hdc, lppt, 1); ! 913: ! 914: ReleaseDC(hwnd,hdc); ! 915: } ! 916: ! 917: ! 918: ! 919: /* HwndToLpobj ! 920: * ----------- ! 921: * ! 922: * Given an object's window, return a pointer to the object. ! 923: * The GetWindowLong call extracts an LPOBJ from the extra data stored with ! 924: * the window. ! 925: * ! 926: * HWND hwndObj - Handle to the object's window ! 927: * ! 928: * RETURNS: A pointer to the object ! 929: * ! 930: * CUSTOMIZATION: Server Demo specific ! 931: * ! 932: */ ! 933: LPOBJ HwndToLpobj (HWND hwndObj) ! 934: { ! 935: return (LPOBJ) GetWindowLong (hwndObj, ibLpobj); ! 936: } ! 937: ! 938: ! 939: ! 940: /* CreateUntitledDoc ! 941: * ----------------- ! 942: * ! 943: * Create a fresh document with one object. ! 944: * ! 945: * RETURNS: TRUE if successful ! 946: * FALSE otherwise ! 947: * ! 948: * CUSTOMIZATION: Re-implement ! 949: * ! 950: */ ! 951: static BOOL CreateUntitledDoc (INT nCmdShow) ! 952: { ! 953: if (!CreateNewDoc (NULL, "(Untitled)", doctypeNew)) ! 954: return FALSE; ! 955: CreateNewObj (FALSE); ! 956: ShowWindow(hwndMain, nCmdShow); ! 957: UpdateWindow(hwndMain); ! 958: return TRUE; ! 959: } ! 960: ! 961: ! 962: /* ProcessCmdLine ! 963: * -------------- ! 964: * ! 965: * Parses the Windows command line which was passed to WinMain. ! 966: * ! 967: * Case One: SrvrDemo.exe ! 968: * fEmbedding = FALSE ! 969: * Create an untitled document. ! 970: * ! 971: * Case two: SrvrDemo.exe filename ! 972: * fEmbedding = FALSE ! 973: * Create a new document from the file. ! 974: * ! 975: * Case three: SrvrDemo.exe -Embedding ! 976: * fEmbedding = TRUE ! 977: * Do not create or register a document. ! 978: * Do not show window until client requests it. ! 979: * ! 980: * Case four: SrvrDemo.exe -Embedding filename ! 981: * fEmbedding = TRUE ! 982: * Load file. ! 983: * Call OleRegisterServerDoc. ! 984: * Do not show window until client requests it. ! 985: * ! 986: * ! 987: * LPSTR lpszLine - The Windows command line ! 988: * int nCmdShow - Parameter to WinMain ! 989: * HWND hwndMain - The application's main window ! 990: * ! 991: * RETURNS: TRUE if the command line was processed correctly. ! 992: * FALSE if a filename was specified which did not ! 993: * contain a proper document. ! 994: * ! 995: * CUSTOMIZATION: None. ! 996: * ! 997: */ ! 998: ! 999: static BOOL ProcessCmdLine (LPSTR lpszLine, HWND hwndMain) ! 1000: { ! 1001: CHAR szBuf[cchFilenameMax]; ! 1002: BOOL fEmbedding = FALSE; // Is "-Embedding" on the command line? ! 1003: INT i=0; ! 1004: OFSTRUCT of; ! 1005: ! 1006: if (!*lpszLine) // No filename or options, so start a fresh document. ! 1007: { ! 1008: return CreateUntitledDoc(SW_SHOWNORMAL); ! 1009: } ! 1010: ! 1011: SkipBlanks (&lpszLine); ! 1012: ! 1013: // Check for "-Embedding" or "/Embedding" and set fEmbedding. ! 1014: if(*lpszLine == '-' || *lpszLine == '/') ! 1015: { ! 1016: lpszLine++; ! 1017: GetWord (&lpszLine, szBuf); ! 1018: fEmbedding = !lstrcmp(szBuf, szEmbeddingFlag); ! 1019: } ! 1020: ! 1021: SkipBlanks (&lpszLine); ! 1022: ! 1023: if (*lpszLine) // if there is a filename ! 1024: { ! 1025: // Put filename into szBuf. ! 1026: GetWord (&lpszLine, szBuf); ! 1027: ! 1028: if (-1 == OpenFile(szBuf, &of, OF_READ | OF_EXIST)) ! 1029: { ! 1030: // File not found ! 1031: if (fEmbedding) ! 1032: return FALSE; ! 1033: else ! 1034: { ! 1035: CHAR sz[100]; ! 1036: wsprintf (sz, "File %s not found.", (LPSTR) szBuf); ! 1037: ErrorBox (sz); ! 1038: return CreateUntitledDoc(SW_SHOWNORMAL); ! 1039: } ! 1040: } ! 1041: ! 1042: if (!CreateDocFromFile (szBuf, NULL, doctypeFromFile)) ! 1043: { ! 1044: // File not in proper format. ! 1045: if (fEmbedding) ! 1046: return FALSE; ! 1047: else ! 1048: { ! 1049: CHAR sz[100]; ! 1050: wsprintf (sz, "File %s not in proper format.", (LPSTR) szBuf); ! 1051: ErrorBox (sz); ! 1052: return CreateUntitledDoc(SW_SHOWNORMAL); ! 1053: } ! 1054: } ! 1055: } ! 1056: ! 1057: if (fEmbedding) ! 1058: { ! 1059: /* Do not show window until told to do so by client. */ ! 1060: ShowWindow(hwndMain, SW_HIDE); ! 1061: } ! 1062: else ! 1063: { ! 1064: ShowWindow(hwndMain, SW_SHOWNORMAL); ! 1065: UpdateWindow(hwndMain); ! 1066: } ! 1067: return TRUE; ! 1068: } ! 1069: ! 1070: ! 1071: ! 1072: /* SaveDimensions ! 1073: * -------------- ! 1074: * ! 1075: * Save the dimensions of the main window in a private profile file. ! 1076: * ! 1077: * CUSTOMIZATION: This function may be removed. If you wish to support ! 1078: * intelligent window placement, then the only necessary ! 1079: * change is to change the string "SrvrDemo.Ini" to a filename ! 1080: * appropriate for your application. ! 1081: */ ! 1082: static VOID SaveDimensions (VOID) ! 1083: { ! 1084: if ((dimsCurrent.nX != dimsSaved.nX) || ! 1085: (dimsCurrent.nY != dimsSaved.nY) || ! 1086: (dimsCurrent.nWidth != dimsSaved.nWidth) || ! 1087: (dimsCurrent.nHeight != dimsSaved.nHeight) ) ! 1088: { ! 1089: // Save current window dimensions to private profile. ! 1090: CHAR szBuf[7]; ! 1091: wsprintf (szBuf, "%d", dimsCurrent.nX); ! 1092: WritePrivateProfileString ! 1093: (szAppName, "x", szBuf, "SrvrDemo.Ini"); ! 1094: wsprintf (szBuf, "%d", dimsCurrent.nY); ! 1095: WritePrivateProfileString ! 1096: (szAppName, "y", szBuf, "SrvrDemo.Ini"); ! 1097: wsprintf (szBuf, "%d", dimsCurrent.nWidth); ! 1098: WritePrivateProfileString ! 1099: (szAppName, "w", szBuf, "SrvrDemo.Ini"); ! 1100: wsprintf (szBuf, "%d", dimsCurrent.nHeight); ! 1101: WritePrivateProfileString ! 1102: (szAppName, "h", szBuf, "SrvrDemo.Ini"); ! 1103: } ! 1104: } ! 1105: ! 1106: ! 1107: ! 1108: /* SelectedObject ! 1109: * -------------- ! 1110: * ! 1111: * Return a pointer to the currently selected object. ! 1112: * ! 1113: * CUSTOMIZATION: What a "selected object" is will vary from application ! 1114: * to application. You may find it useful to have a function ! 1115: * like this. In your application it may be necessary to ! 1116: * actually create an OBJ structure based on what data the ! 1117: * user has selected from the document (by highlighting some ! 1118: * text for example). ! 1119: * ! 1120: */ ! 1121: LPOBJ SelectedObject (VOID) ! 1122: { ! 1123: return HwndToLpobj (SelectedObjectWindow()); ! 1124: } ! 1125: ! 1126: ! 1127: ! 1128: ! 1129: /* SelectedObjectWindow ! 1130: * -------------------- ! 1131: * ! 1132: * Return a handle to the window for the currently selected object. ! 1133: * The GetWindow calls returns a handle to the main window's first child, ! 1134: * which is the selected object's window. ! 1135: * ! 1136: * CUSTOMIZATION: Server Demo specific ! 1137: * ! 1138: */ ! 1139: HWND SelectedObjectWindow (VOID) ! 1140: { ! 1141: return GetWindow (hwndMain, GW_CHILD); ! 1142: } ! 1143: ! 1144: ! 1145: ! 1146: /* SetHiMetricFields ! 1147: * ----------------- ! 1148: * ! 1149: * Adjust the nHiMetricWidth and nHiMetricHeight fields of a NATIVE structure ! 1150: * so that they are equivalent to the nWidth and nHeight fields. ! 1151: * The negative sign in the last line is necessary because the positive ! 1152: * y direction is toward the top of the screen in MM_HIMETRIC mode. ! 1153: * ! 1154: * LPOBJ lpobj - Pointer to the object whose native data will be adjusted ! 1155: * ! 1156: * CUSTOMIZATION: Server Demo specific, although you may need a function like ! 1157: * this if you keep track of the size of an object, and an ! 1158: * object handler needs to know the object's size in ! 1159: * HiMetric units. ! 1160: * ! 1161: * ! 1162: */ ! 1163: VOID SetHiMetricFields (LPOBJ lpobj) ! 1164: { ! 1165: POINT pt; ! 1166: ! 1167: pt.x = lpobj->native.nWidth; ! 1168: pt.y = lpobj->native.nHeight; ! 1169: DeviceToHiMetric (hwndMain, &pt); ! 1170: lpobj->native.nHiMetricWidth = pt.x; ! 1171: lpobj->native.nHiMetricHeight = pt.y; ! 1172: } ! 1173: ! 1174: ! 1175: ! 1176: /* SkipBlanks ! 1177: * ---------- ! 1178: * ! 1179: * LPSTR *plpsz - Pointer to a pointer to a character ! 1180: * ! 1181: * Increment *plpsz past any blanks in the character string. ! 1182: * This function is used in ProcessCmdLine. ! 1183: * ! 1184: */ ! 1185: static VOID SkipBlanks (LPSTR *plpsz) ! 1186: { ! 1187: while (**plpsz && **plpsz == ' ') ! 1188: (*plpsz)++; ! 1189: } ! 1190: ! 1191: ! 1192: ! 1193: /* UpdateObjMenus ! 1194: * --------------- ! 1195: * ! 1196: * Grey or Ungrey menu items depending on the existence of at least one ! 1197: * object in the document. ! 1198: * ! 1199: * CUSTOMIZATION: Server Demo specific ! 1200: * ! 1201: */ ! 1202: static VOID UpdateObjMenus (VOID) ! 1203: { ! 1204: static BOOL fObjMenusEnabled = TRUE; ! 1205: BOOL fOneObjExists; // Does at least one object exist? ! 1206: WORD wEnable; ! 1207: HMENU hMenu; ! 1208: ! 1209: fOneObjExists = (SelectedObjectWindow() != NULL); ! 1210: if (fOneObjExists == fObjMenusEnabled) ! 1211: { ! 1212: // Nothing has changed. ! 1213: return; ! 1214: } ! 1215: ! 1216: wEnable = (WORD)(fOneObjExists ? MF_ENABLED : MF_GRAYED); ! 1217: ! 1218: hMenu = GetMenu(hwndMain); ! 1219: EnableMenuItem(hMenu, menuposColor, MF_BYPOSITION | wEnable); ! 1220: ! 1221: hMenu = GetSubMenu(GetMenu(hwndMain), menuposFile); ! 1222: EnableMenuItem(hMenu, IDM_SAVE, MF_BYCOMMAND | wEnable); ! 1223: EnableMenuItem(hMenu, IDM_SAVEAS, MF_BYCOMMAND | wEnable); ! 1224: ! 1225: hMenu = GetSubMenu(GetMenu(hwndMain), menuposEdit); ! 1226: EnableMenuItem(hMenu, IDM_CUT, MF_BYCOMMAND | wEnable); ! 1227: EnableMenuItem(hMenu, IDM_COPY, MF_BYCOMMAND | wEnable); ! 1228: EnableMenuItem(hMenu, IDM_DELETE, MF_BYCOMMAND | wEnable); ! 1229: ! 1230: hMenu = GetSubMenu(GetMenu(hwndMain), menuposObject); ! 1231: EnableMenuItem(hMenu, IDM_NEXTOBJ, MF_BYCOMMAND | wEnable); ! 1232: ! 1233: DrawMenuBar (hwndMain); ! 1234: fObjMenusEnabled = fOneObjExists; ! 1235: } ! 1236: ! 1237: ! 1238: ! 1239: /* Wait ! 1240: * ---- ! 1241: * ! 1242: * Dispatch messages until the given flag is set to FALSE. ! 1243: * One use of this function is to wait until a Release method is called ! 1244: * after a function has returned OLE_WAIT_FOR_RELEASE. ! 1245: * ! 1246: * BOOL *pf - Pointer to the flag being waited on. ! 1247: * ! 1248: * CUSTOMIZATION: The use of OleUnblockServer is for illustration only. ! 1249: * Since Server Demo does not call OleBlockServer, there ! 1250: * will never be any messages in the OLE queue. ! 1251: * ! 1252: */ ! 1253: VOID Wait (BOOL *pf) ! 1254: { ! 1255: MSG msg; ! 1256: BOOL fMoreMsgs = FALSE; ! 1257: ! 1258: *pf = TRUE; ! 1259: while (*pf==TRUE) ! 1260: { ! 1261: OleUnblockServer (srvrMain.lhsrvr, &fMoreMsgs); ! 1262: if (!fMoreMsgs) ! 1263: // if there are no more messages in the OLE queue, go to system queue ! 1264: { ! 1265: if (GetMessage (&msg, NULL, NULL, NULL)) ! 1266: { ! 1267: TranslateMessage (&msg); ! 1268: DispatchMessage (&msg); ! 1269: } ! 1270: } ! 1271: } ! 1272: } ! 1273: ! 1274: static BOOL FailedUpdate(HWND hwnd) ! 1275: { ! 1276: ! 1277: return(DialogBox(hInst, "FailedUpdate", hwnd, (DLGPROC)fnFailedUpdate)); ! 1278: ! 1279: } ! 1280: ! 1281: BOOL APIENTRY fnFailedUpdate (HWND hDlg, UINT message, DWORD wParam, LONG lParam) ! 1282: { ! 1283: ! 1284: switch (message) ! 1285: { ! 1286: case WM_COMMAND: ! 1287: { ! 1288: WORD wID = LOWORD(wParam); ! 1289: ! 1290: switch (wID) ! 1291: { ! 1292: case IDCANCEL: ! 1293: case IDD_CONTINUEEDIT: ! 1294: EndDialog(hDlg, TRUE); ! 1295: break; ! 1296: ! 1297: case IDD_UPDATEEXIT: ! 1298: EndDialog(hDlg, FALSE); ! 1299: break; ! 1300: ! 1301: default: ! 1302: break; ! 1303: } ! 1304: break; ! 1305: } ! 1306: ! 1307: case WM_INITDIALOG: ! 1308: { ! 1309: CHAR szMsg[200]; ! 1310: ! 1311: szMsg[0] = NULL; ! 1312: ! 1313: wsprintf( ! 1314: szMsg, ! 1315: "This %s document can only be updated when you exit %s.", ! 1316: (LPSTR) szClient, ! 1317: (LPSTR) szAppName ! 1318: ); ! 1319: ! 1320: SetDlgItemText(hDlg, IDD_TEXT, szMsg); ! 1321: return TRUE; ! 1322: } ! 1323: ! 1324: default: ! 1325: break; ! 1326: } ! 1327: ! 1328: return FALSE; ! 1329: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.