【发布时间】:2011-01-14 18:36:36
【问题描述】:
在我的应用程序(Delphi 2007)中,我想将项目从 ListView 拖到 PaintBox 并突出显示 PaintBox 的 OnPaint 处理程序中的相应区域。然而,我总是得到丑陋的文物。您对我如何摆脱它们有什么建议吗?
测试项目:只需创建一个新的 VCL 应用程序并将 Unit1.pas 中的代码替换为以下代码。然后启动应用程序并将列表项拖到 PaintBox 中的矩形上方。
unit Unit1;
interface
uses
Windows,
Messages,
SysUtils,
Variants,
Classes,
Graphics,
Controls,
Forms,
Dialogs,
ExtCtrls,
ComCtrls,
ImgList;
type
TForm1 = class(TForm)
private
PaintBox1: TPaintBox;
ListView1: TListView;
ImageList1: TImageList;
FRectIsHot: Boolean;
function GetSensitiveRect: TRect;
procedure PaintBox1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
procedure PaintBox1Paint(Sender: TObject);
public
constructor Create(AOwner: TComponent); override;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses
TypInfo;
const
IconIDs: array[TMsgDlgType] of PChar = (IDI_EXCLAMATION, IDI_HAND,
IDI_ASTERISK, IDI_QUESTION, nil);
{ TForm1 }
constructor TForm1.Create(AOwner: TComponent);
var
Panel1: TPanel;
mt: TMsgDlgType;
Icon: TIcon;
li: TListItem;
begin
inherited Create(AOwner);
Width := 600;
Height := 400;
ImageList1 := TImageList.Create(Self);
ImageList1.Name := 'ImageList1';
ImageList1.Height := 32;
ImageList1.Width := 32;
ListView1 := TListView.Create(Self);
ListView1.Name := 'ListView1';
ListView1.Align := alLeft;
ListView1.DragMode := dmAutomatic;
ListView1.LargeImages := ImageList1;
Panel1 := TPanel.Create(Self);
Panel1.Name := 'Panel1';
Panel1.Caption := 'Drag list items here';
Panel1.Align := alClient;
PaintBox1 := TPaintBox.Create(Self);
PaintBox1.Name := 'PaintBox1';
PaintBox1.Align := alClient;
PaintBox1.ControlStyle := PaintBox1.ControlStyle + [csDisplayDragImage];
PaintBox1.OnDragOver := PaintBox1DragOver;
PaintBox1.OnPaint := PaintBox1Paint;
PaintBox1.Parent := Panel1;
ListView1.Parent := Self;
Panel1.Parent := Self;
Icon := TIcon.Create;
try
for mt := Low(TMsgDlgType) to High(TMsgDlgType) do
if Assigned(IconIDs[mt]) then
begin
li := ListView1.Items.Add;
li.Caption := GetEnumName(TypeInfo(TMsgDlgType), Ord(mt));
Icon.Handle := LoadIcon(0, IconIDs[mt]);
li.ImageIndex := ImageList1.AddIcon(Icon);
end;
finally
Icon.Free;
end;
end;
function TForm1.GetSensitiveRect: TRect;
begin
Result := PaintBox1.ClientRect;
InflateRect(Result, -PaintBox1.Width div 4, -PaintBox1.Height div 4);
end;
procedure TForm1.PaintBox1Paint(Sender: TObject);
var
r: TRect;
begin
r := GetSensitiveRect;
if FRectIsHot then
begin
PaintBox1.Canvas.Pen.Width := 5;
PaintBox1.Canvas.Brush.Style := bsSolid;
PaintBox1.Canvas.Brush.Color := clAqua;
end
else
begin
PaintBox1.Canvas.Pen.Width := 1;
PaintBox1.Canvas.Brush.Style := bsClear;
end;
PaintBox1.Canvas.Rectangle(r.Left, r.Top, r.Right, r.Bottom);
end;
procedure TForm1.PaintBox1DragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean);
var
r: TRect;
MustRepaint: Boolean;
begin
MustRepaint := False;
if State = dsDragEnter then
begin
FRectIsHot := False;
MustRepaint := True;
end
else
begin
r := GetSensitiveRect;
Accept := PtInRect(r, Point(X, Y));
if Accept <> FRectIsHot then
begin
FRectIsHot := Accept;
MustRepaint := True;
end;
end;
if MustRepaint then
PaintBox1.Invalidate;
end;
end.
编辑:这是故障图片:DragImage artefact http://img269.imageshack.us/img269/6535/15778780.png
我希望看到带有粗边框的完整蓝色矩形。然而,在拖动图像下方可以看到未突出显示的矩形。
编辑 2: This site 谈论“绘画问题”:
ImageList SDK 指出,当 绘制可以得到的拖动图像 更新或屏幕绘画问题 除非你使用 ImageList_DragLeave 隐藏拖动图像的 API 函数 当绘画发生时(这是 中的 HideDragImage 方法是什么 类)。不幸的是,如果你 不拥有当前的控制权 画做这不是真的 选项。
我没有最后一句中提到的问题。尽管如此,我还是找不到正确的位置和正确的图像列表(在我的测试项目中 不是 ImageList1 - 可能是 ListView1.GetDragImages)来调用 ImageList_DragLeave。
【问题讨论】:
-
我已将源代码复制到D2009并运行它。无论拖动哪个对象都没有故障。顺便说一句,运行 Vista。
-
好吧,这暗示 D2007、XP 或我的显卡可能是罪魁祸首。感谢您的测试!
-
我刚刚在我的家用电脑(XP、Turbo Delphi)上测试了它,它看起来和上图一模一样。
-
我相信这可能是 XP 的问题。我在虚拟机中安装了 XP,并且有 D7 和 D2007,两者都出现故障。
-
我猜它只有在启用桌面合成 (Aero) 的情况下才能在 Vista 上运行?
标签: delphi drag-and-drop delphi-2007 paintbox