Hi,
On 31/01/2013 22:41, Dave Hayes wrote:
Hello. I'm trying to get the text, column, and item index on a right
click in a Wx::ListCtrl. The item index works perfectly. However, I
can't seem to get any other information. Here's a very abbreviated idea
of what I am doing:
I can answer this by pulling a couple of 'rabbits out of a hat' in the
form of undocumented method calling and some extra code for none wxMSW
platforms.
The method $event->GetPoint() will return the mouse position.
The method $listctrl->HitTest($point) actually returns three items, the
third of which is the subitem, or column index.
The method $listctrl->GetItem actually accepts two params, the second
being the column number (default 0).
So to get the column text that was clicked the following ought to work:
my $point = $event->GetPoint();
my $listctrl = $event->GetEventObject;
my($itemindex, $flags, $subitemindex) = $listctrl->HitTest($point);
my $text = $listctrl->GetItem($itemindex, $subitemindex)->GetText;
print qq(Right clicked text: $text\n);
Alas, the third return item from $listctrl->HitTest is only implemented
on Windows, so we need a separate method to determine the column clicked
on wxGTK for example. It is quite simple to implement - an
implementation is contained in the attached code.
Hope it helps.
Regards
Mark
#########################################################################################
# Description: wxListCtrl Test
# Created Mon Feb 04 15:01:53 2013
# svn id $Id:$
# Copyright: Copyright (c) 2013 Mark Dootson
# Licence: This program is free software; you can redistribute it
# and/or modify it under the same terms as Perl itself
#########################################################################################
package MainWindow;
use strict;
use warnings;
use Wx qw( :id :misc :window :sizer :panel :listctrl );
use base qw( Wx::Frame );
use Wx::Event qw(
EVT_LIST_ITEM_SELECTED EVT_LIST_ITEM_DESELECTED
EVT_LIST_ITEM_ACTIVATED EVT_LIST_ITEM_FOCUSED
EVT_LIST_ITEM_RIGHT_CLICK
);
sub new {
my $class = shift;
my $self = $class->SUPER::new( @_ );
my $mainpanel = Wx::Panel->new($self, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL|wxBORDER_NONE );
my $list = Wx::ListCtrl->new($mainpanel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxLC_SINGLE_SEL );
my $mainsizer = Wx::BoxSizer->new(wxVERTICAL);
my $panelsizer = Wx::BoxSizer->new(wxVERTICAL);
$panelsizer->Add($list,1,wxALL|wxEXPAND, 0);
$mainpanel->SetSizer($panelsizer);
$mainsizer->Add($mainpanel,1,wxALL|wxEXPAND, 0);
$self->SetSizer($mainsizer);
my @data = (
[qw ( R0CO ROC1 ROC2 ) ],
[qw ( R1CO R1C1 R1C2 ) ],
[qw ( R2CO R2C1 R2C2 ) ],
);
$list->InsertColumn(0, 'Col 0', wxLIST_FORMAT_LEFT, 100);
$list->InsertColumn(1, 'Col 1', wxLIST_FORMAT_LEFT, 100);
$list->InsertColumn(2, 'Col 2', wxLIST_FORMAT_LEFT, 100);
for (my $i = 0; $i < @data; $i++) {
$list->InsertStringItem($i, $data[$i]->[0]);
$list->SetItem($i, 1, $data[$i]->[1]);
$list->SetItem($i, 2, $data[$i]->[2]);
}
EVT_LIST_ITEM_SELECTED($self, $list, \&OnItemSelected);
EVT_LIST_ITEM_DESELECTED($self, $list, \&OnItemDeselected);
EVT_LIST_ITEM_ACTIVATED($self, $list, \&OnItemActivated);
EVT_LIST_ITEM_FOCUSED($self, $list, \&OnItemFocused);
EVT_LIST_ITEM_RIGHT_CLICK($self, $list, \&OnItemRightClick);
return $self;
}
sub OnItemSelected {
my($self, $event) = @_;
$event->Skip(1);
print q(EVT_LIST_ITEM_SELECTED) . qq(\n);
}
sub OnItemDeselected {
my($self, $event) = @_;
$event->Skip(1);
print q(EVT_LIST_ITEM_DESELECTED) . qq(\n);
}
sub OnItemActivated {
my($self, $event) = @_;
$event->Skip(1);
print q(EVT_LIST_ITEM_ACTIVATED) . qq(\n);
}
sub OnItemFocused {
my($self, $event) = @_;
$event->Skip(1);
print q(EVT_LIST_ITEM_FOCUSED) . qq(\n);
}
sub OnItemRightClick {
my($self, $event) = @_;
$event->Skip(1);
print q(EVT_LIST_ITEM_RIGHT_CLICK) . qq(\n);
my $point = $event->GetPoint();
my $listctrl = $event->GetEventObject;
my($itemindex, $flags, $subitemindex) = $listctrl->HitTest($point);
if( !Wx::wxMSW() ) {
# $subitemindex only populated on wxMSW
$subitemindex = $self->_get_generic_subitem( $listctrl, $point );
}
print qq($itemindex, $flags, $subitemindex\n);
my $text = $listctrl->GetItem($itemindex, $subitemindex)->GetText;
print qq(Right clicked text: $text\n);
}
sub _get_generic_subitem {
my($self, $listctrl, $point) = @_;
# iterate through columms and check if $point->x is within that column width
my $left = 0;
for(my $i = 0; $i < $listctrl->GetColumnCount; $i ++) {
my $right = $left + $listctrl->GetColumnWidth($i);
if($point->x >= $left && $point->x <= $right) {
return $i;
} else {
$left = $right + 1;
}
}
Wx::LogError('Could not determine column in right click');
return 0;
}
package Application;
use strict;
use warnings;
use Wx;
use base qw( Wx::App );
sub OnInit {
my $self = shift;
my $mwin = MainWindow->new(undef, -1, 'Test wxListCtrl' );
$self->SetTopWindow($mwin);
$mwin->Show(1);
}
package main;
my $app = Application->new;
$app->MainLoop;
1;