2011-12-26 37 views
1

我想使用TListView(vsIcon)作爲一種選項卡 - 以便只能選擇一個項目,就像選項卡一樣。只選擇一個項目是沒有問題的(禁用Multiselect屬性)。問題是在列表視圖中點擊圖標和文本之間的空白點時取消選擇項目。在TListView控件中禁用取消選擇

這裏是我試過到目前爲止:

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"; 
    } 
} 

上述作品,但有一個問題。在空白區域單擊鼠標時,取消選擇該項目和鍵盤上/下箭頭不再有效,儘管該項目仍然處於選中狀態。如果我忽略鍵盤,對於鼠標選擇它可以正常工作,並忽略狀態欄中消息「NO」的空白區域的點擊。

任何想法如何解決這個問題,所以它適用於所有可能的選擇方法(鍵盤,鼠標(任何其他?))。

回答

1

這裏是另一個可能的回答你的問題:

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. 
+0

我覺得這一個是可用的。感謝你的回答。 – Coder12345 2011-12-30 15:33:58

+0

@Coder - 對你的情況可能並不重要,但一般情況下,如果你不想阻止某些事情,最好防止它(如果你可以幫助它),而不是撤銷已完成的事情。用戶可以按下空白區域的按鈕,但釋放項目上的按鈕,例如.. – 2011-12-31 02:08:35

+0

@Sertac Akyuz:從嚴格的OOP角度來看,我更傾向於基於TCustomListView或者甚至在TCustomMultiSelectListControl上滾動一個新組件,從頭開始要求具體的行爲。我根據@ Coder12345的偏好建立了我的解決方案。 – menjaraz 2011-12-31 04:31:19

3

攔截WM_LBUTTONDOWN發佈到控件並停止默認處理,如果點擊不在項目上。子類的控制,或使用ApplicationEvents組件等。Delphi代碼示例與中介類:

type 
    TListView = class(comctrls.TListView) 
    protected 
    procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN; 
    end; 

    TForm1 = class(TForm) 
    ListView1: TListView; 
    private 
    .. 

procedure TListView.WMLButtonDown(var Message: TWMLButtonDown); 
begin 
    if GetItemAt(Message.XPos, Message.YPos) <> nil then 
    inherited; 
end; 
相關問題