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));
|
|||
|
}
|
|||
|
|
|||
|
|