Search code examples
delphic++buildertlistview

Disabling deselect in TListView control


I would like to use TListView (vsIcon) as a kind of tabs - so that only one item can be selected just like tabs. Selecting only one item is no problem (disabling Multiselect property). Problem is deselecting items when clicking on blank spots between icons and text in the listview.

Here is what I tried so far:

void __fastcall TForm::ListViewChanging(TObject *Sender, TListItem *Item, TItemChange Change, bool &AllowChange)
{
if (Change == ctState)
    {
    TPoint CursorRel = ListView->ScreenToClient(Mouse->CursorPos);
    AllowChange = (ListView->GetItemAt(CursorRel.x, CursorRel.y) != NULL);
    StatusBar->SimpleText = (AllowChange)? "YES" : "NO";
    }
}

The above works but there is a problem. When mouse is clicked on blank area it deselects the item and keyboard up/down arrow no longer work although the item still looks selected. If I ignore keyboard, for mouse selection it works fine and it ignores clicks on blank areas with the message "NO" in the statusbar.

Any ideas how to fix this so it works with all possible selection methods (keyboard, mouse (any other?)).


Solution

  • Here is another possible answer to your question :

    unit Unit1;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ImgList, ComCtrls;
    
    type
      TForm1 = class(TForm)
        ListView1: TListView;
        ImageList1: TImageList;
        StatusBar1: TStatusBar;
        procedure ListView1Changing(Sender: TObject; Item: TListItem;
          Change: TItemChange; var AllowChange: Boolean);
        procedure ListView1MouseUp(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
        procedure ListView1Enter(Sender: TObject);
      private
        FListItem: TListItem;
        procedure SelectedListItemStateSave;
        procedure SelectedListItemStateRestore;
      public
        { Public declarations }
      end;
    
    var
      Form1: TForm1;
    
    implementation
    
    {$R *.dfm}
    
    procedure TForm1.SelectedListItemStateRestore;
    begin
      ListView1.Selected := FListItem;
      ListView1.Selected.Focused := True; // Always focused
    end;
    
    procedure TForm1.SelectedListItemStateSave;
    begin
      FListItem := ListView1.Selected;
    end;
    
    procedure TForm1.ListView1Changing(Sender: TObject; Item: TListItem;
      Change: TItemChange; var AllowChange: Boolean);
    begin
      if (Change=ctState) then
        SelectedListItemStateSave;
    end;
    
    procedure TForm1.ListView1Enter(Sender: TObject);
    begin
      if ListView1.Selected = nil then
      begin
        FListItem :=ListView1.Items[0]; // Initialization
        SelectedListItemStateRestore;
      end;
    end;
    
    procedure TForm1.ListView1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if ListView1.GetItemAt(X,Y) = nil then
      begin
        SelectedListItemStateRestore;
      end;
    end;
    
    end.