windows-nt/Source/XPSP1/NT/com/winole/samples/srvrdemo/srvrdemo.c
2020-09-26 16:20:57 +08:00

1336 lines
33 KiB
C

/*
OLE SERVER DEMO
SrvrDemo.c
This file contains the window handlers, and various initialization and
utility functions.
(c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
*/
#define SERVERONLY
#include <windows.h>
#include <ole.h>
#include "srvrdemo.h"
/* Global variable definitions */
HWND hwndMain = 0;
// Used in converting units from pixels to Himetric and vice-versa
int giXppli = 0; // pixels per logical inch along width
int giYppli = 0; // pixels per logical inch along height
// Since this is a not an MDI app, there can be only one server and one doc.
SRVR srvrMain;
DOC docMain;
CHAR szClient[cchFilenameMax];
CHAR szClientDoc[cchFilenameMax];
// Has the user made changes to the document?
BOOL fDocChanged = FALSE;
// Is this the first instance of this application currently running?
BOOL fFirstInstance = TRUE;
// This flag is used when OleRevokeServerDoc returns OLE_WAIT_FOR_RELEASE,
// and we must wait until DocRelease is called.
BOOL fWaitingForDocRelease = FALSE;
// This flag is used when OleRevokeServer returns OLE_WAIT_FOR_RELEASE,
// and we must wait until SrvrRelease is called.
BOOL fWaitingForSrvrRelease = FALSE;
// This flag is set to TRUE after an application has called OleBlockServer
// and now wishes to unblock the queued messages. See WinMain.
// Server Demo never sets fUnblock to TRUE because it never calls
// OleBlockServer.
BOOL fUnblock = FALSE;
// Set this to FALSE if you want to guarantee that the server will not revoke
// itself when SrvrRelease is called. This is used in the IDM_NEW case and
// the IDM_OPEN case (in OpenDoc).
BOOL fRevokeSrvrOnSrvrRelease = TRUE;
// Version number, which is stored in the native data.
VERSION version = 1;
HBRUSH hbrColor[chbrMax];
// Clipboard formats
OLECLIPFORMAT cfObjectLink;
OLECLIPFORMAT cfOwnerLink;
OLECLIPFORMAT cfNative;
// Method tables.
OLESERVERDOCVTBL docvtbl;
OLEOBJECTVTBL objvtbl;
OLESERVERVTBL srvrvtbl;
HANDLE hInst;
HANDLE hAccelTable;
HMENU hMainMenu = NULL;
// Window dimensions saved in private profile.
static struct
{
INT nX;
INT nY;
INT nWidth;
INT nHeight;
} dimsSaved, dimsCurrent;
static enum
{
// Corresponds to the order of the menus in the .rc file.
menuposFile,
menuposEdit,
menuposColor,
menuposObject
};
// Static functions.
static VOID DeleteInstance (VOID);
static BOOL ExitApplication (BOOL);
static VOID GetWord (LPSTR *plpszSrc, LPSTR lpszDst);
static BOOL InitApplication( HANDLE hInstance);
static BOOL InitInstance (HANDLE hInstance);
static BOOL ProcessCmdLine (LPSTR,HWND);
static VOID SaveDimensions (VOID);
static VOID SkipBlanks (LPSTR *plpsz);
static VOID UpdateObjMenus (VOID);
static BOOL FailedUpdate(HWND);
/* WinMain
* -------
*
* Standard windows entry point
*
* CUSTOMIZATION: None
*
*/
int APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
INT nCmdShow
){
MSG msg;
if (!InitApplication(hInstance))
return FALSE;
msg.wParam = FALSE;
if (!InitInstance(hInstance))
goto errRtn;
if (!InitServer (hwndMain, hInstance))
goto errRtn;
if (!ProcessCmdLine(lpCmdLine,hwndMain))
{
ExitApplication(FALSE);
goto errRtn;
}
for (;;)
{
// Your application should set fUnblock to TRUE when it decides
// to unblock.
if (fUnblock)
{
BOOL fMoreMsgs = TRUE;
while (fMoreMsgs)
{
if (srvrMain.lhsrvr == 0)
OleUnblockServer (srvrMain.lhsrvr, &fMoreMsgs);
}
// We have taken care of all the messages in the OLE queue
fUnblock = FALSE;
}
if (!GetMessage(&msg, NULL, 0, 0))
break;
if( !TranslateAccelerator(hwndMain, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
errRtn:
DeleteInstance ();
return (msg.wParam);
}
/* InitApplication
* ---------------
*
* Initialize the application - register the window classes
*
* HANDLE hInstance
*
* RETURNS: TRUE if classes are properly registered.
* FALSE otherwise
*
* CUSTOMIZATION: Re-implement
*
*/
static BOOL InitApplication( HANDLE hInstance )
{
WNDCLASS wc;
wc.lpszClassName = "MainClass";
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.style = 0;
wc.cbClsExtra = 4;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, "DocIcon");
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = "MainMenu";
if (!RegisterClass(&wc))
return FALSE;
wc.lpszClassName = "ObjClass";
wc.lpfnWndProc = (WNDPROC)ObjWndProc;
wc.hIcon = NULL;
wc.cbWndExtra = cbWindExtra;
wc.lpszMenuName = NULL;
wc.hCursor = LoadCursor(NULL, IDC_CROSS);
if (!RegisterClass(&wc))
return FALSE;
return TRUE;
}
/* InitInstance
* ------------
*
* Create brushes used by the program, the main window, and
* do any other per-instance initialization.
*
* HANDLE hInstance
*
* RETURNS: TRUE if successful
* FALSE otherwise.
*
* CUSTOMIZATION: Re-implement
*
*/
static BOOL InitInstance (HANDLE hInstance)
{
LONG rglColor [chbrMax] =
{
0x000000ff, // Red
0x0000ff00, // Green
0x00ff0000, // Blue
0x00ffffff, // White
0x00808080, // Gray
0x00ffff00, // Cyan
0x00ff00ff, // Magenta
0x0000ffff // Yellow
};
INT iColor;
HDC hDC ;
hInst = hInstance;
// Initialize the method tables.
InitVTbls ();
// Initialize the brushes used.
for (iColor = 0; iColor < chbrMax; iColor++)
hbrColor[iColor] = CreateSolidBrush (rglColor[iColor]);
// Register clipboard formats.
cfObjectLink= (OLECLIPFORMAT)RegisterClipboardFormat ("ObjectLink");
cfOwnerLink = (OLECLIPFORMAT)RegisterClipboardFormat ("OwnerLink");
cfNative = (OLECLIPFORMAT)RegisterClipboardFormat ("Native");
hAccelTable = LoadAccelerators(hInst, "Accelerators");
// hMainMenu = LoadMenu(hInst, "MainMenu");
hwndMain = CreateWindow(
"MainClass",
szAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
3*OBJECT_WIDTH, 3*OBJECT_HEIGHT,
NULL,
NULL,
hInstance,
NULL
);
if (!hwndMain)
return FALSE;
szClient[0] = '\0';
lstrcpy (szClientDoc, "Client Document");
// Initialize global variables with LOGPIXELSX and LOGPIXELSY
hDC = GetDC (NULL); // Get the hDC of the desktop window
giXppli = GetDeviceCaps (hDC, LOGPIXELSX);
giYppli = GetDeviceCaps (hDC, LOGPIXELSY);
ReleaseDC (NULL, hDC);
return TRUE;
}
/* DeleteInstance
* --------------
*
* Deallocate the VTables, and the brushes created for this instance
*
*
* CUSTOMIZATION: The call to FreeVTbls must remain.
*
*/
static VOID DeleteInstance (VOID)
{
INT i;
for (i = 0; i < chbrMax; i++)
DeleteObject (hbrColor[i]);
}
/* ExitApplication
* ---------------
*
* Handles the WM_CLOSE and WM_COMMAND/IDM_EXIT messages.
*
* RETURNS: TRUE if application should really terminate
* FALSE if not
*
*
* CUSTOMIZATION: None
*
*/
static BOOL ExitApplication (BOOL fUpdateLater)
{
if (fUpdateLater)
{
// The non-standard OLE client did not accept the update
// when we requested it, so we are sending the client
// OLE_CLOSED now that we are closing the document.
SendDocMsg (OLE_CLOSED);
}
if (StartRevokingServer() == OLE_WAIT_FOR_RELEASE)
Wait (&fWaitingForSrvrRelease);
/* SrvrRelease will not necessarily post a WM_QUIT message.
If the document is not embedded, SrvrRelease by itself does
not cause the application to terminate. But now we want it to.
*/
if (docMain.doctype != doctypeEmbedded)
PostQuitMessage(0);
SaveDimensions();
return TRUE;
}
/* MainWndProc
* -----------
*
* Main window message handler.
*
*
* CUSTOMIZATION: Remove the color menu and the object menu entirely.
* Add handlers for your application's menu items and any
* Windows messages your application needs to handle.
* The handlers for the menu items that involve OLE
* can be added to, but no logic should be removed.
*
*
*/
LONG APIENTRY MainWndProc
(HWND hwnd, UINT message, WPARAM wParam, LONG lParam )
{
LPOBJ lpobj;
switch (message)
{
case WM_COMMAND:
{
WORD wID = LOWORD(wParam);
if (fWaitingForDocRelease)
{
ErrorBox ("Waiting for a document to be revoked.\n\rPlease wait.");
return 0;
}
switch (wID)
{
case IDM_EXIT:
SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L);
break;
case IDM_ABOUT:
DialogBox(hInst, "AboutBox", hwnd, (DLGPROC)About);
break;
case IDM_NEW:
{
BOOL fUpdateLater;
OLESTATUS olestatus;
if (SaveChangesOption (&fUpdateLater) == IDCANCEL)
break;
else if (fUpdateLater)
SendDocMsg (OLE_CLOSED);
// We want to revoke the doc but not the server, so if
// SrvrRelease is called, do not revoke server.
fRevokeSrvrOnSrvrRelease = FALSE;
if ((olestatus = RevokeDoc()) > OLE_WAIT_FOR_RELEASE)
{
ErrorBox ("Serious Error: Cannot revoke document.");
break;
}
else if (olestatus == OLE_WAIT_FOR_RELEASE)
Wait (&fWaitingForDocRelease);
fRevokeSrvrOnSrvrRelease = TRUE;
if (!CreateNewDoc (0, "(Untitled)", doctypeNew))
{
ErrorBox ("Serious Error: Cannot create new document.");
break;
}
// Your application need not create a default object.
CreateNewObj (FALSE);
EmbeddingModeOff();
break;
}
case IDM_OPEN:
OpenDoc();
UpdateObjMenus();
break;
case IDM_SAVE:
SaveDoc();
break;
case IDM_SAVEAS:
if (!SaveDocAs ())
break;
if (docMain.doctype != doctypeEmbedded)
EmbeddingModeOff();
break;
case IDM_UPDATE:
switch (OleSavedServerDoc (docMain.lhdoc))
{
case OLE_ERROR_CANT_UPDATE_CLIENT:
if (!FailedUpdate(hwnd))
ExitApplication(TRUE);
break;
case OLE_OK:
break;
default:
ErrorBox ("Serious Error: Cannot update.");
}
break;
/* Color menu */
case IDM_RED:
case IDM_GREEN:
case IDM_BLUE:
case IDM_WHITE:
case IDM_GRAY:
case IDM_CYAN:
case IDM_MAGENTA:
case IDM_YELLOW:
lpobj = SelectedObject();
lpobj->native.idmColor = wID;
// Recolor the object on the screen.
InvalidateRect (lpobj->hwnd, (LPRECT)NULL, TRUE);
UpdateWindow (lpobj->hwnd);
fDocChanged = TRUE;
if (docMain.doctype == doctypeFromFile)
// If object is linked, update it in client now.
SendObjMsg (lpobj, OLE_CHANGED);
break;
/* Edit menu */
case IDM_COPY:
CutOrCopyObj (TRUE);
break;
case IDM_CUT:
CutOrCopyObj (FALSE);
// Fall through.
case IDM_DELETE:
RevokeObj (SelectedObject());
DestroyWindow (SelectedObjectWindow());
UpdateObjMenus();
break;
/* Object menu */
case IDM_NEXTOBJ:
lpobj = SelectedObject();
/* The 1 in the second parameter puts the current window
at the bottom of the current window list. */
SetWindowPos(lpobj->hwnd, (HANDLE)1, 0,0,0,0,
SWP_NOMOVE | SWP_NOSIZE);
break;
case IDM_NEWOBJ:
lpobj = CreateNewObj (TRUE);
BringWindowToTop(lpobj->hwnd);
break;
default:
ErrorBox ("Unknown Command.");
break;
}
break;
}
case WM_NCCALCSIZE:
if (!IsIconic(hwnd) && !IsZoomed(hwnd))
{
dimsCurrent.nX = ((LPRECT)lParam)->left;
dimsCurrent.nWidth = ((LPRECT)lParam)->right - dimsCurrent.nX;
dimsCurrent.nY = ((LPRECT)lParam)->top;
dimsCurrent.nHeight = ((LPRECT)lParam)->bottom - dimsCurrent.nY;
}
return DefWindowProc(hwnd, message, wParam, lParam);
break;
case WM_QUERYENDSESSION:
{
BOOL fUpdateLater;
if (SaveChangesOption(&fUpdateLater) == IDCANCEL)
return FALSE;
if (fUpdateLater)
{
// The non-standard OLE client did not accept the update
// when we requested it, so we are sending the client
// OLE_CLOSED now that we are closing the document.
SendDocMsg (OLE_CLOSED);
}
return TRUE;
}
case WM_CLOSE:
{
BOOL fUpdateLater;
if (SaveChangesOption(&fUpdateLater) != IDCANCEL)
ExitApplication(fUpdateLater);
break;
}
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
/* About
* -----
*
* "About Box" dialog handler.
*
* CUSTOMIZATION: None
*
*/
BOOL APIENTRY About (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
return TRUE;
case WM_COMMAND:
{
WORD wID = LOWORD(wParam);
if (wID == IDOK || wID == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return TRUE;
}
break;
}
}
return FALSE;
}
/* ObjWndProc
* ----------
*
* Message handler for the object windows.
*
*
* CUSTOMIZATION: Server Demo specific
*
*/
LONG APIENTRY ObjWndProc
(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL fCapture = FALSE;
static struct {RECT rect; POINT pt;} drag;
static RECT rectMain;
switch (message)
{
case WM_CREATE:
{
LPOBJ lpobj;
LPCREATESTRUCT lpcs;
// The call to CreateWindow puts lpobj into lpCreateParams
lpcs = (LPCREATESTRUCT) lParam;
lpobj = (LPOBJ) lpcs->lpCreateParams;
// Associate the window just created with the object.
lpobj->hwnd = hwnd;
/* Store pointer to object in the window structure. */
SetWindowLong(hwnd, ibLpobj, (LONG) lpobj);
UpdateObjMenus ();
break;
}
case WM_SIZE:
{
RECT rect;
if (fWaitingForDocRelease)
{
ErrorBox ("Waiting for a document to be revoked.\n\rPlease wait.");
return 0;
}
// Get coordinates of object relative to main window's client area.
GetWindowRect (hwnd, (LPRECT)&rect);
ScreenToClient (hwndMain, (LPPOINT)&rect);
ScreenToClient (hwndMain, (LPPOINT)&rect.right);
SizeObj (hwnd, rect, TRUE);
// Fall through.
}
case WM_PAINT:
PaintObj (hwnd);
break;
case WM_LBUTTONDOWN:
if (fWaitingForDocRelease)
{
ErrorBox ("Waiting for a document to be revoked.\n\rPlease wait.");
return 0;
}
BringWindowToTop (hwnd);
GetWindowRect (hwnd, (LPRECT) &drag.rect);
ScreenToClient (hwndMain, (LPPOINT)&drag.rect.left);
ScreenToClient (hwndMain, (LPPOINT)&drag.rect.right);
drag.pt.x = LOWORD(lParam);
drag.pt.y = HIWORD(lParam);
// Convert drag.pt to the main window's client coordinates.
ClientToScreen (hwnd, (LPPOINT)&drag.pt);
ScreenToClient (hwndMain, (LPPOINT)&drag.pt);
// Remember the coordinates of the main window so we do not drag
// an object outside the main window.
GetClientRect (hwndMain, (LPRECT) &rectMain);
SetCapture (hwnd);
fCapture = TRUE;
break;
case WM_MOUSEMOVE:
{
HDC hdc;
POINT pt;
if (!fCapture)
break;
fDocChanged = TRUE;
pt.x = LOWORD(lParam);
pt.y = HIWORD(lParam);
// Convert pt to the main window's client coordinates.
ClientToScreen (hwnd, (LPPOINT)&pt);
ScreenToClient (hwndMain, (LPPOINT)&pt);
if (!PtInRect (&rectMain, pt))
break;
hdc = GetDC(hwndMain);
// Erase old drag rectangle
InvertRect (hdc, (LPRECT)&drag.rect);
// Update drag.rect
OffsetRect (&drag.rect, pt.x - drag.pt.x, pt.y - drag.pt.y);
// Update drag.pt
drag.pt.x = pt.x;
drag.pt.y = pt.y;
// Show new drag rectangle
InvertRect (hdc, (LPRECT)&drag.rect);
ReleaseDC (hwndMain, hdc);
break;
}
case WM_LBUTTONUP:
{
LPOBJ lpobj;
if (!fCapture)
return TRUE;
fCapture = FALSE;
ReleaseCapture ();
MoveWindow (hwnd, drag.rect.left, drag.rect.top,
drag.rect.right - drag.rect.left,
drag.rect.bottom - drag.rect.top, TRUE);
InvalidateRect (hwnd, (LPRECT)NULL, TRUE);
lpobj = HwndToLpobj (hwnd);
lpobj->native.nX = drag.rect.left;
lpobj->native.nY = drag.rect.top;
break;
}
case WM_DESTROY:
DestroyObj (hwnd);
return DefWindowProc(hwnd, message, wParam, lParam);
default:
return DefWindowProc(hwnd, message, wParam, lParam);
}
return 0;
}
/* DeviceToHiMetric
* ----------------
*
* Converts a point from device units to HiMetric units.
* This function is designed to be generic enough to be reused.
*
* HWND hwnd - The window whose display context is to be used
* LPPOINT lppt - The point to be converted.
*
* CUSTOMIZATION: None
*
*/
void DeviceToHiMetric ( LPPOINT lppt)
{
lppt->x = MulDiv (lppt->x, HIMETRIC_PER_INCH, giXppli);
lppt->y = MulDiv (lppt->y, HIMETRIC_PER_INCH, giYppli);
}
/* UpdateFileMenu
* --------------
*
* Updates the "Update <Client doc>" and "Exit & Return to <Client doc>"
* with the currently set client document name
*
* CUSTOMIZATION: Re-implement
*
*/
VOID UpdateFileMenu (INT iSaveUpdateId)
{
CHAR str[cchFilenameMax];
HMENU hMenu = GetMenu(hwndMain);
/* Change File menu so it contains "Update" instead of "Save". */
lstrcpy (str, "&Update ");
lstrcat (str, szClientDoc);
ModifyMenu(hMenu, iSaveUpdateId, MF_BYCOMMAND|MF_STRING, IDM_UPDATE, str);
/* Change File menu so it contains "Exit & Return to <client doc>" */
/* instead of just "Exit" */
lstrcpy (str, "E&xit && Return to ");
lstrcat (str, szClientDoc);
ModifyMenu(hMenu, IDM_EXIT, MF_BYCOMMAND|MF_STRING, IDM_EXIT, str);
}
/* EmbeddingModeOn
* ---------------
*
* Do whatever is necessary for the application to start "embedding mode."
*
* CUSTOMIZATION: Re-implement
*
*/
VOID EmbeddingModeOn(VOID)
{
HMENU hMenu = GetMenu(hwndMain);
UpdateFileMenu (IDM_SAVE);
/* Change File menu so it contains "Save Copy As..." instead of */
/* "Save As..." */
ModifyMenu(hMenu, IDM_SAVEAS, MF_BYCOMMAND|MF_STRING, IDM_SAVEAS,
"Save Copy As..");
/* In embedded mode, the user can edit only the embedded object, not
create new ones. */
EnableMenuItem(hMenu, menuposObject, MF_BYPOSITION | MF_GRAYED);
EnableMenuItem(hMenu, IDM_CUT, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hMenu, IDM_DELETE, MF_BYCOMMAND | MF_GRAYED);
DrawMenuBar (hwndMain);
}
/* EmbeddingModeOff
* ----------------
*
* Do whatever is necessary for the application to end "embedding mode."
*
* CUSTOMIZATION: Re-implement
*
*/
VOID EmbeddingModeOff (VOID)
{
HMENU hMenu = GetMenu(hwndMain);
/* Change File menu so it contains "Save" instead of "Update". */
ModifyMenu(hMenu, IDM_UPDATE, MF_BYCOMMAND | MF_STRING, IDM_SAVE, "&Save");
/* Change File menu so it contains "Exit & Return to <client doc>" */
/* instead of just "Exit" */
ModifyMenu(hMenu, IDM_EXIT, MF_BYCOMMAND | MF_STRING, IDM_EXIT, "E&xit");
/* Change File menu so it contains "Save As..." instead of */
/* "Save Copy As..." */
ModifyMenu(hMenu, IDM_SAVEAS, MF_BYCOMMAND|MF_STRING, IDM_SAVEAS,
"Save &As..");
/* In non-embedded mode, the user can create new objects. */
EnableMenuItem(hMenu, menuposObject, MF_BYPOSITION | MF_ENABLED);
lstrcpy (szClientDoc, "Client Document");
DrawMenuBar (hwndMain);
}
/* ErrorBox
* --------
*
* char *szMessage - String to display inside message box.
*
* CUSTOMIZATION: Server Demo specific
*
*/
VOID ErrorBox (CHAR *szMessage)
{
MessageBox (hwndMain, szMessage, szAppName, MB_OK);
}
/* GetWord
* -------
*
* LPSTR *plpszSrc - Pointer to a pointer to a source string
* LPSTR lpszDst - Pointer to destination buffer
*
* Will copy one space-terminated or null-terminated word from the source
* string to the destination buffer.
* When done, *plpszSrc will point to the character after the word.
*
* CUSTOMIZATION: Server Demo specific
*
*/
static VOID GetWord (LPSTR *plpszSrc, LPSTR lpszDst)
{
INT i = 0;
while (**plpszSrc && **plpszSrc != ' ')
{
lpszDst[i++] = *(*plpszSrc)++;
}
lpszDst[i] = '\0';
}
/* HiMetricToDevice
* ----------------
*
* Converts a point from HiMetric units to device units.
* This function is designed to be generic enough to be reused.
*
* HWND hwnd - The window whose display context is to be used
* LPPOINT lppt - The point to be converted.
*
* CUSTOMIZATION: None
*
*/
void HiMetricToDevice ( LPPOINT lppt )
{
lppt->x = MulDiv (giXppli, lppt->x, HIMETRIC_PER_INCH);
lppt->y = MulDiv (giYppli, lppt->y, HIMETRIC_PER_INCH);
}
/* HwndToLpobj
* -----------
*
* Given an object's window, return a pointer to the object.
* The GetWindowLong call extracts an LPOBJ from the extra data stored with
* the window.
*
* HWND hwndObj - Handle to the object's window
*
* RETURNS: A pointer to the object
*
* CUSTOMIZATION: Server Demo specific
*
*/
LPOBJ HwndToLpobj (HWND hwndObj)
{
return (LPOBJ) GetWindowLong (hwndObj, ibLpobj);
}
/* CreateUntitledDoc
* -----------------
*
* Create a fresh document with one object.
*
* RETURNS: TRUE if successful
* FALSE otherwise
*
* CUSTOMIZATION: Re-implement
*
*/
static BOOL CreateUntitledDoc (INT nCmdShow)
{
if (!CreateNewDoc (0, "(Untitled)", doctypeNew))
return FALSE;
CreateNewObj (FALSE);
ShowWindow(hwndMain, nCmdShow);
UpdateWindow(hwndMain);
return TRUE;
}
/* ProcessCmdLine
* --------------
*
* Parses the Windows command line which was passed to WinMain.
*
* Case One: SrvrDemo.exe
* fEmbedding = FALSE
* Create an untitled document.
*
* Case two: SrvrDemo.exe filename
* fEmbedding = FALSE
* Create a new document from the file.
*
* Case three: SrvrDemo.exe -Embedding
* fEmbedding = TRUE
* Do not create or register a document.
* Do not show window until client requests it.
*
* Case four: SrvrDemo.exe -Embedding filename
* fEmbedding = TRUE
* Load file.
* Call OleRegisterServerDoc.
* Do not show window until client requests it.
*
*
* LPSTR lpszLine - The Windows command line
* int nCmdShow - Parameter to WinMain
* HWND hwndMain - The application's main window
*
* RETURNS: TRUE if the command line was processed correctly.
* FALSE if a filename was specified which did not
* contain a proper document.
*
* CUSTOMIZATION: None.
*
*/
static BOOL ProcessCmdLine (LPSTR lpszLine, HWND hwndMain)
{
CHAR szBuf[cchFilenameMax];
BOOL fEmbedding = FALSE; // Is "-Embedding" on the command line?
INT i=0;
OFSTRUCT of;
if (!*lpszLine) // No filename or options, so start a fresh document.
{
return CreateUntitledDoc(SW_SHOWNORMAL);
}
SkipBlanks (&lpszLine);
// Check for "-Embedding" or "/Embedding" and set fEmbedding.
if(*lpszLine == '-' || *lpszLine == '/')
{
lpszLine++;
GetWord (&lpszLine, szBuf);
fEmbedding = !lstrcmp(szBuf, szEmbeddingFlag);
}
SkipBlanks (&lpszLine);
if (*lpszLine) // if there is a filename
{
// Put filename into szBuf.
GetWord (&lpszLine, szBuf);
if (-1 == OpenFile(szBuf, &of, OF_READ | OF_EXIST))
{
// File not found
if (fEmbedding)
return FALSE;
else
{
CHAR sz[100];
wsprintf (sz, "File %s not found.", (LPSTR) szBuf);
ErrorBox (sz);
return CreateUntitledDoc(SW_SHOWNORMAL);
}
}
if (!CreateDocFromFile (szBuf, 0, doctypeFromFile))
{
// File not in proper format.
if (fEmbedding)
return FALSE;
else
{
CHAR sz[100];
wsprintf (sz, "File %s not in proper format.", (LPSTR) szBuf);
ErrorBox (sz);
return CreateUntitledDoc(SW_SHOWNORMAL);
}
}
}
if (fEmbedding)
{
/* Do not show window until told to do so by client. */
ShowWindow(hwndMain, SW_HIDE);
}
else
{
ShowWindow(hwndMain, SW_SHOWNORMAL);
UpdateWindow(hwndMain);
}
return TRUE;
}
/* SaveDimensions
* --------------
*
* Save the dimensions of the main window in a private profile file.
*
* CUSTOMIZATION: This function may be removed. If you wish to support
* intelligent window placement, then the only necessary
* change is to change the string "SrvrDemo.Ini" to a filename
* appropriate for your application.
*/
static VOID SaveDimensions (VOID)
{
if ((dimsCurrent.nX != dimsSaved.nX) ||
(dimsCurrent.nY != dimsSaved.nY) ||
(dimsCurrent.nWidth != dimsSaved.nWidth) ||
(dimsCurrent.nHeight != dimsSaved.nHeight) )
{
// Save current window dimensions to private profile.
CHAR szBuf[7];
wsprintf (szBuf, "%d", dimsCurrent.nX);
WritePrivateProfileString
(szAppName, "x", szBuf, "SrvrDemo.Ini");
wsprintf (szBuf, "%d", dimsCurrent.nY);
WritePrivateProfileString
(szAppName, "y", szBuf, "SrvrDemo.Ini");
wsprintf (szBuf, "%d", dimsCurrent.nWidth);
WritePrivateProfileString
(szAppName, "w", szBuf, "SrvrDemo.Ini");
wsprintf (szBuf, "%d", dimsCurrent.nHeight);
WritePrivateProfileString
(szAppName, "h", szBuf, "SrvrDemo.Ini");
}
}
/* SelectedObject
* --------------
*
* Return a pointer to the currently selected object.
*
* CUSTOMIZATION: What a "selected object" is will vary from application
* to application. You may find it useful to have a function
* like this. In your application it may be necessary to
* actually create an OBJ structure based on what data the
* user has selected from the document (by highlighting some
* text for example).
*
*/
LPOBJ SelectedObject (VOID)
{
return HwndToLpobj (SelectedObjectWindow());
}
/* SelectedObjectWindow
* --------------------
*
* Return a handle to the window for the currently selected object.
* The GetWindow calls returns a handle to the main window's first child,
* which is the selected object's window.
*
* CUSTOMIZATION: Server Demo specific
*
*/
HWND SelectedObjectWindow (VOID)
{
return GetWindow (hwndMain, GW_CHILD);
}
/* SetHiMetricFields
* -----------------
*
* Adjust the nHiMetricWidth and nHiMetricHeight fields of a NATIVE structure
* so that they are equivalent to the nWidth and nHeight fields.
* The negative sign in the last line is necessary because the positive
* y direction is toward the top of the screen in MM_HIMETRIC mode.
*
* LPOBJ lpobj - Pointer to the object whose native data will be adjusted
*
* CUSTOMIZATION: Server Demo specific, although you may need a function like
* this if you keep track of the size of an object, and an
* object handler needs to know the object's size in
* HiMetric units.
*
*
*/
VOID SetHiMetricFields (LPOBJ lpobj)
{
POINT pt;
pt.x = lpobj->native.nWidth;
pt.y = lpobj->native.nHeight;
DeviceToHiMetric ( &pt);
lpobj->native.nHiMetricWidth = pt.x;
lpobj->native.nHiMetricHeight = pt.y;
}
/* SkipBlanks
* ----------
*
* LPSTR *plpsz - Pointer to a pointer to a character
*
* Increment *plpsz past any blanks in the character string.
* This function is used in ProcessCmdLine.
*
*/
static VOID SkipBlanks (LPSTR *plpsz)
{
while (**plpsz && **plpsz == ' ')
(*plpsz)++;
}
/* UpdateObjMenus
* ---------------
*
* Grey or Ungrey menu items depending on the existence of at least one
* object in the document.
*
* CUSTOMIZATION: Server Demo specific
*
*/
static VOID UpdateObjMenus (VOID)
{
static BOOL fObjMenusEnabled = TRUE;
BOOL fOneObjExists; // Does at least one object exist?
WORD wEnable;
HMENU hMenu;
fOneObjExists = (SelectedObjectWindow() != NULL);
if (fOneObjExists == fObjMenusEnabled)
{
// Nothing has changed.
return;
}
wEnable = (WORD)(fOneObjExists ? MF_ENABLED : MF_GRAYED);
hMenu = GetMenu(hwndMain);
EnableMenuItem(hMenu, menuposColor, MF_BYPOSITION | wEnable);
hMenu = GetSubMenu(GetMenu(hwndMain), menuposFile);
EnableMenuItem(hMenu, IDM_SAVE, MF_BYCOMMAND | wEnable);
EnableMenuItem(hMenu, IDM_SAVEAS, MF_BYCOMMAND | wEnable);
hMenu = GetSubMenu(GetMenu(hwndMain), menuposEdit);
EnableMenuItem(hMenu, IDM_CUT, MF_BYCOMMAND | wEnable);
EnableMenuItem(hMenu, IDM_COPY, MF_BYCOMMAND | wEnable);
EnableMenuItem(hMenu, IDM_DELETE, MF_BYCOMMAND | wEnable);
hMenu = GetSubMenu(GetMenu(hwndMain), menuposObject);
EnableMenuItem(hMenu, IDM_NEXTOBJ, MF_BYCOMMAND | wEnable);
DrawMenuBar (hwndMain);
fObjMenusEnabled = fOneObjExists;
}
/* Wait
* ----
*
* Dispatch messages until the given flag is set to FALSE.
* One use of this function is to wait until a Release method is called
* after a function has returned OLE_WAIT_FOR_RELEASE.
*
* BOOL *pf - Pointer to the flag being waited on.
*
* CUSTOMIZATION: The use of OleUnblockServer is for illustration only.
* Since Server Demo does not call OleBlockServer, there
* will never be any messages in the OLE queue.
*
*/
VOID Wait (BOOL *pf)
{
MSG msg;
BOOL fMoreMsgs = FALSE;
*pf = TRUE;
while (*pf==TRUE)
{
OleUnblockServer (srvrMain.lhsrvr, &fMoreMsgs);
if (!fMoreMsgs)
// if there are no more messages in the OLE queue, go to system queue
{
if (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
}
}
static BOOL FailedUpdate(HWND hwnd)
{
return(DialogBox(hInst, "FailedUpdate", hwnd, (DLGPROC)fnFailedUpdate));
}
BOOL APIENTRY fnFailedUpdate (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
WORD wID = LOWORD(wParam);
switch (wID)
{
case IDCANCEL:
case IDD_CONTINUEEDIT:
EndDialog(hDlg, TRUE);
break;
case IDD_UPDATEEXIT:
EndDialog(hDlg, FALSE);
break;
default:
break;
}
break;
}
case WM_INITDIALOG:
{
CHAR szMsg[200];
szMsg[0] = '\0';
wsprintf(
szMsg,
"This %s document can only be updated when you exit %s.",
(LPSTR) szClient,
(LPSTR) szAppName
);
SetDlgItemText(hDlg, IDD_TEXT, szMsg);
return TRUE;
}
default:
break;
}
return FALSE;
}