home *** CD-ROM | disk | FTP | other *** search
- // ObjectWindows - (C) Copyright 1992 by Borland International
-
- /* implementation of class TOLEObject */
-
- #include <owl.h>
-
- #define SERVERONLY
- #include <ole.h>
-
- #include <ctype.h>
- #include "olesrvr.h"
- #include <string.h>
- #include <fstream.h>
-
- OLEOBJECTVTBL TOLEObject::_vtbl;
-
-
- /*
- constructor
- -----------
- */
- TOLEObject::TOLEObject ()
- {
- lpvtbl = &_vtbl;
- native.type = objEllipse;
- native.version = 1;
- lpClients[0] = 0;
- fRelease = FALSE;
- }
-
-
- ostream &operator<< (ostream &out, TOLEObject &obj)
- {
- out << int (obj.native.type) << " ";
- out << obj.native.version;
- return out;
- }
-
-
- istream &operator>> (istream &in, TOLEObject &obj)
- {
- int newType;
-
- in >> newType;
- ((TWindowServer *) GetApplicationObject()->MainWindow)->ShapeChange ((NATIVETYPE) newType);
- obj.native.type = (NATIVETYPE) newType;
- in >> obj.native.version;
- return in;
- }
-
-
- /*
- SetType
- -------
-
- sets the "type" instance variable and calls ObjectChanged()
- */
- void
- TOLEObject::SetType (NATIVETYPE type)
- {
- native.type = type;
-
- ObjectChanged();
- }
-
-
- /*
- ObjectChanged
- -------------
-
- send each of the clients we are linked to an OLE_CHANGED message
- */
- void
- TOLEObject::ObjectChanged ()
- {
- TOLEDocument *pDoc = ((TOLEApp *) GetApplicationObject())->pServer->pDocument;
-
- //
- // call the object through its callback function
- //
- if (lpClients[0])
- for (int i = 0; lpClients[i] != 0; i++)
- lpClients[i]->lpvtbl->CallBack (lpClients[i], OLE_CHANGED, this);
-
- //
- // mark the document as changed
- //
- pDoc->fDirty = TRUE;
- }
-
-
- /*
- AddClientLink
- -------------
- */
- void
- TOLEObject::AddClientLink (LPOLECLIENT lpOleClient)
- {
- //
- // we always append clients to the end of the list
- //
- // find the next slot
- //
- for (int i = 0; i < MAXLINKS; i++)
- if (lpClients[i] == 0) {
- lpClients[i] = lpOleClient;
- lpClients[i + 1] = 0; // NULL terminator
- return;
- }
- }
-
-
- /*
- Draw
- ----
-
- draw the type specified by "type" using the device context that is passed
- in
- */
- void
- TOLEObject::Draw (HDC hDC)
- {
- HANDLE hOldBrush = SelectObject (hDC, CreateSolidBrush (RGB (255, 0, 0)));
- HANDLE hOldPen = SelectObject (hDC, GetStockObject (NULL_PEN));
-
- switch (native.type) {
- case objEllipse:
- Ellipse (hDC, 0, 0, OBJWIDTH, OBJHEIGHT);
- break;
-
- case objRect:
- Rectangle (hDC, 0, 0, OBJWIDTH, OBJHEIGHT);
- break;
-
- case objTriangle:
- int xCenter = OBJWIDTH / 2;
- POINT pts[] = {{xCenter, 0},
- {0, OBJHEIGHT - 1},
- {OBJWIDTH - 1, OBJHEIGHT - 1},
- {xCenter, 0}};
-
- Polygon (hDC, pts, 4);
- break;
- }
-
- DeleteObject (SelectObject (hDC, hOldBrush));
- SelectObject (hDC, hOldPen);
- }
-
-
- /*
- GetNativeData
- -------------
-
- returns a global memory handle that contains the native data for the
- receiver
-
- this handle can be used to set the Native clipboard data format
- */
- HANDLE
- TOLEObject::GetNativeData ()
- {
- HANDLE hData;
- LPNATIVE lpData;
-
- hData = GlobalAlloc (GMEM_DDESHARE, sizeof (native));
-
- if (hData) {
- lpData = (LPNATIVE) GlobalLock (hData);
- *lpData = native;
- GlobalUnlock (hData);
- }
-
- return hData;
- }
-
-
- /*
- GetLinkData
- -----------
-
- returns a global memory handle that contains three fields:
-
- - class name
- - document name (typically a fully qualified path name that identifies
- the file containing the document)
- - item name (uniquely identifies the part of the document that is defined
- as an object)
-
- the class name and document name are null terminated, and the item name
- has two terminating null characters, e.g. CNAME\0DNAME\0INAME\0\0
-
- NOTE: item names are assigned by the server. since we have only 1 object
- per document, we always use the same name ("1"). most applications
- would use a different strategy, e.g. "Object1", "Object2", ...
-
- since "ObjectLink" and "OwnerLink" formats contain the same information
- the handle that is returned can be used for both clipboard formats
- */
- HANDLE
- TOLEObject::GetLinkData ()
- {
- HANDLE hData;
- LPSTR lpData;
- TOLEDocument *pDoc = ((TOLEApp *) GetApplicationObject())->pServer->pDocument;
- int docNameLen = strlen (pDoc->szName);
- const int classKeyLen = sizeof (szClassKey) - 1;
- int len = classKeyLen + docNameLen + strlen ("1") + 4;
-
- hData = GlobalAlloc (GMEM_DDESHARE, len);
-
- if (hData) {
- lpData = (LPSTR) GlobalLock (hData);
-
- //
- // write class name
- //
- lstrcpy (lpData, szClassKey);
- lpData += classKeyLen + 1;
-
- //
- // write document name
- //
- lstrcpy (lpData, pDoc->szName);
- lpData += docNameLen + 1;
-
- //
- // write item name (we always write "1")
- //
- *lpData++ = '1';
- *lpData++ = '\0';
-
- //
- // write extra null terminator
- //
- *lpData = '\0';
-
- GlobalUnlock (hData);
- }
-
- return hData;
- }
-
-
- /*
- SizeToHiMetric
- --------------
-
- convert a width and height from device units to MM_HIMETRIC units
- which are required by the OLE libraries
- */
- static
- void
- SizeToHiMetric (int &width, int &height)
- {
- HDC hDC = GetDC (0); // screen
- int dpiX = GetDeviceCaps (hDC, LOGPIXELSX);
- int dpiY = GetDeviceCaps (hDC, LOGPIXELSY);
- const long HiMetricPerInch = 2540;
-
- width = int (width * HiMetricPerInch / dpiX);
- height = int (height * HiMetricPerInch / dpiY);
-
- ReleaseDC (0, hDC);
- }
-
-
- /*
- GetMetafilePicture
- ------------------
- */
- HANDLE
- TOLEObject::GetMetafilePicture ()
- {
- LPMETAFILEPICT lpPict;
- HANDLE hPict;
- HMETAFILE hMF;
- HDC hDC = CreateMetaFile (NULL);
- int width = 100, height = 100;
-
- //
- // draw the object into the metafile
- //
- SetWindowOrg (hDC, 0, 0);
- SetWindowExt (hDC, width, height);
- Draw (hDC);
-
- //
- // get the handle to the metafile.
- //
- hMF = CloseMetaFile (hDC);
-
- //
- // allocate the metafile picture
- //
- hPict = GlobalAlloc (GMEM_DDESHARE, sizeof (METAFILEPICT));
-
- if (hPict) {
- SizeToHiMetric (width, height);
- lpPict = (LPMETAFILEPICT) GlobalLock (hPict);
-
- lpPict->mm = MM_ANISOTROPIC;
- lpPict->hMF = hMF;
- lpPict->xExt = width;
- lpPict->yExt = height;
-
- GlobalUnlock (hPict);
- }
-
- return hPict;
- }
-
-
- /*
- GetBitmapData
- -------------
- */
- HBITMAP
- TOLEObject::GetBitmapData ()
- {
- HWND hWnd = GetApplicationObject()->MainWindow->HWindow;
- HDC hDC = GetDC (hWnd);
- HDC hMemoryDC = CreateCompatibleDC (hDC);
- HBITMAP hBitmap = CreateCompatibleBitmap (hDC, 100, 100);
- HBITMAP hOldBitmap = (HBITMAP) SelectObject (hMemoryDC, hBitmap);
- int width = 100, height = 100;
-
- ReleaseDC (hWnd, hDC);
- PatBlt (hMemoryDC, 0, 0, width, height, WHITENESS);
- Draw (hMemoryDC);
- SelectObject (hMemoryDC, hOldBitmap);
- DeleteDC (hMemoryDC);
-
- //
- // convert the width and height to MM_HIMETRIC (all OLE libraries express
- // the size of every object in MM_HIMETRIC)
- //
- SizeToHiMetric (width, height);
-
- //
- // SetBitmapDimension() wants the width and height in .1 millimeter
- // units, so we must divide by 10...
- //
- SetBitmapDimension (hBitmap, width / 10, height / 10);
-
- return hBitmap;
- }
-
-
- /*
- callback DoVerb
- -------- ------
-
- client application has called OleActivate() on an embedded object and
- requests an action on the object
-
- the action is specified by the verb identifier "wVerb"
-
- our server only understands EDIT and PLAY:
- - all we do for PLAY is beep
-
- - for EDIT we bring up the server and let the user edit the specified
- object
-
- PARAMETERS:
- - "wVerb" is the index to the verb to execute
- - "fShow" indicates if the server should show the object or remain in
- its current state
- - "fFocus" indicates if the server should take the focus
-
- WHAT TO DO:
- - for PLAY verb, a server doesn't usually show its window or affect the
- focus
- - for EDIT verb, show the server's window and object if "fShow" and take
- the focus is "fFocus"
- - return OLE_OK if successful, OLE_ERROR_DOVERB otherwise
- */
- OLESTATUS FAR PASCAL _export
- TOLEObject::DoVerb (LPOLEOBJECT lpOleObject,
- unsigned int wVerb,
- BOOL fShow,
- BOOL fTakeFocus)
- {
- switch (wVerb) {
- case verbEdit:
- //
- // the easiest way to show the server's window is to send the object a
- // "Show" message
- //
- return fShow ? lpOleObject->lpvtbl->Show (lpOleObject, fTakeFocus) : OLE_OK;
-
- case verbPlay:
- for (int i = 0; i < 10; i++)
- MessageBeep (0);
-
- return OLE_OK;
-
- default:
- return OLE_ERROR_DOVERB;
- }
- }
-
-
- /*
- callback EnumFormats
- -------- -----------
-
- client has requested that we enumerate all clipboard formats that we
- support for object "lpOleObject"
-
- the server library will make multiple calls until we return the format
- that the server library is looking for
-
- PARAMETERS:
- - "cfFormat" is the last format returned by this method. if it is 0 then
- this is the first call to the method for this series
-
- we terminate the query by returning NULL
-
- NOTE: we *must* return the formats in the same order as the order that
- data is placed on the clipboard!
- */
- OLECLIPFORMAT FAR PASCAL _export
- TOLEObject::EnumFormats (LPOLEOBJECT /* lpOleObject */,
- OLECLIPFORMAT cfFormat)
- {
- TOLEApp *pApp = (TOLEApp *) GetApplicationObject();
-
- //
- // if "cfFormat" is 0 that indicates the client wants us to return the
- // first format
- //
- if (cfFormat == 0)
- return pApp->cfNative;
-
- else if (cfFormat == pApp->cfNative)
- return pApp->cfOwnerLink;
-
- else if (cfFormat == pApp->cfOwnerLink)
- return CF_METAFILEPICT;
-
- else if (cfFormat == CF_METAFILEPICT)
- return CF_BITMAP;
-
- else
- return NULL;
- }
-
-
- /*
- callback GetData
- -------- -------
-
- we are requested to supply data for the object in a specific format,
- such as Native or CF_METAFILEPICT
-
- in general you should handle the same data formats that you put on the
- clipboard when the object was embedded/linked
-
- these should be the same formats that are returned by method EnumFormats()
-
- requests foro GetData occur at any time that the client needs to display
- an object or when the data must be written to a client file
- */
- OLESTATUS FAR PASCAL _export
- TOLEObject::GetData (LPOLEOBJECT lpOleObject,
- WORD cfFormat,
- LPHANDLE lpHandle)
- {
- TOLEApp *pApp = (TOLEApp *) GetApplicationObject();
- TOLEObject *pObject = (TOLEObject *) lpOleObject; // just a cast
-
- if (cfFormat == pApp->cfNative) {
- *lpHandle = pObject->GetNativeData();
-
- return *lpHandle ? OLE_OK : OLE_ERROR_MEMORY;
- }
-
- if (cfFormat == pApp->cfOwnerLink) {
- *lpHandle = pObject->GetLinkData();
-
- return *lpHandle ? OLE_OK : OLE_ERROR_MEMORY;
- }
-
- if (cfFormat == CF_BITMAP) {
- *lpHandle = pObject->GetBitmapData();
-
- return *lpHandle ? OLE_OK : OLE_ERROR_MEMORY;
- }
-
- if (cfFormat == CF_METAFILEPICT) {
- *lpHandle = pObject->GetMetafilePicture();
-
- return *lpHandle ? OLE_OK : OLE_ERROR_MEMORY;
- }
-
- return OLE_ERROR_FORMAT;
- }
-
-
- /*
- callback QueryProtocol
- -------- -------------
-
- server library is trying to determine which protocols we support
-
- "lpszProtocol" will either be "StdFileEditing" or "StdExecute"
-
- if we don't support the protocol then we should return NULL
-
- since we don't support "StdFileExecute" we return NULL in that case
- */
- LPVOID FAR PASCAL _export
- TOLEObject::QueryProtocol (LPOLEOBJECT lpOleObject,
- LPSTR lpszProtocol)
- {
- return lstrcmp (lpszProtocol, "StdFileEditing") ? NULL : lpOleObject;
- }
-
-
- /*
- callback Release
- -------- -------
-
- this method gets called when the library wants to inform us that we have
- no more clients connected to the object
-
- it is initiated after the client calls OleDelete() or the server calls
- OleRevokeServer(), OleRevokeServerDoc(), or OleRevokeObject()
-
- this is the last time that the receiving object will be called, so all
- resources for the object can be free'd, but we MUST not delete the object
- itself...
-
- WHAT TO DO:
- - free resourcess associated with the object
- - set a flag to indicate "Release" has been called
- - NULL out any saved LPOLECLIENT handles saved in the object
- - return OLE_OK if successful, OLE_ERROR_GENERIC otherwise
- */
- OLESTATUS FAR PASCAL _export
- TOLEObject::Release (LPOLEOBJECT lpOleObject)
- {
- TOLEObject *pObject = (TOLEObject *) lpOleObject;
-
- pObject->lpClients[0] = 0;
- pObject->fRelease = TRUE;
- return OLE_OK;
- }
-
-
- /*
- callback SetBounds
- -------- ---------
- */
- OLESTATUS FAR PASCAL _export
- TOLEObject::SetBounds (LPOLEOBJECT /* lpoleobj */,
- LPRECT /* lprect */)
- {
- return OLE_ERROR_GENERIC;
- }
-
-
- /*
- callback SetColorScheme
- -------- --------------
- */
- OLESTATUS FAR PASCAL _export
- TOLEObject::SetColorScheme (LPOLEOBJECT /* lpOleObject */,
- LPLOGPALETTE /* lpPal */)
- {
- return OLE_ERROR_GENERIC;
- }
-
-
- /*
- callback SetData
- -------- -------
-
- this routine gets called to provide the server with the data for an
- object that is embedded in a client
-
- this routine gets called after the server has received an "Edit" message
-
- this method is always called before "DoVerb" and "Show"
-
- WHAT TO DO:
- - if the data format isn't Native, return OLE_ERROR_FORMAT
- - lock down the memory to get a pointer to the data, returning
- OLE_ERROR_MEMORY if GlobalLock() returns NULL
- - copy the data to "lpOleObject"
- - unlock the memory and call GlobalFree() on the handle (you are
- responsible for the memory!)
- - return OLE_OK
- */
- OLESTATUS FAR PASCAL _export
- TOLEObject::SetData (LPOLEOBJECT lpOleObject,
- OLECLIPFORMAT cfFormat,
- HANDLE hData)
- {
- TOLEApp *pApp = (TOLEApp *) GetApplicationObject();
-
- if (cfFormat != pApp->cfNative)
- return OLE_ERROR_FORMAT; // data isn't in Native format
-
- else {
- LPNATIVE lpData = (LPNATIVE) GlobalLock (hData);
-
- if (lpData == NULL)
- return OLE_ERROR_MEMORY;
-
- else {
- TOLEObject *pObject = (TOLEObject *) lpOleObject;
-
- ((TWindowServer *) pApp->MainWindow)->ShapeChange (lpData->type);
- pObject->native = *lpData;
- pApp->pServer->pDocument->fDirty = FALSE;
-
- GlobalUnlock (hData);
- GlobalFree (hData);
- return OLE_OK;
- }
- }
- }
-
-
- /*
- callback SetTargetDevice
- -------- ---------------
- */
- OLESTATUS FAR PASCAL _export
- TOLEObject::SetTargetDevice (LPOLEOBJECT /* lpOleObject */,
- HANDLE /* hData */)
- {
- return OLE_ERROR_GENERIC;
- }
-
-
- /*
- callback Show
- -------- ----
-
- this method gets called when we should make the object visible by
- making the server window visible and possibly scroling the object into
- view
-
- if the object is selectable, select it as well
-
- PARAMETERS:
- - "fTakeFocus" indicates whether the server should set focus to itself
-
- WHAT TO DO:
- - show the window(s) if not visible
- - scroll "lpOleObject" into view and select it if possible
- - if "fTakeFocus" is TRUE, call SetFocus() with the main window handle
- - return OLE_OK if successful, OLE_ERROR_GENERIC otherwise
- */
- OLESTATUS FAR PASCAL _export
- TOLEObject::Show (LPOLEOBJECT /* lpOleObject */,
- BOOL fTakeFocus)
- {
- TOLEApp *pApp = (TOLEApp *) GetApplicationObject();
-
- //
- // in our case all we need to do is request that the window is showing
- //
- pApp->MainWindow->Show (SW_SHOWNORMAL);
-
- if (fTakeFocus)
- SetFocus (pApp->MainWindow->HWindow);
-
- return OLE_OK;
- }
-
-
-
- typedef OLESTATUS FAR PASCAL _export (FAR *LPOBJDOVERB)(LPOLEOBJECT,unsigned int,BOOL,BOOL);
- typedef OLECLIPFORMAT FAR PASCAL _export (FAR *LPOBJENUMFORMATS)(LPOLEOBJECT,OLECLIPFORMAT);
- typedef OLESTATUS FAR PASCAL _export (FAR *LPOBJGETDATA)(LPOLEOBJECT,WORD,LPHANDLE);
- typedef LPVOID FAR PASCAL _export (FAR *LPOBJQUERYPROTOCOL)(LPOLEOBJECT,const char far *);
- typedef OLESTATUS FAR PASCAL _export (FAR *LPOBJRELEASE)(LPOLEOBJECT);
- typedef OLESTATUS FAR PASCAL _export (FAR *LPOBJSETBOUNDS)(LPOLEOBJECT,const RECT far *);
- typedef OLESTATUS FAR PASCAL _export (FAR *LPOBJSETCOLORSCHM)(LPOLEOBJECT,const LOGPALETTE far *);
- typedef OLESTATUS FAR PASCAL _export (FAR *LPOBJSETDATA)(LPOLEOBJECT,OLECLIPFORMAT,HANDLE);
- typedef OLESTATUS FAR PASCAL _export (FAR *LPOBJSETTARGETDEVICE)(LPOLEOBJECT,HANDLE);
- typedef OLESTATUS FAR PASCAL _export (FAR *LPOBJSHOW)(LPOLEOBJECT,BOOL);
-
-
- /*
- InitVTBL
- --------
-
- create thunks for OLEOBJECT method callback tables
- */
- BOOL
- TOLEObject::InitVTBL (HINSTANCE hInstance)
- {
- _vtbl.DoVerb = (LPOBJDOVERB) MakeProcInstance ((FARPROC) DoVerb, hInstance);
- _vtbl.EnumFormats = (LPOBJENUMFORMATS) MakeProcInstance ((FARPROC) EnumFormats, hInstance);
- _vtbl.GetData = (LPOBJGETDATA) MakeProcInstance ((FARPROC) GetData, hInstance);
- _vtbl.QueryProtocol = (LPOBJQUERYPROTOCOL) MakeProcInstance ((FARPROC) QueryProtocol, hInstance);
- _vtbl.Release = (LPOBJRELEASE) MakeProcInstance ((FARPROC) Release, hInstance);
- _vtbl.SetBounds = (LPOBJSETBOUNDS) MakeProcInstance ((FARPROC) SetBounds, hInstance);
- _vtbl.SetColorScheme = (LPOBJSETCOLORSCHM) MakeProcInstance ((FARPROC) SetColorScheme, hInstance);
- _vtbl.SetData = (LPOBJSETDATA) MakeProcInstance ((FARPROC) SetData, hInstance);
- _vtbl.SetTargetDevice = (LPOBJSETTARGETDEVICE) MakeProcInstance ((FARPROC) SetTargetDevice, hInstance);
- _vtbl.Show = (LPOBJSHOW) MakeProcInstance ((FARPROC) Show, hInstance);
-
- return _vtbl.DoVerb != NULL &&
- _vtbl.EnumFormats != NULL &&
- _vtbl.GetData != NULL &&
- _vtbl.QueryProtocol != NULL &&
- _vtbl.Release != NULL &&
- _vtbl.SetBounds != NULL &&
- _vtbl.SetColorScheme != NULL &&
- _vtbl.SetData != NULL &&
- _vtbl.SetTargetDevice != NULL &&
- _vtbl.Show != NULL;
- }
-