Annotation of mstools/samples/ole/srvrdemo/srvrdemo.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.