Namen der COM-Befehle von MS Word



  • Hallo,

    ich bin ein wenig ratlos beim Schreiben einer Ansteuerung für Word über die COM-Komponente (Interface IDispatch).

    Als Grundlage verwende ich die Wrapperklassen von Microsoft, die es bei Jochen Kalmbach runterzuladen gibt, um den Code zu vereinfachen ( http://blog.kalmbachnet.de/?postid=63 ).

    Jedoch scheinen die Funktionsaufrufe für Word aus der TypeLibrary (msword.olb) und von Visual Basic nicht gleich der Befehle von der Wrapperklasse zu sein.

    Z.B. ist der Befehl fürs Suchen von Wörtern in C++ hier dann "EditFind" und nicht "Selection.Find", wie es in der Type-Library angegeben ist.

    Also statt

    VARAINT vSelection;
    Invoke(pdispWord, DISPATCH_METHOD, NULL, NULL, NULL, OLESTR("Selection"), TEXT(""), NULL, (VARIANT FAR*)&vSelection);
    

    funktioniert nur

    BSTR b_searchString = ::SysAllocString(OLESTR("Wort"));
    Invoke(pdispWord, DISPATCH_METHOD, NULL, NULL, NULL, OLESTR("EditFind"), Text("s), b_searchString);
    

    und zwar von dieser Befehlsübersicht: www.wbrnet.info/db/5301.html
    Das gleich passierte mir auch mit dem Befehl "FilePrint" aus der Übersicht und dem eigentlichen Befehl "PrintOut" aus der TypeLibrary.

    Allerdings fehlen mir die Parameterangaben, was das Implementieren etwas mühselig macht, da ich keine Fehlerausgabe habe.

    Hätte jemand eine Idee, wo es eine solche Übersicht gibt bzw. wie ich doch die "echten" Visual-Basic-Befehle aus der Type-Library übernehmen kann oder auch Beispiele dafür?

    Viele Grüße,

    Tobias


  • Mod

    Ich glaube Du verwechselst die Dialoge mit den VB Befehlen!
    Geh doch in den Makro-Editor von Word.
    IMHO findest Du da die identischen Namen.



  • Danke schon mal für die Antwort.
    Ich glaube, ich habe die falsche Bibliothek verwendet. Und zwar habe ich

    CreateObject(OLESTR("Word.Basic"), &m_pdispWord);
    

    statt

    CreateObject(OLESTR("Word.Application"), &m_pdispWord);
    

    verwendet.

    Eine Frage noch zum Verständnis der Type-Lib:

    Wenn ich z.B. eine Word-Instanz sichtbar machen will, habe ich aus der TypeLib den Befehl

    HRESULT Visible([in] VARIANT_BOOL prop);
    

    .
    Wie rufe ich den Befehl dann mit Invoke korrekt auf?
    Etwa so?

    Invoke(m_pdispWord, DISPATCH_PROPERTYGET, NULL, NULL, NULL, OLESTR("Visible"), TEXT("b&bVisible"), bVisible, NULL)
    

    .

    Leider kriege ich da nur eine schöne Absturzmeldung.

    Gruß,

    Tobias



  • Sir_Tobias schrieb:

    TEXT("b&bVisible")
    

    Du willst aber *viele* Parameter übergeben! Lies nochmals die Doku zu "Invoke" 😉



  • @Jochen:

    Vielen Dank für den Tip, also werden nur die Typen übergeben und nicht die Namen. Also so dann:

    OLESTR("Visible"), TEXT("b"), vVisible))
    

    Was für mich noch nicht ganz klar ist:

    Aus der Type-Lib will ich z.B. die Funktion

    HRESULT OpenOld(
                    [in] VARIANT* FileName, 
                    [in, optional] VARIANT* ConfirmConversions, 
                    [in, optional] VARIANT* ReadOnly, 
                    [in, optional] VARIANT* AddToRecentFiles, 
                    [in, optional] VARIANT* PasswordDocument, 
                    [in, optional] VARIANT* PasswordTemplate, 
                    [in, optional] VARIANT* Revert, 
                    [in, optional] VARIANT* WritePasswordDocument, 
                    [in, optional] VARIANT* WritePasswordTemplate, 
                    [in, optional] VARIANT* Format, 
                    [out, retval] Document** prop);
    

    verwenden.

    1. Wie kann ich die optionalen Parameter auslassen oder müssen immer alle belegt sein?
    2. Wenn ich den Rückgabewert, also die Properties des Dokuments speichern möchte, welcher Datentyp ist da zu verwenden. Document** geht ja schlecht?!

    Gruß,

    Tobias



  • Sir_Tobias schrieb:

    1. Wie kann ich die optionalen Parameter auslassen oder müssen immer alle belegt sein?

    Bist Du Dir sicher, dass die Parameter jeweils ein "VARIANT*" (mit Stern!) sind? Ich hätte jetzt alle ohne Stern vermutet.
    Optionale-Parameter übergibt man in einem Variant mit dem Typ "VT_ERROR" und dem Code "DISP_E_PARAMNOTFOUND".
    Also z.B: so:

    VARIANT m;  // Missing parameter
    VariantInit(&m);
    V_VT(&m) = VT_ERROR;
    V_ERROR(&missing) = DISP_E_PARAMNOTFOUND;
    Invoke(m_pdispWord, DISPATCH_METHOD, NULL, NULL, NULL, 
      OLESTR("OpenOld"), 
      TEXT("vvvvvvvvvv&D"), 
      vFileName, 
      m, m, m, m, m, m, m, m, m,
      &pDoc,
      NULL)
    VariantClear(&m);
    

    Hab es aber nicht wirklich probiert...

    Sir_Tobias schrieb:

    2. Wenn ich den Rückgabewert, also die Properties des Dokuments speichern möchte, welcher Datentyp ist da zu verwenden. Document** geht ja schlecht?!

    IDispatch



  • Hallo,

    vielen Dank für die Tips. Welchen Unterschied macht es eigentlich, den VARIANT-Typ als Safe-Array ("v") oder gleich den enthaltenden Typ mit anzugeben ("seeee")?

    Wenn der Aufruf nicht klappt, gibt es laut MSDN die Möglichkeit, sich eine Fehlermeldung ausgeben zu lassen, die ich ja folgendermaßen aufrufen kann:

    EXCEPINFO getExcepInfo;
    if ((FAILED(Invoke(m_pdispWord, DISPATCH_METHOD, &returnVal, &getExcepInfo, NULL, OLESTR("OpenOld"), TEXT("vvvvvvvvvv&D"), 
    vFileName, vError, vError, vError, vError, vError, vError, vError, vError, vError, &pDoc))) {
    BSTR bstr_Fehler = getExcepInfo.bstrSource;
    

    Wie kann man diese Fehlermeldung sinnvoll ausgeben lassen?

    Gruß,

    Tobias


  • Mod

    Sir_Tobias schrieb:

    vielen Dank für die Tips. Welchen Unterschied macht es eigentlich, den VARIANT-Typ als Safe-Array ("v") oder gleich den enthaltenden Typ mit anzugeben ("seeee")?

    Weil es die Schnittstelle so beschriebt. Bitte lies doch mal die Doku wie Jochen es Dir gesagt hat.
    Das Problem ist nämlich: Machst Du es richtig funktioniert es, machst Du es falsch geht es nicht! 😉



  • Hallo,

    vielen Dank für die ausführliche Hilfe, habe es soweit hinbekommen:

    Eine kleine Frage hätte ich allerdings noch:

    Ich möchte gerne Konstanten aus der Typelib statt reine Zahlen verwenden, um möglichst die Kompatibilität zwischen den Office-Versionen zu wahren. Z.B. diese hier:

    typedef enum {
        wdFindStop = 0,
        wdFindContinue = 1,
        wdFindAsk = 2
    } WdFindWrap;
    

    Wie greife ich darauf zu? Geht das überhaupt mit Invoke(...)?

    Vielen Dank schon mal.

    Gruß,

    Tobias


  • Mod

    Das hat nichts mit Invoke zu tun, sondern dem importieren der TypeLib. Du benötigst die entsprechende Header Datei. Hier werden keine symbolischen Namen übergeben sondenr Zahlen!



  • Hallo,

    vielen Dank für den Hinweis. Aber wenn ich die Typelib (z.B. msword.olb) direkt importiere, klappt es doch mit anderen Office-Versionen nicht mehr, oder?

    Gruß,

    Tobias


  • Mod

    Sir_Tobias schrieb:

    vielen Dank für den Hinweis. Aber wenn ich die Typelib (z.B. msword.olb) direkt importiere, klappt es doch mit anderen Office-Versionen nicht mehr, oder?

    Wieso? Du verwendest doch die Wrapper und DispIDS nicht. Du verwendest doch nur die enum's.



  • Importiere doch die TLB _einmal_ und kopiere dir die "versteckten" Dateien und nimm daraus dann die enums 😉


Anmelden zum Antworten