Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Displaying sort arrows in Win32::GUI::ListView headers

by tomsell (Acolyte)
on Jan 02, 2013 at 13:30 UTC ( #1011271=perlquestion: print w/ replies, xml ) Need Help??
tomsell has asked for the wisdom of the Perl Monks concerning the following question:

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.

Update

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.

Comment on Displaying sort arrows in Win32::GUI::ListView headers
Select or Download Code

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1011271]
Approved by marto
Front-paged by ww
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (9)
As of 2015-07-07 11:06 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (88 votes), past polls