214 lines
7.5 KiB
C++
214 lines
7.5 KiB
C++
//+---------------------------------------------------------------------
|
||
//
|
||
// File: clsdesc.cxx
|
||
//
|
||
// Contents: ClassDescriptor implementation
|
||
//
|
||
//------------------------------------------------------------------------
|
||
|
||
//[ classdescriptor_overview
|
||
/*
|
||
ClassDescriptor Overview
|
||
|
||
A ClassDescriptor is a structure the contains global, static information
|
||
about an OLE Compound Document class. Having a ClassDescriptor allows
|
||
the base classes to do a lot of work on behalf of the derived class because
|
||
it can get information it needs from the ClassDescriptor instead of resorting
|
||
to virtual method calls. A single ClassDescriptor is shared by all object
|
||
instances of that Compound Document class.
|
||
|
||
A ClassDescriptor has three conceptual parts. The first part is a collection
|
||
of information loaded from resources. This includes strings, menus, accelerators,
|
||
and an icon. The second part is a pair of verb tables that are used to implement
|
||
IOleObject::DoVerb. The third part is two pairs of format tables that are
|
||
used to implement many of the Get/Set/Query methods on IDataObject.
|
||
Each of these parts has its own initialization method to prepare that part of
|
||
the class descriptor.
|
||
|
||
The ClassDescriptor is usually associated with the ClassFactory.
|
||
|
||
*/
|
||
//]
|
||
|
||
#include "headers.hxx"
|
||
#pragma hdrstop
|
||
|
||
#define MAX_USERTYPE_LEN 64
|
||
|
||
//+---------------------------------------------------------------
|
||
//
|
||
// Member: ClassDescriptor::ClassDescriptor
|
||
//
|
||
// Synopsis: Constructor for ClassDescriptor structure
|
||
//
|
||
// Notes: A DLL (in-process) server should allocate the class
|
||
// descriptor at library initialization time and allocate
|
||
// it in shared memory (GMEM_SHARE flag with GlobalAlloc, or
|
||
// the OLE shared allocator, MEMCTX_SHARED).
|
||
//
|
||
// The constructor ensures all members of the structure
|
||
// are initialized to NULL
|
||
//
|
||
//----------------------------------------------------------------
|
||
|
||
ClassDescriptor::ClassDescriptor(void)
|
||
{
|
||
// initialize everything to NULL
|
||
// ZeroMemory(this, sizeof(ClassDescriptor));
|
||
memset(this, 0, sizeof(ClassDescriptor));
|
||
}
|
||
|
||
//+---------------------------------------------------------------
|
||
//
|
||
// Member: ClassDescriptor::Init
|
||
//
|
||
// Synopsis: Initializes a class descriptor structure from resources
|
||
//
|
||
// Arguments: [hinst] -- instance handle of module with resources used
|
||
// to initialize the class descriptor
|
||
//
|
||
// Returns: TRUE iff the class descriptor was successfully initialized
|
||
//
|
||
// Notes: This method only fills in the part of the class descriptor
|
||
// that can be initialized from resources. The other part
|
||
// that requires initialization are the verb and format tables.
|
||
//
|
||
// Objects that are concerned about resource load times could
|
||
// not use this initialization method and fill in fields of the
|
||
// class descriptor directly.
|
||
//
|
||
//----------------------------------------------------------------
|
||
|
||
BOOL ClassDescriptor::Init(HINSTANCE hinst, WORD wBaseID)
|
||
{
|
||
//REVIEW: Currently, information loaded from resources is duplicated
|
||
//REVIEW: in the registration database. We could
|
||
//REVIEW: (1) load this stuff from the reg db instead (except CLSID), or
|
||
//REVIEW: (2) do an autoregistration feature where the reg db is filled
|
||
//REVIEW: in from the class descriptor information loaded from resources
|
||
|
||
//REVIEW: We could also support loading the verb and format tables
|
||
//REVIEW: from resources/regdb as well.
|
||
|
||
_hinst = hinst;
|
||
_wBaseResID = wBaseID;
|
||
|
||
// load our class id string and convert it into our real class id
|
||
TCHAR szClsId[40];
|
||
ZeroMemory (szClsId, sizeof (szClsId));
|
||
|
||
LoadString(hinst, wBaseID+IDOFF_CLASSID, szClsId, ARRAY_SIZE(szClsId));
|
||
|
||
#if !defined(UNICODE) && !defined(OLE2ANSI)
|
||
LPOLESTR lpostr = ConvertMBToOLESTR(szClsId,-1);
|
||
BOOL fRet = OK(CLSIDFromString(lpostr, &_clsid));
|
||
TaskFreeMem(lpostr);
|
||
#else
|
||
BOOL fRet = OK(CLSIDFromString(szClsId, &_clsid));
|
||
#endif
|
||
|
||
// load our in-place menus and accelerators
|
||
_hicon = LoadIcon(hinst, MAKEINTRESOURCE(wBaseID+IDOFF_ICON));
|
||
|
||
_haccel = (HACCEL)LoadAccelerators(hinst,
|
||
MAKEINTRESOURCE(wBaseID+IDOFF_ACCELS));
|
||
|
||
LoadResourceData(hinst,
|
||
MAKEINTRESOURCE(wBaseID+IDOFF_MGW),
|
||
&_mgw,
|
||
sizeof(_mgw));
|
||
|
||
LoadResourceData(hinst,
|
||
MAKEINTRESOURCE(wBaseID+IDOFF_MISCSTATUS),
|
||
&_dwMiscStatus,
|
||
sizeof(_dwMiscStatus));
|
||
|
||
#if !defined(UNICODE) && !defined(OLE2ANSI)
|
||
|
||
CHAR szUserClassType[MAX_USERTYPE_LEN];
|
||
|
||
#define SetWideClassType(y,x) \
|
||
MultiByteToWideChar(CP_ACP \
|
||
, 0 \
|
||
, (y) \
|
||
, -1 \
|
||
, _szUserClassType[(x)] \
|
||
, ARRAY_SIZE(_szUserClassType[(x)]))
|
||
LoadString(hinst
|
||
, wBaseID+IDOFF_USERTYPEFULL
|
||
, szUserClassType
|
||
, MAX_USERTYPE_LEN);
|
||
|
||
SetWideClassType(szUserClassType,USERCLASSTYPE_FULL);
|
||
|
||
LoadString(hinst
|
||
, wBaseID+IDOFF_USERTYPESHORT
|
||
, szUserClassType
|
||
, MAX_USERTYPE_LEN);
|
||
|
||
SetWideClassType(szUserClassType,USERCLASSTYPE_SHORT);
|
||
|
||
LoadString(hinst
|
||
, wBaseID+IDOFF_USERTYPEAPP
|
||
, szUserClassType
|
||
, MAX_USERTYPE_LEN);
|
||
|
||
SetWideClassType(szUserClassType,USERCLASSTYPE_APPNAME);
|
||
|
||
LoadString(hinst
|
||
, wBaseID+IDOFF_DOCFEXT
|
||
, szUserClassType
|
||
, MAX_USERTYPE_LEN);
|
||
|
||
MultiByteToWideChar(CP_ACP
|
||
, 0
|
||
, szUserClassType
|
||
, -1
|
||
, _szDocfileExt
|
||
, ARRAY_SIZE(_szDocfileExt));
|
||
#else
|
||
LoadString(hinst
|
||
, wBaseID+IDOFF_USERTYPEFULL
|
||
, _szUserClassType[USERCLASSTYPE_FULL]
|
||
, ARRAY_SIZE(_szUserClassType[USERCLASSTYPE_FULL]));
|
||
LoadString(hinst
|
||
, wBaseID+IDOFF_USERTYPESHORT
|
||
, _szUserClassType[USERCLASSTYPE_SHORT]
|
||
, ARRAY_SIZE(_szUserClassType[USERCLASSTYPE_SHORT]));
|
||
LoadString(hinst
|
||
, wBaseID+IDOFF_USERTYPEAPP
|
||
, _szUserClassType[USERCLASSTYPE_APPNAME]
|
||
, ARRAY_SIZE(_szUserClassType[USERCLASSTYPE_APPNAME]));
|
||
LoadString(hinst
|
||
, wBaseID+IDOFF_DOCFEXT
|
||
, _szDocfileExt
|
||
, ARRAY_SIZE(_szDocfileExt));
|
||
|
||
#endif
|
||
|
||
return fRet;
|
||
}
|
||
|
||
//+---------------------------------------------------------------
|
||
//
|
||
// Member: ClassDescriptor::LoadMenu, public
|
||
//
|
||
// Synopsis: Loads a copy of the menus for the server
|
||
//
|
||
// Notes: A single copy of the menu cannot be shared by all
|
||
// instances of the class, like an accelerator table can.
|
||
// This is because the menu is not a read-only resource
|
||
// (e.g. you can "check" a menu item and merge in verb
|
||
// menu items). Therefore each class instance must load
|
||
// its own copy of the menu. This LoadMenu call is used
|
||
// for that purpose.
|
||
//
|
||
//---------------------------------------------------------------
|
||
|
||
HMENU
|
||
ClassDescriptor::LoadMenu(void)
|
||
{
|
||
return ::LoadMenu(_hinst, MAKEINTRESOURCE(_wBaseResID+IDOFF_MENU));
|
||
}
|
||
|
||
|