2013-07-31 40 views
3

我使用了ViewStyle:= vsReport的ListView。當我從一個點拖動一行到另一個點時,它需要拖動行的第一列的值(如果是1),並將其顯示在深灰色的矩形中,如下所示。如何更改ListView OnDrag圖像?

enter image description here

我試着看着周圍的XE4源代碼,但找不到在哪裏這個背景顏色設置。我想將此背景顏色更改爲clSkyBlue(或類似的東西),但不知道它是如何完成的。

你如何去改變拖動操作的默認深灰色背景圖像?

+2

您無法找到它,背景顏色未在VCL代碼中設置。 VCL調用'ListView_CreateDragImage'傳遞被拖拽項目的索引,操作系統回傳一個圖像列表,該列表稍後被'ImageList_BeginDrag'拖拽。 –

+0

@SertacAkyuz圖像是在這個dll comctl32.dll我是對不對?也許可以通過這個方法添加一個圖像:ImageList_AddIcon()但我不確定,甚至更好,用這個方法ImageList_ReplaceIcon代替它。但是,自定義這將改變整個操作系統的映像。 – EProgrammerNotFound

+0

@SertacAkyuz此外,圖像索引爲0,請參見:SetDragImage(0,2,2);'在此過程中''過程TCustomTreeView.DoStartDrag(var DragObject:TDragObject);' – EProgrammerNotFound

回答

1

VCL的拖動操作沒有拖出圖像,但它確實提供了一種提供拖動圖像的機制。這通常是通過構建自己的「拖動圖像列表」來完成的,通過覆蓋控件本身的GetDragImages方法(當使用內部拖動對象時),或者在拖動開始時構建自己的「拖動對象」,以及組裝一個圖像列表在它的GetDragImages方法中,當拖動被啓動時由VCL調用。

這種機制雖然對於TListViewTTreeView控件有點不同,因爲底層api控件本身支持爲正在拖動的項目提供拖動圖像。因此,與其他控件不同,這些控件會覆蓋它們的方法,並返回在覆蓋DoStartDrag方法中創建的圖像列表,其中控件要求api提供圖像列表。這就是爲什麼你無法找到在VCL代碼中創建拖動圖像的原因。

要重寫此行爲,可以重寫子類中的這些(可能還有其他一些)方法並實現它們。我不知道這是否容易,我發現通過在事件處理函數中構造一個拖拽對象更容易提供一個圖像列表。這通常不會產生任何效果,因爲在我們拖動對象被調用的時候,VCL已經在api提供的圖像列表上定位,並且api創建了正在拖動的臨時列表。然後,我們可以強制拖動原始圖像列表結束並替換我們自己的圖像列表。

下面是一個簡單的例子。除了錯誤處理,資源保護,熱點決定等。請看VCL代碼,看看它是如何確保實際上有一個被拖動的項目。

type 
    TListWiewDragControlObjectEx = class(TDragControlObjectEx) 
    protected 
    function GetDragImages: TDragImageList; override; 
    end; 

function TListWiewDragControlObjectEx.GetDragImages: TDragImageList; 
var 
    Bmp: TBitmap; 
    R: TRect; 
begin 
    Bmp := TBitmap.Create; 
    Bmp.Canvas.Brush.Color := clSkyBlue; 
    R := TListView(Control).Selected.DisplayRect(drBounds); 
    Bmp.SetSize(R.Right - R.Left, R.Bottom - R.Top); 
    Bmp.Canvas.Font := TListView(Control).Font; 
    Bmp.Canvas.TextOut(0, 0, TListView(Control).Selected.Caption); 

    Result := TDragImageList.Create(Control); 
    Result.Width := Bmp.Width; 
    Result.Height := Bmp.Height; 
    ImageList_EndDrag;    // end the drag with the temporary list 
    Result.SetDragImage(Result.Add(Bmp, nil), 0, 0); 
    Bmp.Free; 
end; 

procedure TForm1.ListView1StartDrag(Sender: TObject; 
    var DragObject: TDragObject); 
begin 
    DragObject := TListWiewDragControlObjectEx.Create(ListView1); 
    DragObject.AlwaysShowDragImages := True; 
end; 
+0

我在ImageList_EndDrag上得到一個未定義的錯誤; –

+0

@Cape - 在使用子句中包含'commctrl'。對不起.. –

+0

我試過這個,但我放棄了放棄物品的能力。它拖得很好,但是當我把它放在它的新位置時,什麼也沒有發生。奇怪。我將不得不爲今後的發佈而編制此表。 –