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