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