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