#68 ListBox does not repaint if removing items removes scrollbar

closed
Robert May
None
5
2007-01-26
2007-01-25
Ali Bassiri
No

Just came across this,

I have a ListBox defined as follows:

$g_W1->AddListbox(-multisel=>2,-sort=>1,-vscroll=>1,-width=>180,-height=>300,-left=>260,-top=>150,-name=>"Machine_SelListBox");

This listbox can fit approximatly 22 items, now I add say 27 items to this listbox.

Now select all items, by selecting the first item and draging mouse downwards to the end item.

now click a designated delete button. the box will not repaint properly.. a call to Update or Redraw does not fix this.

the button for deletion is as follows:

sub Machine_RemButton_Click{

my $select_listbox = $g_W1->Machine_SelListBox;

my @items = $select_listbox->SelectedItems();
if(!defined $items[0]){
return;
}
foreach (reverse @items){
$select_listbox->Item($_)->Remove();
#other delete item methods did not work either.
}

}

also in another method, I was trying to add to the list box and wanted to select the items I had added by calling SelCur function using FindStringExact, this also causes repaint issues in Listbox as the scrollbar appears.

Discussion

  • Robert May
    Robert May
    2007-01-25

    • assigned_to: nobody --> robertemay
    • status: open --> pending
     
  • Robert May
    Robert May
    2007-01-25

    Logged In: YES
    user_id=674651
    Originator: NO

    I can't reproduce your problem (win98, Win2k, AS Perl 587). From the information you've given I produced this sample, which seems to behave correctly. Can you run it, and see if it works for you. If not, can you please explain what 'does not repaint correctly' means in your case.

    Regards,
    Rob.

    #!perl -w
    use strict;
    use warnings;

    use Win32::GUI();

    my $item = 0;

    my $mw = Win32::GUI::Window->new(
    -title => "Listbox Redraw problem Test",
    -size => [400,300],
    );

    my $lb = $mw->AddListbox(
    -name => "Machine_SelListBox",
    -pos => [10,10],
    -size => [180, 200],
    -multisel => 2,
    -sort => 1,
    -vscroll => 1,
    );

    $mw->AddButton(
    -text => "Add Item",
    -size => [85,23],
    -pos => [200,10],
    -onClick => sub { $lb->AddString("Item " . $item++); 1; },
    );

    $mw->AddButton(
    -text => "Delete Selected",
    -size => [85,23],
    -pos => [200,43],
    -onClick => \&del_items,
    );

    $mw->Show();
    Win32::GUI::Dialog();
    $mw->Hide();
    exit(0);

    sub del_items {

    my @items = $lb->SelectedItems();
    return 1 unless defined $items[0];

    foreach my $i (reverse @items) {
    #$lb->DeleteString($i); # Also works fine
    $lb->Item($i)->Remove();
    }

    return 1;
    }
    __END__

    I've marked this bug report as 'Pending' which means that if you do not respond within 4 days the item will be closed by the system.

     
  • Robert May
    Robert May
    2007-01-25

    Logged In: YES
    user_id=674651
    Originator: NO

    Sorry, that should read
    "I've marked this bug report as 'Pending' which means that if you do not
    respond within *14* days the item will be closed by the system."

     
  • Logged In: NO

    Just found out that the cause of this is the tabstrip behind the box... Try the code below..

    Try 15 items, then select all *FROM TOP TO BUTTOM*, then click on the delete button... the listbox borders will no longer be rendered.

    Similar thing happens with ListView, but for ListView, create two columns, then grab the resize edge of the second column and resize it to the right, past the right edge. this will cause a horizontal scrollbar to be created, however, the scrollbar is not painted, and is just solid gray.

    both these have to do with the tabstrip being behind them.

    Let me know if you cant see this and i'll send you more info and screenshot. i'm tried with latest version of perl and an older one, same thing happens. I'm using this package: Win32-GUI-1.05-PPM-5.8.zip for win32::GUI

    #!perl -w
    use strict;
    use warnings;

    use Win32::GUI();

    my $item = 0;

    my $mw = Win32::GUI::Window->new(
    -title => "Listbox Redraw problem Test",
    -size => [700,700],
    );

    my $g_tabStrip = $mw->AddTabStrip(
    -name=>"TabStrip",
    -width=>450,
    -height=>650,
    -top=>5,
    -left=>10
    );

    $g_tabStrip->InsertItem(-text=>"Machines");
    $g_tabStrip->InsertItem(-text=>"Drivers");
    $g_tabStrip->InsertItem(-text=>"Tasks");

    my $lb = $mw->AddListbox(
    -name => "Machine_SelListBox",
    -pos => [50,50],
    -size => [180, 200],
    -multisel => 2,
    -sort => 1,
    -vscroll => 1,
    );

    $mw->AddButton(
    -text => "Add Item",
    -size => [85,23],
    -pos => [250,50],
    -onClick => sub { $lb->AddString("Item " . $item++); 1; },
    );

    $mw->AddButton(
    -text => "Delete Selected",
    -size => [85,23],
    -pos => [250,93],
    -onClick => \&del_items,
    );

    $mw->Show();
    Win32::GUI::Dialog();
    $mw->Hide();
    exit(0);

    sub del_items {

    my @items = $lb->SelectedItems();
    return 1 unless defined $items[0];

    foreach my $i (reverse @items) {
    #$lb->DeleteString($i); # Also works fine
    $lb->Item($i)->Remove();
    }

    return 1;
    }

     
  • Robert May
    Robert May
    2007-01-26

    Logged In: YES
    user_id=674651
    Originator: NO

    Thanks for the feedback. I can see your problem, and have learned rather more than is good for me about the internals of the Windows Tab Control while investigating it. I don't believe that it's a bug with Win32::GUI, but a "feature" of the way Windows creates and handles the Tab Control that underlies Win32::GUI::TabStrip.

    As a result I've got a (slightly) simpler example that shows the problem (using a RichEdit control):

    #!perl -w
    use strict;
    use warnings;

    use Win32::GUI qw(CW_USEDEFAULT);

    my $mw = Win32::GUI::Window->new(
    -left => CW_USEDEFAULT,
    -size => [200,150],
    );

    my $ts = $mw->AddTabStrip(
    -size => [$mw->ScaleWidth(), $mw->ScaleHeight()]
    );
    $ts->InsertItem(-text => "Tab 1");

    $mw->AddRichEdit(
    -pos => [10, 40],
    -size => [100,70],
    -multiline => 1,
    -vscroll => 1,
    );

    $mw->Show();
    Win32::GUI::Dialog();
    $mw->Hide();
    exit(0);
    __END__

    Run that, click in the RichEdit field, and hit 'Return' enough times to go beyond the end of the box, and a scrollbar (sort of) appears. 'Backspace' moves you back until the scrollbar (doesn't properly) disappear. In fact this will happen with any action that changes the frame of a window. It's the frame that isn't drawing correctly, which is why InvalidateRect() and friends won't help - they only redraw the client area of a window.

    Without going in to the detail (which I can if you would like), there are (at least) 2 solutions that work:

    (1) Create the TabStrip control after the controls that you want to appear on it. This feels un-intuitave to me, but it appears to be how most MS dialogs do it:

    #!perl -w
    use strict;
    use warnings;

    use Win32::GUI qw(CW_USEDEFAULT);

    my $mw = Win32::GUI::Window->new(
    -left => CW_USEDEFAULT,
    -size => [200,150],
    );

    $mw->AddRichEdit(
    -pos => [10, 40],
    -size => [100,70],
    -multiline => 1,
    -vscroll => 1,
    );

    my $ts = $mw->AddTabStrip(
    -size => [$mw->ScaleWidth(), $mw->ScaleHeight()]
    );
    $ts->InsertItem(-text => "Tab 1");

    $mw->Show();
    Win32::GUI::Dialog();
    $mw->Hide();
    exit(0);
    __END__

    (2) Make the controls you want to appear on the tab strip children of the tabstrip, rather than children of the main window. This feels more natural to me, but I can't make TABing work properly in a Win32::GUI::DialogBox window. I can with the option above.

    #!perl -w
    use strict;
    use warnings;

    use Win32::GUI qw(CW_USEDEFAULT);

    my $mw = Win32::GUI::Window->new(
    -left => CW_USEDEFAULT,
    -size => [200,150],
    );

    my $ts = $mw->AddTabStrip(
    -size => [$mw->ScaleWidth(), $mw->ScaleHeight()]
    );
    $ts->InsertItem(-text => "Tab 1");

    $ts->AddRichEdit(
    -pos => [10, 40],
    -size => [100,70],
    -multiline => 1,
    -vscroll => 1,
    );

    $mw->Show();
    Win32::GUI::Dialog();
    $mw->Hide();
    exit(0);
    __END__

    I hope this helps. I've closed this item, but if you don't agree, then please respond here, and I'll re-open it.

    Regards,
    Rob.

     
  • Robert May
    Robert May
    2007-01-26

    • status: pending --> closed