Loading ...
Sorry, an error occurred while loading the content.

Re: A SysListView32 control with multiple columns

Expand Messages
  • Dennis K. Paulsen
    This issue will need to be looked at. If you have a moment to document it at http://sourceforge.net/projects/winguitest, please do so. As far as SysHeader32,
    Message 1 of 13 , Apr 29, 2005
    • 0 Attachment
      This issue will need to be looked at. If you have a moment to
      document it at http://sourceforge.net/projects/winguitest, please do
      so. As far as SysHeader32, it should be a walk-in-the-park, time
      permitting; which it hasn't been for me as of late.


      Regards,
      Dennis

      --- In perlguitest@yahoogroups.com, "mustard99122"
      <dale_bertrand@y...> wrote:
      >
      >
      >
      > I'm having a problem getting the contents of a SysListView32 with
      > multiple columns using GetListViewContents. I noticed that a few
      > other people are also having problems. Is this feature on anyone's
      > todo list? It would be well worth my time to implement this feature,
      > but don't have any experience with the Windows API.
      >
      > Has anyone had any luck getting data from the SysHeader32 control?
      >
      > Anyone have a work-around?
      >
      > Thanks for the great tool!
      >
      > - Dale
    • denishowe
      In perlguitest@yahoogroups.com, mustard99122 ... In guitest.xs: ListView_GetItemText(g_hWnd, iItem, 0, g_szBuffer, MAX_DATA_BUF); the 0 selects the first
      Message 2 of 13 , Sep 29, 2005
      • 0 Attachment
        In perlguitest@yahoogroups.com, "mustard99122"
        <dale_bertrand@y...> wrote:
        > I'm having a problem getting the contents of a SysListView32
        > with multiple columns using GetListViewContents.

        In guitest.xs:

        ListView_GetItemText(g_hWnd, iItem, 0, g_szBuffer, MAX_DATA_BUF);

        the "0" selects the first column. It looks like it should be possible
        to extend GetListViewContents() to collect values from all the columns
        and return the contents as a list of lists.

        If I was to do this, what would I do with the patch or should I try to
        get set up for CVS access to SourceForge?
      • Piotr Kaluski
        ... to ... The best way would be if you take the most recent files from CVS (Instructions how to do it are here: https://sourceforge.net/cvs/?group_id=104592)
        Message 3 of 13 , Sep 29, 2005
        • 0 Attachment
          >
          > If I was to do this, what would I do with the patch or should I try
          to
          > get set up for CVS access to SourceForge?

          The best way would be if you take the most recent files from CVS
          (Instructions how to do it are here:
          https://sourceforge.net/cvs/?group_id=104592) and apply your changes
          there and than send me a patch. Note that after getting the files
          from
          CVS, you have to remove build.pl file (yes: REMOVE). Otherwise the
          code
          will not build.
          Please send a patch directly to me. Yahoo eats some spaces when
          displaying posts and "patch" program gets confused.
          Eventualy, if you really can't make cvs work for you, you can modify
          whatever file version you have and send it to me. Again - to me
          directly. Or even better - post changes in the group and send it to
          me
          directly (so people will have an opportunity to comment).

          -Piotr
        • denishowe
          Firstly, thanks to Piotr and co for their magnificent work on Win32::GuiTest. I gave up trying to get cvsnt to connect to SourceForge via sockscap. I ve been
          Message 4 of 13 , Oct 3, 2005
          • 0 Attachment
            Firstly, thanks to Piotr and co for their magnificent work on
            Win32::GuiTest.

            I gave up trying to get cvsnt to connect to SourceForge via sockscap.

            I've been playing with the XS code (my first attempt at this sort of
            thing). I succeeded in reading all the items and subitems out of a
            multi-column ListView control, but only by a couple of gross hacks:

            sub GetListViewContents
            {
            my $window = shift;
            my @res;
            my $item_count = GetListViewItemCount($window);
            for my $item_index (0..$item_count-1)
            {
            my $subitem_index = 0;
            my @item;
            while ($subitem_index < 10)
            {
            my $subitem = GetListViewItem(
            $window, $item_index << 16 | $subitem_index);
            push @item, $subitem;
            $subitem_index++;
            }
            push @res, \@item;
            $item_index++;
            }
            return @res;
            }

            Note that I always collect ten columns. Also note that I'm packing
            the item and subitem indexes into a single arg rather than trying to
            marshal multiple args through SendMessage.

            I exposed GetLVItemText(), passing through the item/subitem arg:

            SV*
            GetListViewItem(hWnd, iItem)
            HWND hWnd
            int iItem
            CODE:
            char szItem[MAX_DATA_BUF+1] = "";
            GetLVItemText(hWnd, iItem, szItem);
            RETVAL = newSVpv(szItem, 0);
            OUTPUT:
            RETVAL

            And I exposed GetLVItemCount():

            int
            GetListViewItemCount(hWnd)
            HWND hWnd
            CODE:
            RETVAL = GetLVItemCount(hWnd);
            OUTPUT:
            RETVAL

            HookProc unhacks the WM_LV_GETTEXT message like this:

            if (pCW->message == WM_LV_GETTEXT) {
            *g_szBuffer = NUL;
            int iItem = pCW->wParam;
            int iSubItem = iItem & 0xFFFF;
            iItem >>= 16;
            ListView_GetItemText(g_hWnd, iItem, iSubItem, g_szBuffer,
            MAX_DATA_BUF);
            UnhookWindowsHookEx(g_hHook);
            } else ...

            All of this sort of assumes the ListView is in "Detail" mode (in which
            it can have multiple columns and a header).

            I found an easy way to get the count of columns for ListView handle
            $lv:

            use Win32::GUI;
            my $header = Win32::GUI::ListView::GetHeader($lv);
            my $n_cols = Win32::GUI::Header::GetItemCount($header);

            Which makes me wonder how much of Win32::GUI it is desirable to
            duplicate into GuiTest. It would be better to move FindWindowLike(),
            SendKeys(), and the other things that are unique to GuiTest, into GUI
            and scrap GuiTest rather than slowly and painfully copying lots of
            functions the other way.
          • Piotr Kaluski
            ... That s really nice to read. However, the foundation of module was created by Ernesto Guisado and then extented by Dennis Paulsen and Gabor Szabo. I have
            Message 5 of 13 , Oct 3, 2005
            • 0 Attachment
              --- In perlguitest@yahoogroups.com, "denishowe" <dbh@d...> wrote:
              > Firstly, thanks to Piotr and co for their magnificent work on
              > Win32::GuiTest.
              >

              That's really nice to read. However, the foundation of module was
              created by Ernesto Guisado and then extented by Dennis Paulsen and
              Gabor Szabo. I have only made few recent changes.

              As for the remaining part of your post I need some to digest it.

              -Piotr
            • Piotr Kaluski
              Denis, I totally understand your point. However, I think there are some subtle differences between Win32::GUI and Win32::GuiTest. Win32::GUI is a perl wrapper
              Message 6 of 13 , Oct 4, 2005
              • 0 Attachment
                Denis,
                I totally understand your point. However, I think there are some
                subtle differences between Win32::GUI and Win32::GuiTest.
                Win32::GUI is a perl wrapper around user32.dll and gdi32.dll. It is
                basically a perl OO library for writing Win GUI applications. Most of
                this library's methods assume that controls and windows they operate
                are owned by the same process, which calls those methods. This is
                different for Win32::GuiTest. Its functions assume that controls and
                windows they operate are hosted by a different process. It does not
                matter for basic controls, but it does matter for more advanced
                controls like ListView.
                Calls to Win32::GUI::ListView::GetHeader() and
                Win32::GUI::Header::GetItemCount() worked because those functions
                send and return numbers. But I expect that you will get application
                crashes if you will try to retrieve/add items to the list using
                Win32::GUI methods. This is why Dennis Paulsen had to adopt hooking
                for simple ListView operations. This is why I implemented Virtual
                Memory functions. Have a look at a more detailed explanation:
                http://www.piotrkaluski.com/files/winguitest/docs/ch02s04.html.

                -Piotr


                >
                > I found an easy way to get the count of columns for ListView handle
                > $lv:
                >
                > use Win32::GUI;
                > my $header = Win32::GUI::ListView::GetHeader($lv);
                > my $n_cols = Win32::GUI::Header::GetItemCount($header);
                >
                > Which makes me wonder how much of Win32::GUI it is desirable to
                > duplicate into GuiTest. It would be better to move FindWindowLike
                (),
                > SendKeys(), and the other things that are unique to GuiTest, into
                GUI
                > and scrap GuiTest rather than slowly and painfully copying lots of
                > functions the other way.
              • denishowe
                ... You re right of course. When Win32::GUI tried to get the text of a ListView item the program under test blew up, just as you explain in your tutorial.
                Message 7 of 13 , Oct 4, 2005
                • 0 Attachment
                  In perlguitest@yahoogroups.com, "Piotr Kaluski" <pkaluski@p...> wrote:
                  > Win32::GuiTest...functions assume that controls and
                  > windows they operate are hosted by a different process.
                  > It does not matter for basic controls, but it does
                  > matter for more advanced controls like ListView.

                  You're right of course. When Win32::GUI tried to get the text of a
                  ListView item the program under test blew up, just as you explain in
                  your tutorial.

                  Couldn't one still merge Win32::GuiTest into Win32::GUI if certain GUI
                  functions used the message-hook trick for controls in other processes?
                  How tricky would that be?
                • Piotr Kaluski
                  Well, first of all it is not our decision. The idea has to be accepted by Win::GUI development team. Apart from this, I am not sure there is someone who would
                  Message 8 of 13 , Oct 4, 2005
                  • 0 Attachment
                    Well, first of all it is not our decision. The idea has to be accepted
                    by Win::GUI development team. Apart from this, I am not sure there is
                    someone who would actually have time to do it. Win32::GuiTest is a kind
                    of procedural API, whereas Win32::GUI is a an object oriented library.
                    So we can't just copy and paste the code.
                    There is a space for discussion on this merge. Especially from
                    design/phylosophy point of view. But whatever would be a conclusion,
                    the hard facts are that there are no resources to code it (not that I
                    know of). However, if it occurs that there is a strong will to do that
                    and a strong commitment to do the actuall work, I would be happy to
                    help.
                    -Piotr

                    >
                    > Couldn't one still merge Win32::GuiTest into Win32::GUI if certain
                    GUI
                    > functions used the message-hook trick for controls in other
                    processes?
                    > How tricky would that be?
                  • Piotr Kaluski
                    Hi, I just had a closer look on Win32::GUI. Boy, that s impressive what those guys did. They wrapped many, many useful Win32 API functions. So we should
                    Message 9 of 13 , Oct 6, 2005
                    • 0 Attachment
                      Hi,
                      I just had a closer look on Win32::GUI. Boy, that's impressive what
                      those guys did. They wrapped many, many useful Win32 API functions.
                      So we should definitely have a closer look at this module. For some
                      functions, there would be this interprocess boundaries problem. But
                      there is quite a lot of functions, which can be used already.
                      The only problem I see right now is that Win32::GUI is object
                      oriented and it assumes, that you create windows and controls. I did
                      not find a function allowing to attach to existing window created by
                      some other process (which does not mean that such a functions does
                      not exist).

                      --Piotr

                      --- In perlguitest@yahoogroups.com, "Piotr Kaluski" <pkaluski@p...>
                      wrote:
                      > Well, first of all it is not our decision. The idea has to be
                      accepted
                      > by Win::GUI development team. Apart from this, I am not sure there
                      is
                      > someone who would actually have time to do it. Win32::GuiTest is a
                      kind
                      > of procedural API, whereas Win32::GUI is a an object oriented
                      library.
                      > So we can't just copy and paste the code.
                      > There is a space for discussion on this merge. Especially from
                      > design/phylosophy point of view. But whatever would be a
                      conclusion,
                      > the hard facts are that there are no resources to code it (not that
                      I
                      > know of). However, if it occurs that there is a strong will to do
                      that
                      > and a strong commitment to do the actuall work, I would be happy to
                      > help.
                      > -Piotr
                      >
                      > >
                      > > Couldn't one still merge Win32::GuiTest into Win32::GUI if certain
                      > GUI
                      > > functions used the message-hook trick for controls in other
                      > processes?
                      > > How tricky would that be?
                    • Piotr Kaluski
                      OK, I sent a question to Win32::GUI list. Have a look below on my question and the answer. Give it a try. Win32::GUI has many handy functions (I am not hired
                      Message 10 of 13 , Oct 6, 2005
                      • 0 Attachment
                        OK,
                        I sent a question to Win32::GUI list. Have a look below on my
                        question and the answer. Give it a try. Win32::GUI has many handy
                        functions (I am not hired by Win32::GUI team to promote them :-))

                        --Piotr

                        QUESTION:
                        Hi,
                        I am one of developers of Win32::GuiTest library. It is a module for
                        GUI test automation. I am actually pretty impressed with all the
                        great work you have done. Using your module should free us from
                        writing some functions ourselves.
                        I have one question. My impression is, that your library is object
                        oriented and it assumes, that a script using it has actually created
                        all windows it manipulates. Is it possible to attach to a
                        window/control created by some other application? Say I have a handle
                        of a main window of Windows calculator. How do I turn it into
                        Win::GUI object?


                        ANSWER (sent by Jeremy White):
                        Interesting question. As a quick/dirty answer, yes it could be
                        possible. The basic problem is that when Win::GUI object's are
                        destroyed the underlying window handle is also "destroyed".This could
                        be solved by having some sort of flag to say if Win::GUI actually
                        owns the object or not.

                        Ok - the above is true when we're using objects via method calls but
                        most of the internals can also be called as functions. For example:

                        $win->Show(); #shows the window

                        but we could also call it this way:

                        Win32::GUI::Show($win);

                        Where $win is a Win32::GUI object OR the handle...So, if you've got a
                        handle for some other app, then it should just work...

                        Hope that makes some sense.

                        Cheers,

                        jez.

                        END OF ANSWER




                        --- In perlguitest@yahoogroups.com, "Piotr Kaluski" <pkaluski@p...>
                        wrote:
                        > Hi,
                        > I just had a closer look on Win32::GUI. Boy, that's impressive what
                        > those guys did. They wrapped many, many useful Win32 API functions.
                        > So we should definitely have a closer look at this module. For some
                        > functions, there would be this interprocess boundaries problem. But
                        > there is quite a lot of functions, which can be used already.
                        > The only problem I see right now is that Win32::GUI is object
                        > oriented and it assumes, that you create windows and controls. I
                        did
                        > not find a function allowing to attach to existing window created
                        by
                        > some other process (which does not mean that such a functions does
                        > not exist).
                        >
                        > --Piotr
                        >
                        > --- In perlguitest@yahoogroups.com, "Piotr Kaluski" <pkaluski@p...>
                        > wrote:
                        > > Well, first of all it is not our decision. The idea has to be
                        > accepted
                        > > by Win::GUI development team. Apart from this, I am not sure
                        there
                        > is
                        > > someone who would actually have time to do it. Win32::GuiTest is
                        a
                        > kind
                        > > of procedural API, whereas Win32::GUI is a an object oriented
                        > library.
                        > > So we can't just copy and paste the code.
                        > > There is a space for discussion on this merge. Especially from
                        > > design/phylosophy point of view. But whatever would be a
                        > conclusion,
                        > > the hard facts are that there are no resources to code it (not
                        that
                        > I
                        > > know of). However, if it occurs that there is a strong will to do
                        > that
                        > > and a strong commitment to do the actuall work, I would be happy
                        to
                        > > help.
                        > > -Piotr
                        > >
                        > > >
                        > > > Couldn't one still merge Win32::GuiTest into Win32::GUI if
                        certain
                        > > GUI
                        > > > functions used the message-hook trick for controls in other
                        > > processes?
                        > > > How tricky would that be?
                      • Piotr Kaluski
                        ... Dennis, I had a look at your code. I haven t tested it yet, but I have some comments and would like to hear your and other people s opinion. I have placed
                        Message 11 of 13 , Nov 1, 2005
                        • 0 Attachment
                          --- In perlguitest@yahoogroups.com, "Piotr Kaluski" <pkaluski@p...> wrote:
                          >
                          > >
                          > > If I was to do this, what would I do with the patch or should I try
                          > to
                          > > get set up for CVS access to SourceForge?
                          >
                          > The best way would be if you take the most recent files from CVS
                          > (Instructions how to do it are here:
                          > https://sourceforge.net/cvs/?group_id=104592) and apply your changes
                          > there and than send me a patch. Note that after getting the files
                          > from
                          > CVS, you have to remove build.pl file (yes: REMOVE). Otherwise the
                          > code
                          > will not build.
                          > Please send a patch directly to me. Yahoo eats some spaces when
                          > displaying posts and "patch" program gets confused.
                          > Eventualy, if you really can't make cvs work for you, you can modify
                          > whatever file version you have and send it to me. Again - to me
                          > directly. Or even better - post changes in the group and send it to
                          > me
                          > directly (so people will have an opportunity to comment).
                          >
                          > -Piotr
                          >

                          Dennis,
                          I had a look at your code. I haven't tested it yet, but I have some
                          comments and would like to hear your and other people's opinion.
                          I have placed your code (and diffs with release 1.50.4) in the files
                          section of this group (new_lv.zip file).
                          Your code is terse, which proves that you have a pretty good command
                          of perl. However, I am afraid that this terseness, may make the code
                          slightly less readable for some less experienced developers.

                          The main point of your change was to give a user a chance to choose
                          not only an element from the list, but also a column in this element.
                          So you had to add a mechinism to pass an index of a column (subitem).
                          You have chosen, to merge this parameter with list view item index.
                          The code looks as follows:

                          #define pCW ((CWPSTRUCT*)lParam)
                          LRESULT HookProc (int code, WPARAM wParam, LPARAM lParam)
                          {
                          //// List Views ////
                          if (pCW->message == WM_LV_GETTEXT) {
                          *g_szBuffer = NUL;
                          int iItem = pCW->wParam;
                          int iSubItem = iItem & 0xFFFF;
                          iItem >>= 16;
                          ListView_GetItemText(g_hWnd, iItem, iSubItem, g_szBuffer,
                          MAX_DATA_BUF);
                          UnhookWindowsHookEx(g_hHook);
                          ......

                          --End of code--

                          So you treat pCW->wParam as a double word, which has iItem and
                          iSubItem in it. It probably works fine (I didn't test it), but I am
                          wondering if we can use pCW->lParam to pass iSubItem as separate
                          value. The code would look like this:

                          #define pCW ((CWPSTRUCT*)lParam)
                          LRESULT HookProc (int code, WPARAM wParam, LPARAM lParam)
                          {
                          //// List Views ////
                          if (pCW->message == WM_LV_GETTEXT) {
                          *g_szBuffer = NUL;
                          int iItem = pCW->wParam;
                          int iSubItem = pCW->lParam;
                          ListView_GetItemText(g_hWnd, iItem, iSubItem, g_szBuffer,
                          MAX_DATA_BUF);
                          UnhookWindowsHookEx(g_hHook);
                          ......

                          --End of code--

                          GetListViewContents would then look like this:

                          sub GetListViewContents
                          {
                          my $lv = shift;
                          my @res;
                          my $item_count = GetListViewItemCount($lv);
                          my $header = GetListViewHeader($lv);
                          my $column_count = $header ? GetHeaderColumnCount($header) : 1;
                          # Items are numbered from 0
                          for my $item_index (0..$item_count-1)
                          {
                          # Sub-items are numbered from 1
                          # push @res, [map(GetListViewItem($lv, $item_index << 16 | $_),
                          # 1..$column_count)];
                          # PK: Instead of lines above it would be:
                          push @res, [map(GetListViewItem($lv, $item_index, $_ ),
                          1..$column_count)];

                          }
                          return @res;
                          }

                          --End of code

                          That would of course require some changes in other functions:
                          GetListViewItem, GetLVItemText.

                          What do you think?

                          --Piotr
                        • denishowe
                          ... Yes, that works perfectly for me. MSDN had convinced me that I couldn t use lParam but I can no longer find the relevant page.
                          Message 12 of 13 , Nov 8, 2005
                          • 0 Attachment
                            In perlguitest@yahoogroups.com, "Piotr Kaluski" <pkaluski@p...> wrote:

                            > I am wondering if we can use pCW->lParam
                            > to pass iSubItem as separate value.

                            Yes, that works perfectly for me. MSDN had convinced me that I
                            couldn't use lParam but I can no longer find the relevant page.
                          Your message has been successfully submitted and would be delivered to recipients shortly.