Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

Hi monks, happy new year.

I'm not quite sure how to get Win32::GUI to display the familiar sort arrows in ListView headers. As this feature is not exposed by Win32::GUI, a suitable HDITEM structure has to be sent as the contents of the HDM_SETITEM message.

Which I translate into:

sub HDI_FORMAT {0x4} sub HDF_SORTDOWN {0x400} sub HDF_STRING {0x4000} sub HDM_SETITEM {0x1200 + 4} $hditem = pack("LLLLLLLLLLL", HDI_FORMAT, # mask 0, # cxy 0, # pszText 0, # hbm 0, # cchTextMax HDF_SORTDOWN | HDF_STRING, # fmt 0, # lParam 0, # iImage 0, # iOrder 0, # type 0 # pvFilter ); $hditem_ptr = pack('P44', $hditem); $hwnd = $myListView->GetHeader();

None of the following calls seem to do anything, their return value being "4":

Win32::GUI::SendMessage($hwnd, HDM_SETITEM, $columnClicked, $hditem_pt +r); Win32::GUI::SendMessage($hwnd, HDM_SETITEM, $columnClicked, unpack('L! +', $hditem_ptr)); $sendMessage = new Win32::API("user32","SendMessage","NNIP","I"); $sendMessage->Call($hwnd, HDM_SETITEM, $columnClicked, $hditem_ptr); $sendMessage->Call($hwnd, HDM_SETITEM, $columnClicked, unpack('L!', $h +ditem_ptr)); $listview->Show(1); # refresh

However, Win32::GuiTest gets the job done:

use Win32::GuiTest qw( :ALL ); $hditem_ptr = AllocateVirtualBuffer($hwnd, 44); WriteToVirtualBuffer($hditem_ptr, $hditem); SendMessage($hwnd, HDM_SETITEM, $columnClicked, $hditem_ptr->{ptr}); FreeVirtualBuffer($hditem_ptr); ShowWindow($hwnd, 1); # refresh

What am I missing here? Is it an address space issue or am I pack'ing the SendMessage lParam incorrectly? I'd really like to use Win32::GUI's SendMessage.


The problem are these declarations:

sub HDM_FIRST {0x1200} sub HDM_GETITEM {HDM_FIRST+11} # !WRONG: HDM_FIRST not a function c +all, result is 1211

Here's the fix.

sub HDM_GETITEM {&HDM_FIRST+11} # RIGHT: HDM_FIRST called, result is + 4619

So, for posterity, here's the complete code to display sort arrows in Win32::GUI::ListView headers (you should put this on a ColumnClick event handler on the ListView):

sub HDI_WIDTH {0x1} sub HDI_FORMAT {0x4} sub HDF_SORTUP {0x400} sub HDF_SORTDOWN {0x200} sub HDM_FIRST {0x1200} sub HDM_GETITEM {&HDM_FIRST+11} sub HDM_SETITEM {&HDM_FIRST+12} sub HDF_LEFT {0x0} sub HDF_RIGHT {0x1} sub HDF_CENTER {0x2} sub HDF_STRING {0x4000} # loop over columns, setting the arrow on the clicked column # and removing it from the others for (0 .. scalar $myListView->GetColumnOrderArray()){ my $arrowstate = ($_ == $columnclicked) # $columnclicked courtesy of + ColumnClick event handler ? $state # $state can be 'asc' or 'de +sc' (or something alike) : 'unset'; # and 'unset' setSortArrow($myListView, $_, $arrowstate); } sub setSortArrow { my ($listview, $column, $state) = @_; # request information on the format and the width of the column head +er my $hditem = pack("L11", HDI_FORMAT | HDI_WIDTH, # mask 0, # cxy 0, # pszText 0, # hbm 0, # cchTextMax 0, # fmt 0, # lParam 0, # iImage 0, # iOrder 0, # type 0 # pvFilter ); my $ptr = pack('P44', $hditem); my $hwnd = $listview->GetHeader(); my $r = Win32::GUI::SendMessage($hwnd, HDM_GETITEM, $column, unpack( +'L!', $ptr)); return unless $r; my @members = unpack('L11', $hditem); # cxy and fmt now updated by +call to HDM_GETITEM my $width = $members[1]; my $cxy = 0; my $fmt = sprintf("%X", $members[5]); my $justf = (($fmt | HDF_RIGHT) eq $fmt) ? HDF_RIGHT : ((($fmt | HDF_CENTER) eq +$fmt) ? HDF_CENTER + : HDF_LEFT); my $flags = HDF_STRING | $justf; # keep text and its justificatio +n unless($state eq 'unset'){ $flags |= ($state eq 'asc') ? HDF_SORTUP : HDF_SORTDOWN; # text on narrow columns will be trunacted with ellipses: adjust w +idth a little # FIXME: "80" is a little arbitrary and repeated sorting will keep + very narrow # columns growing until they are 80 pixels wide if((($fmt & HDF_SORTDOWN & HDF_SORTUP) > 0) && ($width < 80)){ $cxy = $width + 5; } } $members[0] = HDI_FORMAT | ($cxy ? HDI_WIDTH : 0x0); $members[1] = $cxy; $members[5] = $flags; $hditem = pack("L11", @members); $ptr = pack('P44', $hditem); $r = Win32::GUI::SendMessage($hwnd, HDM_SETITEM, $column, unpack('L! +', $ptr)); }

Comments and improvements are welcome.

In reply to Displaying sort arrows in Win32::GUI::ListView headers by tomsell

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others having an uproarious good time at the Monastery: (8)
    As of 2018-09-21 15:30 GMT
    Find Nodes?
      Voting Booth?
      Eventually, "covfefe" will come to mean:

      Results (187 votes). Check out past polls.

      • (Sep 10, 2018 at 22:53 UTC) Welcome new users!