TDM Geschrieben 26. Januar 2007 Geschrieben 26. Januar 2007 Hallo, Ich habe folgendes Problem: Über einen Dialog werden Daten eingelesen usw. Diese werden anschließend in einer Maske ausgegeben. In dieser Maske sind außerdem Buttons für das Speichern und Drucken als Worddokument. Dazu habe ich eine Klasse CWordFile geschrieben: class CWordFile { public: void p_print(void); void p_save(const CString& p_lpPath); static const CWordFile p_open(const CString& a_lpDestination); CWordFile(const CWordFile& p_oRhs); void p_setBookMarkText(const CString& p_lpBookMarkName, const CString& p_lpBookMarkText); virtual ~CWordFile(); private: CWordFile( const CString& p_lpSource); struct SValue_t { public: SValue_t(const CString& p_lpSource):m_lpeSource(p_lpSource) {} CString m_lpeSource; struct SWValue_t { public: CComDispatchDriver m_oeSpDispDokument; CComDispatchDriver m_oeSpDocuments; CComDispatchDriver m_oeSpDispWord; IDispatchPtr m_oeSpDocument; } m_seWordMembers; } m_seMembers; static struct SWord_t { HRESULT m_oeHR; VARIANT m_oevResult; CLSID m_oeCLSIDWordApplication; IDispatchPtr m_oeSpIWord; INT m_neMemberCounter; } s_m_seWordMembers; void m_Work(const INT p_nFlags); void m_init(void); void m_uninit(void); }; Es soll nur möglich sein, ein Objekt über die open-Methode zu erzeugen. Evtl. Initialisierungen für Word finden im Konstruktor statt: CWordFile::CWordFile(const CString& p_lpSource):m_seMembers(p_lpSource) { if (++CWordFile::s_m_seWordMembers.m_neMemberCounter == 1) { m_init(); } } und werden evtl. im Destruktor wieder unitialisiert: CWordFile::~CWordFile() { if (--CWordFile::s_m_seWordMembers.m_neMemberCounter == 0) { m_uninit(); } } Wie bereits erwähnt, wird das ein Objekt über einen Dialog erzeugt: void COutputDlg::On_Save_clicked() { auto CString a_lpSource = CSettings::s_p_lpGetWordSource(); static char BASED_CODE szFilter[] = "Worddokumente (*.doc)|*.doc|Textdatei (*.txt)|*.txt; | Alle Dateien (*.*)|*.*||"; auto CFileDialog a_oSFD(FALSE, NULL, NULL, OFN_OVERWRITEPROMPT, szFilter); auto CString a_lpDestination = _T(""); a_oSFD.m_ofn.lpstrTitle="Speichern unter"; if(a_oSFD.DoModal() == IDOK) { a_lpDestination = a_oSFD.GetPathName(); TRACE("%s", a_oSFD.GetFileExt()); try { auto CWordFile a_oFile = CWordFile:_open(a_lpSource); s_m_setBookmarks(a_oFile); a_oFile.p_save(a_lpDestination); } catch (CString p_lpException) { this ->MessageBox(p_lpException); } } }[/code] Es wird also über Open ein neues Objekt erstellt: [code]const CWordFile CWordFile:_open(const CString& p_lpSource) { if (!p_lpSource.IsEmpty()) { auto CString a_lpFile = (LPCTSTR) CFile(p_lpSource, CFile::modeRead | CFile::modeWrite | CFile::typeBinary).GetFilePath(); auto CWordFile a_oResult(a_lpFile); a_oResult.m_seMembers.m_seWordMembers.m_oeSpDispWord = CComDispatchDriver(CWordFile::s_m_seWordMembers.m_oeSpIWord); { auto DISPID a_dispidDocuments = 0; CWordFile::s_m_seWordMembers.m_oeHR = (a_oResult.m_seMembers.m_seWordMembers.m_oeSpDispWord) .GetIDOfName(L"Documents", &a_dispidDocuments); CWordFile::s_m_seWordMembers.m_oeHR = (a_oResult.m_seMembers.m_seWordMembers.m_oeSpDispWord) .GetProperty(a_dispidDocuments, &(CWordFile::s_m_seWordMembers.m_oevResult)); } a_oResult.m_seMembers.m_seWordMembers.m_oeSpDocuments = CComDispatchDriver( (CWordFile::s_m_seWordMembers.m_oevResult).pdispVal); if (SUCCEEDED(CWordFile::s_m_seWordMembers.m_oeHR) && (a_oResult.m_seMembers.m_seWordMembers.m_oeSpDocuments != NULL)) { auto VARIANT a_vFilename; a_vFilename.vt = VT_BSTR; a_vFilename.bstrVal = A2BSTR(a_lpFile); CWordFile::s_m_seWordMembers.m_oeHR = (a_oResult.m_seMembers.m_seWordMembers.m_oeSpDocuments) .Invoke1(L"Open", &a_vFilename, &(CWordFile::s_m_seWordMembers.m_oevResult)); SysFreeString(a_vFilename.bstrVal); a_oResult.m_seMembers.m_seWordMembers.m_oeSpDocument = NULL; { auto VARIANT a_vDocNummer; a_vDocNummer.vt = VT_I4; a_vDocNummer.lVal = 1; CWordFile::s_m_seWordMembers.m_oeHR = a_oResult.m_seMembers.m_seWordMembers.m_oeSpDocuments .Invoke1(L"Item", &a_vDocNummer, &(CWordFile::s_m_seWordMembers.m_oevResult)); a_oResult.m_seMembers.m_seWordMembers.m_oeSpDocuments = (CWordFile::s_m_seWordMembers.m_oevResult).pdispVal; } a_oResult.m_seMembers.m_seWordMembers.m_oeSpDispDokument = CComDispatchDriver(a_oResult.m_seMembers.m_seWordMembers.m_oeSpDocuments); } return a_oResult; } else { throw "Ungültiger Dateiname."; } } Problem ist nur, dass das lokale CWordFile-Objekt der Open-Methode nach Aufruf dieser zerstört wird (und damit auch die Zeiger in den CComDispatchDrivern). Ich habe zwar versucht diese via Kopierkonstruktor zu speichern: CWordFile::CWordFile(const CWordFile& p_oRhs):m_seMembers(p_oRhs.m_seMembers.m_lpeSource) { ++CWordFile::s_m_seWordMembers.m_neMemberCounter; (*(this -> m_seMembers.m_seWordMembers.m_oeSpDispDokument.p)) = (*(p_oRhs.m_seMembers.m_seWordMembers.m_oeSpDispDokument.p)); (*(this -> m_seMembers.m_seWordMembers.m_oeSpDispWord.p)) = (*(p_oRhs.m_seMembers.m_seWordMembers.m_oeSpDispWord.p)); (*(this -> m_seMembers.m_seWordMembers.m_oeSpDocuments.p)) = (*(p_oRhs.m_seMembers.m_seWordMembers.m_oeSpDocuments.p)); /*(this -> m_seMembers.m_seWordMembers.m_oeSpDispDokument) = CComDispatchDriver(p_oRhs.m_seMembers.m_seWordMembers.m_oeSpDispDokument.p); (this -> m_seMembers.m_seWordMembers.m_oeSpDispWord) = CComDispatchDriver(p_oRhs.m_seMembers.m_seWordMembers.m_oeSpDispWord.p); (this -> m_seMembers.m_seWordMembers.m_oeSpDocuments) = CComDispatchDriver(p_oRhs.m_seMembers.m_seWordMembers.m_oeSpDocuments.p);*/ } Aber das geht nicht, weil egal was ich mache diese Objekte beim Destruktor auf NULL gesetzt werden und damit hat die Funktion zum Setzen von Textmarken wenig sinn: void COutputDlg::s_m_setBookmarks(const CWordFile& p_oWordFile) { UpdateData(TRUE); auto CWordFile a_oWordFile = p_oWordFile; if (this ->m_oeMember.p_bHasUser()) { a_oWordFile.p_setBookMarkText(DOC_STI_FNAME, m_oeValOpStiFName); //a_oWordFile.p_setBookMarkText(..., m_oeValOpStiIdent); a_oWordFile.p_setBookMarkText(DOC_STI_SG, m_oeValOpStiSG); a_oWordFile.p_setBookMarkText(DOC_STI_SNAME, m_oeValOpStiSName); a_oWordFile.p_setBookMarkText(DOC_STI_TEL, m_oeValOpStiTel); } } , weil dann ein Verweis (in dem neuen Objekt) auf NULL an folgender Stelle steht: void CWordFile:_setBookMarkText(const CString& p_lpBookMarkName, const CString& p_lpBookMarkText) { auto IDispatchPtr a_oSpBookmarks = NULL; auto VARIANT a_ovResult; auto HRESULT a_lHR; this -> m_seMembers.m_seWordMembers.[B]m_oeSpDispDokument[/B].GetPropertyByName(L"Bookmarks", &a_ovResult);[COLOR="Red"] // <-- Da[/COLOR] a_oSpBookmarks = a_ovResult.pdispVal; auto CComDispatchDriver a_oSpDispBookmarks(a_oSpBookmarks); IDispatchPtr a_oSpBookmark = NULL; { auto VARIANT a_ovBkmName; a_ovBkmName.vt = VT_BSTR; a_ovBkmName.bstrVal = A2BSTR((LPCSTR) p_lpBookMarkName); a_oSpDispBookmarks.Invoke1(L"Item", &a_ovBkmName, &a_ovResult); SysFreeString(a_ovBkmName.bstrVal); a_oSpBookmark = a_ovResult.pdispVal; } if (a_oSpBookmark == NULL) { throw CString(CString(_T("Textmarke ")) + p_lpBookMarkName + CString(_T(" wurde nicht gefunden"))); } else { auto CComDispatchDriver a_oSpDispBookmark(a_oSpBookmark); auto IDispatchPtr a_oSpBmRange = NULL; { auto DISPID a_lDispidRange = 0; a_lHR = a_oSpDispBookmark.GetIDOfName(L"Range", &a_lDispidRange); a_lHR = a_oSpDispBookmark.GetProperty(a_lDispidRange, &a_ovResult); a_oSpBmRange = a_ovResult.pdispVal; } auto CComDispatchDriver a_oSpDispRange(a_oSpBmRange); { VARIANT a_ovNewText; a_ovNewText.vt = VT_BSTR; a_ovNewText.bstrVal = A2BSTR((LPCSTR) p_lpBookMarkText); auto DISPID a_lDispidText = 0; a_lHR = a_oSpDispRange.GetIDOfName(L"Text", &a_lDispidText); a_lHR = a_oSpDispRange.PutProperty(a_lDispidText, &a_ovNewText); SysFreeString(a_ovNewText.bstrVal); } } }[/code] Kann bei diesem Problem evtl. einer helfen ? Zitieren
Klotzkopp Geschrieben 26. Januar 2007 Geschrieben 26. Januar 2007 Ich habe echt Probleme, dem zu folgen. Könntest du den Code mal auf das Notwendigste reduzieren, oder ein Minimalbeispiel posten? Allgemein: CComDispatchDriver ist ein typedef von CComQIPtr. Es ist allgemein nicht sinnvoll, die Funktionalität von Smartpointern zu unterwandern und mit den darin enthaltenen rohen Zeigern zu hantieren. Dann hättest du dir den Smartpointer auch sparen können. Zitieren
TDM Geschrieben 30. Januar 2007 Autor Geschrieben 30. Januar 2007 ok 2. Versuch (hoffentlich wird es jetzt übersichtlicher ): Da ich die Datei noch Drucken will, hab ich mir so gedacht, dass ich die ja speichern müsste. Ergo: Member Ergo2: Problem mit den Pointern ist weg. Ergo3: Jedes Objekt macht ersteinmal eine eigene Wordschnittstelle: class CWordFile { public: void p_print(void); void p_save(const CString& p_lpPath); void p_setBookMarkText(const CString& p_lpBookMarkName, const CString& p_lpBookMarkText); CWordFile (const CString& p_lpSource); virtual ~CWordFile(); private: struct SValue_t { public: SValue_t(const CString& p_lpPath):m_seWordMembers(p_lpPath) { } CString m_lpeSource; struct SWValue_t { public: SWValue_t(const CString& p_lpPath); ~SWValue_t(); CComDispatchDriver m_oeSpDispDokument; CComDispatchDriver m_oeSpDocuments; IDispatchPtr m_oeSpDocument; HRESULT m_oeHR; VARIANT m_oevResult; CLSID m_oeCLSIDWordApplication; IDispatchPtr m_oeSpIWord; CComDispatchDriver m_oeSpDispWord; } m_seWordMembers; } m_seMembers; }; Zum Verständnis: Objekt wird über Konstruktor erzeugt; Konstruktor erzeugt Memberstruktur; Memberstruktur erzeugt Wordstruktur; Normaler Konstruktor: CWordFile::CWordFile(const CString& p_lpSource):m_seMembers(p_lpSource) { if (p_lpSource.IsEmpty()) { throw "Der Pfad zur Word-Datei ist leer."; } } (Wird vielleicht noch hübscher gemacht.) Der Übersichtlichkeit halber, habe ich noch ein paar Makros definiert: #define MP(p, v) (p.m_seMembers.v) #define MWP(p, v) (p.m_seMembers.m_seWordMembers.v) #define M(v) (this -> m_seMembers.v) #define _MW(v) (this -> m_seMembers.m_seWordMembers.v) #define MW(v) (this -> v) (Die Verweisen einfach auf die jeweilige Variable um Schreibarbeit zu ersparen.) Den Konstruktor der Wordmembers kürz ich mal: CWordFile::SValue_t::SWValue_t::SWValue_t(const CString& p_lpPath) { CoInitialize(NULL); MW(m_oeHR) = CLSIDFromProgID(L"Word.Application", &(MW(m_oeCLSIDWordApplication))); if (SUCCEEDED(MW(m_oeHR))) { MW(m_oeHR) = CoCreateInstance(MW(m_oeCLSIDWordApplication), NULL, CLSCTX_SERVER, IID_IDispatch, (void **) (IDispatch *) &(MW(m_oeSpIWord))); if (SUCCEEDED(MW(m_oeHR)) && (MW(m_oeSpIWord) != NULL)) { // weitere Initialisierungen (s.o.) } } else { CoUninitialize(); throw "Es ist kein MS-Word installiert."; } } So, nun das Problem - der Destruktor: CWordFile::SValue_t::SWValue_t::~SWValue_t() { auto VARIANT a_vArgsClose; a_vArgsClose.vt = VT_BOOL; a_vArgsClose.boolVal = FALSE; if (MW(m_oeSpDocuments) != NULL) { MW(m_oeHR) = MW(m_oeSpDocuments).Invoke1(L"Close", &a_vArgsClose, &(MW(m_oevResult))); } MW(m_oeHR) = MW(m_oeSpDispWord).Invoke0(L"Quit", &(MW(m_oevResult))); MW(m_oeSpIWord) -> ~IDispatch(); //= NULL; CoUninitialize(); } Problem an der Sache ist nun, dass nach dem Konstruktor in MASM der Destruktor von m_oeSpIWord aufgerufen wird. Damit ich aber alle anderen Interfaces befreie, muss ich das lt. Tut. vorher auf NULL setzen. NULL geht nicht, Destruktor geht nicht, delete geht auch nicht. Von NULL den Destruktor aufzufen ist bisschen sinnlos, deswegen bekommen ich da immer einen Access Error. Btw: Wenn jemand was damit anfangen kann: EAX = 00406C2E EBX = 00000000 ECX = 00000100 EDX = 00406C2E ESI = 00000000 EDI = 00000000 EIP = 00406C2E ESP = 0012ECFC EBP = 0012F554 EFL = 00000212 Thread 0xEA8 wurde mit Code 0 (0x0) beendet. Thread 0xE44 wurde mit Code 0 (0x0) beendet. Nicht abgefangene Ausnahme in BZR.exe (KERNEL32.DLL): 0x800706BF: (kein Name). Nicht abgefangene Ausnahme in BZR.exe: 0xC0000005: Access Violation. Nicht abgefangene Ausnahme in BZR.exe (KERNEL32.DLL): 0x800706BF: (kein Name). An sich ist das zwar kein Problem, da ich den Member durch expliziten Destruktoraufruf in einem Try-Block zerstöre (und damit nicht immer so ein blödes Fenster kommt), aber dennoch stört sowas. Url zum Tut.: Office Automation mit C++ oder Visual Basic Hoffe jetzt sieht man mehr durch. :/ Zitieren
Klotzkopp Geschrieben 30. Januar 2007 Geschrieben 30. Januar 2007 Hoffe jetzt sieht man mehr durch. :/Leider nein. Mir ist, ehrlich gesagt, selten so ein Kuddelmuddel untergekommen. Die Namensgebung der Variablen ist IMHO furchtbar. Ich bekomme schon einen Knoten im Hirn, wenn ich versuche, m_seWordMembers/m_seMembers oder SValue_t/SWValue_t auseinanderzuhalten. Schon die Suffixe "Value" und "Members" sind verwirrend, weil sie keine zusätzliche Informationen enthalten. Und mit den Makros hast du es IMHO noch schlimmer gemacht. Wenn man merkt, dass man viel zu viel tippt, dann sollte man die Klassenstruktur vereinfachen, und Funktionalität besser verkapseln, und nicht die wirre Struktur hinter noch weniger durchschaubaren Makros verstecken. Noch dazu sind die Makros so ähnlich, dass man sich anstrengen muss, um sie auseinander zu halten. Blickst du da selbst eigentlich noch durch? Und das hier#define MW(v) (this -> v)ist praktisch der Gipfel. Ich verstehe sowieso nicht, warum du "this->" benutzt, wenn du einen Memberpräfix verwendest. Schreib doch gleich v. Problem an der Sache ist nun, dass nach dem Konstruktor in MASM der Destruktor von m_oeSpIWord aufgerufen wird.Inwiefern ist das ein Problem? Dass der Destruktor eines Smartpointers aufgerufen wird, ist ein üblicher Vorgang, z.B. be Kopieroperationen. Damit ich aber alle anderen Interfaces befreie, muss ich das lt. Tut. vorher auf NULL setzen. NULL geht nicht, Destruktor geht nicht, delete geht auch nicht.Was heißt "geht nicht"? Der explizite Destruktoraufruf ist jedenfalls ein Fehler. Zitieren
TDM Geschrieben 30. Januar 2007 Autor Geschrieben 30. Januar 2007 Mir ist, ehrlich gesagt, selten so ein Kuddelmuddel untergekommen. Die Namensgebung der Variablen ist IMHO furchtbar. Ich bekomme schon einen Knoten im Hirn, wenn ich versuche, m_seWordMembers/m_seMembers oder SValue_t/SWValue_t auseinanderzuhalten. Schon die Suffixe "Value" und "Members" sind verwirrend, weil sie keine zusätzliche Informationen enthalten. Und mit den Makros hast du es IMHO noch schlimmer gemacht. Wenn man merkt, dass man viel zu viel tippt, dann sollte man die Klassenstruktur vereinfachen, und Funktionalität besser verkapseln, und nicht die wirre Struktur hinter noch weniger durchschaubaren Makros verstecken. Noch dazu sind die Makros so ähnlich, dass man sich anstrengen muss, um sie auseinander zu halten. Blickst du da selbst eigentlich noch durch? Natürlich seh ich durch die Variablenbezeichnung noch durch; Dateityp, Verwendungszweck und Name sind eigentlich (für mich) ausreichend erklärt. Für angewiesene Notationen/Strukturvorgaben kann ich aber nichts. Das mit dem Makro weiß ich, dass das besch...eiden ist, aber dafür sind es ja Makros die kann ich einfach ändern ohne jede Zeile im Quelltext anzupassen. Z.B. #define MW(v) v Inwiefern ist das ein Problem? Dass der Destruktor eines Smartpointers aufgerufen wird, ist ein üblicher Vorgang, z.B. be Kopieroperationen. Was heißt "geht nicht"? Der explizite Destruktoraufruf ist jedenfalls ein Fehler. Wie gesagt ist das Problem nach dem Destruktor: 116: CoUninitialize(); 0041193F 8B F4 mov esi,esp 00411941 FF 15 B8 FE 42 00 call dword ptr [__imp__CoUninitialize@0 (0042feb8)] 00411947 3B F4 cmp esi,esp 00411949 E8 D6 27 00 00 call _chkesp (00414124) 117: } 0041194E C6 45 FC 03 mov byte ptr [ebp-4],3 00411952 8B 4D F0 mov ecx,dword ptr [ebp-10h] 00411955 83 C1 34 add ecx,34h [COLOR="Red"];Hier...[/COLOR] 00411958 E8 2B FB FE FF call @ILT+1155(ATL::CComDispatchDriver::~CComDispatchDriver) (00401488) [COLOR="red"];... Verweis auf NULL -> Fehler[/COLOR] 0041195D C6 45 FC 02 mov byte ptr [ebp-4],2 00411961 8B 4D F0 mov ecx,dword ptr [ebp-10h] 00411964 83 C1 30 add ecx,30h 00411967 E8 9E F6 FE FF call @ILT+5(_com_ptr_t<_com_IIID<IDispatch,&_GUID_00020400_0000_0000_c000_000000000046> >::~_ 0041196C C6 45 FC 01 mov byte ptr [ebp-4],1 00411970 8B 4D F0 mov ecx,dword ptr [ebp-10h] 00411973 83 C1 08 add ecx,8 00411976 E8 8F F6 FE FF call @ILT+5(_com_ptr_t<_com_IIID<IDispatch,&_GUID_00020400_0000_0000_c000_000000000046> >::~_ 0041197B C6 45 FC 00 mov byte ptr [ebp-4],0 0041197F 8B 4D F0 mov ecx,dword ptr [ebp-10h] 00411982 83 C1 04 add ecx,4 00411985 E8 FE FA FE FF call @ILT+1155(ATL::CComDispatchDriver::~CComDispatchDriver) (00401488) 0041198A C7 45 FC FF FF FF FF mov dword ptr [ebp-4],0FFFFFFFFh 00411991 8B 4D F0 mov ecx,dword ptr [ebp-10h] 00411994 E8 EF FA FE FF call @ILT+1155(ATL::CComDispatchDriver::~CComDispatchDriver) (00401488) 00411999 8B 4D F4 mov ecx,dword ptr [ebp-0Ch] 0041199C 64 89 0D 00 00 00 00 mov dword ptr fs:[0],ecx 004119A3 5F pop edi 004119A4 5E pop esi 004119A5 5B pop ebx 004119A6 83 C4 60 add esp,60h 004119A9 3B EC cmp ebp,esp 004119AB E8 74 27 00 00 call _chkesp (00414124) 004119B0 8B E5 mov esp,ebp 004119B2 5D pop ebp 004119B3 C3 ret Deswegen habe ich den Destruktor auch in den try-block gepackt. Ich weiß, dass das Mist ist, aber da wird zumindest nicht das Fenster von wegen "Blabla.exe hat eine internen Fehler ausgelößt, möchten Sie dieses Problem melden?" angezeigt... Sobald das Problem weg ist, wird zumindest dieser Hack entfernt...:floet: Zitieren
Bubble Geschrieben 30. Januar 2007 Geschrieben 30. Januar 2007 Und mit den Makros hast du es IMHO noch schlimmer gemacht. Der Ansicht möchte ich mich anschließen. Und vielleicht noch hinzufügen, dass man mit Präfixen auch sparsamer umgehen kann "auto" ist überflüssig, dass ist der Default. Wie oft rufst Du CoInitialize pro Thread aus? Pro erstelltem Object? 1x pro Thread würde reichen. MW(m_oeSpIWord) -> ~IDispatch(); //= NULL; Du willst den destructor manuell aufrufen? :eek Warum? Du solltest den Code übersichtlicher gestallten und die Bezeichner aussagekräftiger wählen. Notfalls komplett neu schreiben. Das hilft auch bei der Fehlersuche. Zitieren
TDM Geschrieben 31. Januar 2007 Autor Geschrieben 31. Januar 2007 So... Ich habe es geschafft, meinen Auftraggeber von der Notation und Struktur abzubringen. Deswegen habe ich auch jetzt das nicht mehr alles in eine Klasse geschrieben und siehe da - es geht. Als Beispiel mal die Klasse _Application (für Word selber) Documents und _Document: class _Application : public COleDispatchDriver { public: _Application() {} _Application(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {} _Application(const _Application& dispatchSrc) : COleDispatchDriver(dispatchSrc) {} public: public: LPDISPATCH GetApplication(); long GetCreator(); LPDISPATCH GetParent(); CString GetName(); LPDISPATCH GetDocuments(); //... }; class Documents : public COleDispatchDriver { public: Documents() {} Documents(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {} Documents(const Documents& dispatchSrc) : COleDispatchDriver(dispatchSrc) {} public: public: LPUNKNOWN Get_NewEnum(); long GetCount(); LPDISPATCH GetApplication(); long GetCreator(); LPDISPATCH GetParent(); LPDISPATCH Item(VARIANT* Index); void Close(VARIANT* SaveChanges, VARIANT* OriginalFormat, VARIANT* RouteDocument); LPDISPATCH Add(VARIANT* Template, VARIANT* NewTemplate); LPDISPATCH Open(VARIANT* FileName, VARIANT* ConfirmConversions, VARIANT* ReadOnly, VARIANT* AddToRecentFiles, VARIANT* PasswordDocument, VARIANT* PasswordTemplate, VARIANT* Revert, VARIANT* WritePasswordDocument, VARIANT* WritePasswordTemplate, VARIANT* Format); void Save(VARIANT* NoPrompt, VARIANT* OriginalFormat); }; class _Document : public COleDispatchDriver { public: _Document() {} _Document(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {} _Document(const _Document& dispatchSrc) : COleDispatchDriver(dispatchSrc) {} // Attributes public: // Operations public: CString GetName(); LPDISPATCH GetApplication(); long GetCreator(); LPDISPATCH GetParent(); LPDISPATCH GetBuiltInDocumentProperties(); LPDISPATCH GetCustomDocumentProperties(); CString GetPath(); LPDISPATCH GetBookmarks(); LPDISPATCH GetTables(); LPDISPATCH GetFootnotes(); LPDISPATCH GetEndnotes(); LPDISPATCH GetComments(); long GetType(); BOOL GetAutoHyphenation(); void SetAutoHyphenation(BOOL bNewValue); BOOL GetHyphenateCaps(); void SetHyphenateCaps(BOOL bNewValue); long GetHyphenationZone(); void SetHyphenationZone(long nNewValue); long GetConsecutiveHyphensLimit(); void SetConsecutiveHyphensLimit(long nNewValue); LPDISPATCH GetSections(); LPDISPATCH GetParagraphs(); LPDISPATCH GetWords(); LPDISPATCH GetSentences(); LPDISPATCH GetCharacters(); LPDISPATCH GetFields(); LPDISPATCH GetFormFields(); LPDISPATCH GetStyles(); LPDISPATCH GetFrames(); LPDISPATCH GetTablesOfFigures(); LPDISPATCH GetVariables(); LPDISPATCH GetMailMerge(); LPDISPATCH GetEnvelope(); }; Alle Methoden rufen ansich eigentlich immer nur die InvokeHelper-Methode mit unterschiedlichen Parametern auf. Jetzt muss ich ja "nur" noch was für die Bookmarks ect. schreiben. :beagolisc Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.