package Win32::GUI::Combobox_improved; use strict; use warnings; use Win32::GUI; use Win32::API; our @ISA = qw( Win32::GUI::Combobox ); # API GetComboBoxInfo: # http://msdn.microsoft.com/library/en-us/shellcc/platform/commctls/comboboxes/comboboxreference/comboboxfunctions/getcomboboxinfo.asp # Struct COMBOINFO: # http://msdn.microsoft.com/library/en-us/shellcc/platform/commctls/comboboxes/comboboxreference/comboboxstructures/comboboxinfo.asp # Struct RECT: # http://msdn.microsoft.com/library/en-us/gdi/rectangl_6cqa.asp # Note: I have flattened the rcItem and rcButton RECT structs, # because of bugs in Win32::API and Win32::API::Struct's # handling of nested structs, or in my own understanding of it. Win32::API::Struct->typedef( 'COMBOBOXINFO', qw( DWORD cbSize; LONG rcItem_left; LONG rcItem_top; LONG rcItem_right; LONG rcItem_bottom; LONG rcButton_left; LONG rcButton_top; LONG rcButton_right; LONG rcButton_bottom; DWORD stateButton; HWND hwndCombo; HWND hwndItem; HWND hwndList; )); Win32::API->Import("user32", <<'END_API') or die; BOOL GetComboBoxInfo( HWND hwndCombo, COMBOBOXINFO * pcbi ); END_API sub _GetComboBoxInfo { my ($self) = @_; my $hwndCombo = $self->{-handle}; my $pcbi = Win32::API::Struct->new('COMBOBOXINFO'); $pcbi->{cbSize} = $pcbi->sizeof(); my $rc = GetComboBoxInfo( $hwndCombo, $pcbi, ); return unless $rc; warn unless $hwndCombo == $pcbi->{hwndCombo}; return $pcbi; } # Retrieves the handle to the child edit control # portion of a ComboBox control. sub GetEditControl { my ($self) = @_; my $combo_box_info = $self->_GetComboBoxInfo() or return; return $combo_box_info->{hwndItem}; } # Retrieves the handle to the child drop-down control # portion of a ComboBox control. sub GetDropDownControl { my ($self) = @_; my $combo_box_info = $self->_GetComboBoxInfo() or return; return $combo_box_info->{hwndList}; } package main; use strict; use warnings; use Win32::GUI; $| = 1; # Important! - Turn off buffering my $W1 = Win32::GUI::Window->new( -name => 'W1', -title => 'PerlMonks_494615', -pos => [ 100, 100 ], -size => [ 300, 200 ], ); my $combo_style = '-dropdown'; # Allows edits #my $combo_style = '-dropdownlist'; # Does not allow edits my $cb1 = Win32::GUI::Combobox_improved->new( $W1, # Parent -name => 'CB1', -left => 10, -top => 10, -width => 125, -height => 100, -tabstop => 1, $combo_style => 1, ); my $cb2 = Win32::GUI::Combobox_improved->new( $W1, # Parent -name => 'CB2', -left => 140, -top => 10, -width => 125, -height => 100, -tabstop => 1, $combo_style => 1, ); { my %handle_to_parent; foreach my $cb ( $cb1, $cb2 ) { my $handle_cb = $cb->{-handle}; my $handle_edit = $cb->GetEditControl(); my $handle_dd = $cb->GetDropDownControl(); $handle_to_parent{ $handle_cb } = $handle_cb; $handle_to_parent{ $handle_edit } = $handle_cb; $handle_to_parent{ $handle_dd } = $handle_cb; } my %handle_to_name = ( $cb1->{-handle} => 'CB1', $cb2->{-handle} => 'CB2', ); sub dump_it { my $event = (caller(1))[3]; my $focus = $W1->GetFocus(); my $true_focus = $handle_to_parent{$focus} || $focus; my $name = $handle_to_name{$true_focus}; print "$event: focus going to $name\n"; } } $cb1->InsertItem($_) foreach qw(Able Baker Charlie); $cb2->InsertItem($_) foreach qw(Roger Fox Dog); $cb1->Select(0); $cb2->Select(0); $W1->Show(); Win32::GUI::Dialog(); sub CB1_GotFocus { dump_it() } sub CB2_GotFocus { dump_it() } sub CB1_LostFocus { dump_it() } sub CB2_LostFocus { dump_it() }