Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Weired QAX setProperty() behavior
QtWS25 Last Chance

Weired QAX setProperty() behavior

Scheduled Pinned Locked Moved Unsolved General and Desktop
qaxobjectdumpcpp
8 Posts 2 Posters 3.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    diverger
    wrote on 7 Jul 2016, 11:03 last edited by diverger 7 Jul 2016, 11:10
    #1

    I use Qt's dumpcpp tool dump the msword.olb to cpp files. There is one method dumped as

    inline void Paragraph::SetWidowControl(int value){ setProperty("WidowControl", QVariant(value)); }
    

    And in my code, I tried three different ways

    1. Invoke the method with "SetWidowControl(true)", don't work, and the debug shows:

       QAxBase: Error calling IDispatch member WidowControl: Unknown error
      
    2. Invoke "setProperty("WidowControl", true)" directly, show the same error message (as it's basically same with case 1).

    3. Invoke "dynamicCall("SetWidowControl(bool)", true)", no error message showed and all are OK.

    I've two questions:

    1. Why 1 and 2 not work? I think they are the 'normal' methods, but they don't work.
    2. According to: Paragraph.WidowControl property. It doesn't mentioned there is a method "SetWidowControl" and the dumpcpp tool didn't dump one. So, why case 3 works? I'm not familiar with COM tech, so what Qt's 'setProperty' does? I guess it must use similar ways as 'dynamicCall()' to direct MSWord to do something.

    My toolchain is Qt 5.7.0 and VS2015, and the word edition is office365 (office 2016).

    1 Reply Last reply
    0
    • H Online
      H Online
      hskoglund
      wrote on 7 Jul 2016, 21:45 last edited by
      #2

      Hi, the reason #3 flavor works but not #1 and #2 I think occurs because you don't have the correct COM interface instantiated in your QAxBase class. If you check the control property of that class does it say IDispatch or Paragraph?

      It's usually easier (and slower) to call using dynamicCall() to call into COM.
      You can call directly (e.g. ... ->SetWindowControl(true); but then you have to set that Control property first. (It's a bit like comparing virtual calls or normal function calls in C++).

      D 1 Reply Last reply 8 Jul 2016, 03:18
      0
      • H hskoglund
        7 Jul 2016, 21:45

        Hi, the reason #3 flavor works but not #1 and #2 I think occurs because you don't have the correct COM interface instantiated in your QAxBase class. If you check the control property of that class does it say IDispatch or Paragraph?

        It's usually easier (and slower) to call using dynamicCall() to call into COM.
        You can call directly (e.g. ... ->SetWindowControl(true); but then you have to set that Control property first. (It's a bit like comparing virtual calls or normal function calls in C++).

        D Offline
        D Offline
        diverger
        wrote on 8 Jul 2016, 03:18 last edited by
        #3

        @hskoglund Thanks for your reply. The word.h and word.cpp are dumpped using command line "dumpcpp msword.olb". The tool automatically generates the classes with methods.

        class WORD_EXPORT Paragraphs : public QAxObject
        {
        public:
            Paragraphs(IDispatch *subobject = 0, QAxObject *parent = 0)
             : QAxObject((IUnknown*)subobject, parent)
           {
               internalRelease();
           }
           .........
           inline int WidowControl() const; //Returns the value of WidowControl
           inline void SetWidowControl(int value); //Sets the value of the WidowControl property
           ..........
        }
        

        Can you give me more informations about where the property defined?

        1 Reply Last reply
        0
        • H Online
          H Online
          hskoglund
          wrote on 8 Jul 2016, 11:20 last edited by
          #4

          Hi, I think the properties are mostly used from Visual Basic and C# and SetWidowControl() function are used from C++

          I also have dumpcpp.exe and msword.olb somewhere in my computer, I can make a simple demo/test program using method #1 (or #2) later tonight if you need.

          D 1 Reply Last reply 8 Jul 2016, 11:29
          0
          • H hskoglund
            8 Jul 2016, 11:20

            Hi, I think the properties are mostly used from Visual Basic and C# and SetWidowControl() function are used from C++

            I also have dumpcpp.exe and msword.olb somewhere in my computer, I can make a simple demo/test program using method #1 (or #2) later tonight if you need.

            D Offline
            D Offline
            diverger
            wrote on 8 Jul 2016, 11:29 last edited by diverger 7 Aug 2016, 11:37
            #5

            @hskoglund I'm really appreciated if you can have try it for me :). Now I'm not if it's Qt's bug or MS's bug. And I find that Qt's method accept a 'int', it seems MS use 'bool', can this be the reason?

            BTW, Qt's dumpcpp is not perfect yet, when generating the method, it sometimes omit the class qualifier with the first parameter. such as it generate 'Range' instead of 'Word::Range', so you may need manually add 'Word::' to them :(. Maybe a brute 'using namespace Word;' should work too.

            1 Reply Last reply
            0
            • H Online
              H Online
              hskoglund
              wrote on 9 Jul 2016, 10:31 last edited by
              #6

              Hi, yesterday I tested running dumpcpp on the msword.olb on my computer (I have Office 2010 installed). Sure enough I got a word.cpp and word.h but the generated .cpp file was 60 MB! When I tried to compile in using Qt 5.7+MSVC2015 I got errors on stuff like ListTemplate and Range :-(
              And trying to edit that 60 MB word.cpp file ---> Qt Creator crashes..
              So I spent some time splitting in up and getting it compile cleanly. But try as I might, I could only get #2 and #3 not #1 (which I think is the superior one).
              Finally I realized that the dumpcpp program had maybe misparsed something in that huge msword.olb. Since the object model for Office has been more or less the same the last 20 years, if I could find an older version of Office perhaps that msword.olb would be a better match for dumpcpp. On my old portable I had Office 2003, run dumpcpp and voila a word.cpp only 30 MB (a midget), and most important no errors when compiling :-) You have Office 2016 perhaps that msword.olb also gives better word.cpp and word.h files? Anyway, I think it doesn't matter what version of Office you use, as long as the compilation runs ok.

              I'll post now 2 versions of my test program, one using dynamic calls (or rather the usual querySubObject() flavor and the other using more fancy C++ direct calls.

              1 Reply Last reply
              0
              • H Online
                H Online
                hskoglund
                wrote on 9 Jul 2016, 10:40 last edited by hskoglund 7 Sept 2016, 10:42
                #7

                First version: create a vanilla Qt widgets app, in the .pro file insert "axcontainer" after "...gui" on the top line.

                Then in mainwindow.cpp, insert "#include qaxobject.h" at the top and
                after ui->setupUi(this); insert:

                    auto wApp = new QAxObject("Word.Application");
                    if (nullptr == wApp) return;
                    wApp->setProperty("Visible",true);
                    auto doc = wApp->querySubObject("Documents")->querySubObject("Add()");
                
                    for (int p = 0; (p < 100); ++p)
                    {
                        auto para = doc->querySubObject("Content")->querySubObject("Paragraphs")->querySubObject("Add()");
                
                        para->querySubObject("Range")->setProperty("Text","Four score and seven years ago our fathers "
                        "brought forth on this continent a new nation, conceived in liberty, and dedicated to the "
                        "proposition that all men are created equal.");
                        para->querySubObject("Format")->setProperty("SpaceAfter",20);
                
                        para->setProperty("WidowControl",-1);   // for true
                //     para->setProperty("WidowControl",0);    // for false
                
                        para->querySubObject("Range")->querySubObject("InsertParagraphAfter()");
                    }
                

                This is the style I think 99% of QAxObject programs are written.

                Advantages: you don't need to run dumpcpp and you don't need to include any humongous word.* files in your project.

                Disadvantage: just like JS, no compile time checks, surprises can await you when you start the program.

                1 Reply Last reply
                0
                • H Online
                  H Online
                  hskoglund
                  wrote on 9 Jul 2016, 10:52 last edited by
                  #8

                  2nd version, a bit more fancy, requiring you to run dumpcpp to get 2 files: word.cpp and word.h. Create a vanilla widget app, insert " axcontainer" in the .pro file (same as above). Add word.cpp into your project (so it wil compiled along with main.cpp and mainwindow.cpp.

                  Then in mainwindow.cpp insert "#include word.h" at the top, and after ui->setupUi(this); insert:

                      auto wApp = new Word::Application;
                      if (nullptr == wApp) return;
                      wApp->SetVisible(true);
                      auto doc = wApp->Documents()->Add();
                  
                      for (int p = 0; (p < 100); ++p)
                      {
                          auto para= doc->Content()->Paragraphs()->Add();
                  
                          para->Range()->SetText("Four score and seven years ago our fathers "
                          "brought forth on this continent a new nation, conceived in liberty, and dedicated to the "
                          "proposition that all men are created equal. Now we are engaged in a great civil war, "
                          "testing whether that nation, or any nation so conceived and so dedicated, can long endure.");
                          para->Format()->SetSpaceAfter(20);
                  
                          para->SetWidowControl(0);    // for false
                  //     para->setWidowControl(-1);   // for true
                  
                          para->Range()->InsertParagraphAfter();
                      }
                  

                  These calls will be changed to dynamic calls inside word.h but it's nice to have command completions and syntax checking by the compiler.

                  Note: when dealing with COM, thanks to it being used first by Visual Basic and VBA for Office, it's sometimes problems with the boolean chaps true and false, so I prefer to use 0 for false and -1 for true, same as in the Visual Basic.

                  1 Reply Last reply
                  0

                  8/8

                  9 Jul 2016, 10:52

                  • Login

                  • Login or register to search.
                  8 out of 8
                  • First post
                    8/8
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved