in reply to Win32 - Where will the focus go?

Even though the LostFocus event handler is called before the GotFocus event handler, the value returned by GetFocus() actually changes just before the LostFocus event. Therefore, your solution should be as simple as calling $your_main_window->GetFocus() inside your LostFocus event handler; it should tell you who is getting the new focus.

I may be wrong about this, but the example code below bears the thought out.
Working, tested code:

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 $T1 = $W1->AddTextfield( -name => 'T1', -text => '', -left => 10, -top => 10, -width => 200, -height => 25, -prompt => ['T1:', 80], ); my $T2 = $W1->AddTextfield( -name => 'T2', -text => '', -left => 10, -top => 35, -width => 200, -height => 25, -prompt => ['T2:', 80], ); $W1->Show(); print "$_->{-name}\t$_->{-handle}\n" foreach $W1, $T1, $T2; Win32::GUI::Dialog(); sub T1_GotFocus { print "\nT1_GotFocus - ",$W1->GetFocus(), "\n"; } sub T2_GotFocus { print "\nT2_GotFocus - ",$W1->GetFocus(), "\n"; } sub T1_LostFocus { print "\nT1_LostFocus - ",$W1->GetFocus(); } sub T2_LostFocus { print "\nT2_LostFocus - ",$W1->GetFocus(); }

Replies are listed 'Best First'.
Re^2: Win32 - Where will the focus go?
by ChrisR (Hermit) on Sep 23, 2005 at 19:45 UTC
    You're right. I should just forget about the Win32::GUI->GetMessage().

    I took another look at the problem after reading your post. The main difference is that if the focus is going to a combobox by the user pressing the TAB key or clicking in the textbox portion of the combobox the the handle is that of the textbox portion where GotFocus() returns the handle of the combobox. If the user clicks the arrow to dropdown the combobox list, the GotFocus idea works flawlessly.

    So how do I get the handles of both the textbox and the dropdown portions of a combobox?

      1. The simple solution. Each ComboBox can be configured as either
        • -dropdown, which allow edits, or
        • -dropdownlist, which does not allow edits.
        Of the two, only -dropdown has the split focus issue. So, if you can just use -dropdownlist, then your problem is solved.
      2. The less-simple solution. You can use Win32::API to call GetComboBoxInfo, which will give you the handles to the component controls. You can do this with straight-forward procedural code, but I chose to create a sub-class that provides the new methods GetEditControl and GetDropDownControl.

      Working, tested code:

      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() }

        Thanks!! That is the perfect solution to my problem and even included references for the internals. Again, thanks a lot! ++