我想实现在拖动一个控件时,跟随鼠标的移动显示一个和被拖动的控件的一样的一个图形,不知道什么方法最好?
下面是我自己写的一个类及使用的代码(拖动一个Lable到一个Panel上),它继承了TDragControlObject类,但为什么总是不显示图形呢,不知道问题出在哪里!
请指教!谢谢!
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
Panel1: TPanel;
procedure Label1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Label1StartDrag(Sender: TObject;
var DragObject: TDragObject);
procedure Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
private
{ Private declarations }
list1item : string;
public
{ Public declarations }
end;
type
TTextDragObject = class(TDragControlObject)
private
DragImgs : TDragImageList;
FDragText : string;
protected
function GetDragImages: TDragImageList; override;
public
constructor createNew(AControl: TControl;Text : string);
constructor create(AControl: TControl); override;
destructor Destroy; override;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Label1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbleft then
Label1.BeginDrag(True);
end;
constructor TTextDragObject.createNew(AControl: TControl;Text : string);
begin
inherited create(AControl);
FDragText := Text;
end;
constructor TTextDragObject.create(AControl: TControl);
begin
inherited;
end;
destructor TTextDragObject.Destroy;
begin
inherited;
end;
function TTextDragObject.GetDragImages: TDragImageList;
var
Bmp : TBitmap;
Idx : Integer;
bmp2 : TBitmap;
p : TPoint;
begin
if DragImgs=nil then
DragImgs := TDragImageList.create(nil);
Bmp := TBitmap.create;
bmp2 := TBitmap.create;
Bmp.Height := Bmp.Canvas.TextHeight(FDragText);
Bmp.Width := Bmp.Canvas.TextWidth(FDragText);
Bmp.Canvas.TextOut(0,0,FDragText);
DragImgs.Width := Bmp.Width;
DragImgs.Height := Bmp.Height;
Idx := DragImgs.AddMasked(Bmp,clWhite);
DragImgs.SetDragImage(Idx, 0, 0);
Result := DragImgs;
Bmp.Free;
end;
procedure TForm1.Label1StartDrag(Sender: TObject;
var DragObject: TDragObject);
var
pt: TPoint;
begin
DragObject := TTextDragObject.createNew(Panel1,Label1.Caption);
end;
procedure TForm1.Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
if Source is TLabel then
if (Source as TLabel).Name = 'Label2' then
Accept := True;
end;
end.
下面是我自己写的一个类及使用的代码(拖动一个Lable到一个Panel上),它继承了TDragControlObject类,但为什么总是不显示图形呢,不知道问题出在哪里!
请指教!谢谢!
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, ExtCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
Panel1: TPanel;
procedure Label1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Label1StartDrag(Sender: TObject;
var DragObject: TDragObject);
procedure Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
private
{ Private declarations }
list1item : string;
public
{ Public declarations }
end;
type
TTextDragObject = class(TDragControlObject)
private
DragImgs : TDragImageList;
FDragText : string;
protected
function GetDragImages: TDragImageList; override;
public
constructor createNew(AControl: TControl;Text : string);
constructor create(AControl: TControl); override;
destructor Destroy; override;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Label1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbleft then
Label1.BeginDrag(True);
end;
constructor TTextDragObject.createNew(AControl: TControl;Text : string);
begin
inherited create(AControl);
FDragText := Text;
end;
constructor TTextDragObject.create(AControl: TControl);
begin
inherited;
end;
destructor TTextDragObject.Destroy;
begin
inherited;
end;
function TTextDragObject.GetDragImages: TDragImageList;
var
Bmp : TBitmap;
Idx : Integer;
bmp2 : TBitmap;
p : TPoint;
begin
if DragImgs=nil then
DragImgs := TDragImageList.create(nil);
Bmp := TBitmap.create;
bmp2 := TBitmap.create;
Bmp.Height := Bmp.Canvas.TextHeight(FDragText);
Bmp.Width := Bmp.Canvas.TextWidth(FDragText);
Bmp.Canvas.TextOut(0,0,FDragText);
DragImgs.Width := Bmp.Width;
DragImgs.Height := Bmp.Height;
Idx := DragImgs.AddMasked(Bmp,clWhite);
DragImgs.SetDragImage(Idx, 0, 0);
Result := DragImgs;
Bmp.Free;
end;
procedure TForm1.Label1StartDrag(Sender: TObject;
var DragObject: TDragObject);
var
pt: TPoint;
begin
DragObject := TTextDragObject.createNew(Panel1,Label1.Caption);
end;
procedure TForm1.Panel1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
if Source is TLabel then
if (Source as TLabel).Name = 'Label2' then
Accept := True;
end;
end.
解决方案 »
- 请教delphi事件与对象指针方法的关系
- DBGridEh中的下拉表格选择方法怎么实现的?我看了很多资料和Demo还是搞不明白!
- 应用程序打包问题(在线等)
- 100分!!!急等!地图上实现链接点固化的问题!
- 免费100MASP空间申请(支持CGI)
- 怎样可以使QRDBText控件里加上TLabel的Layout属性和功能呢???重分谢答
- 怎样在一个DBgrid里实现记录的插入、修改、删除、保存,但是不用任何button,也不用DBnavigator?
- XML中文显示问题
- 又是报表问题!急!在线等待……
- 求助 在teechart中 如何将曲线超出Y轴边界的部分从Y轴底部显示
- 如何实现程序启动后10秒自动最小化到托盘,再过10秒又恢复到主窗口?
- 刚学DLL简单的问题路过的帮看看
鼠标变成列的标题形状,我看了它的源代码好像实现起来
比较复杂.
unit TextObjectU;interfaceuses Windows, Messages, SysUtils, Classes,Controls,Graphics,StdCtrls,Forms;const
BASE_FONT_SIZE = 12;
type
TPrintFont = set of (pfCustom,pfNormal,pfDbWidth,pfDbHeight,pfBold,pfStrikeOut,pfSmooth,pfItalic,pfUnderline);
TTextObject = class(TCustomControl)
private
FLock: Boolean;
FActive: Boolean;
FAutoSize: Boolean;
FSelected: Boolean;
FCanReSize: Boolean;
FEditing: Boolean;
FEdit: TEdit;
FOldPos: TPoint; //记录鼠标屏幕位置
FMouseDownArea: Word; //记录鼠标按下时区域
FCharSpacing: SmallInt;
FPrintFont: TPrintFont; //模拟显示字体
FPFWTimes: Integer; //自定义字体宽
FPFHTimes: Integer; //自定义字体高
FLogFont: TLogFont;
FSmallRect: array[1..8] of TRect;
FClientRect: TRect; //文本 显示&编辑 区
FOnSelected: TNotifyEvent;
procedure DrawCtHandle;
function GetActive: Boolean;
procedure SetActive(const Value: Boolean);
function GetCharSpacing: Byte;
procedure SetCharSpacing(const Value: Byte);
function InchToPoint(Value: Byte): SmallInt;
function PointToInch(Value: SmallInt): Byte;
procedure MouseDragMoveResize(CtrHandle: Integer);
procedure SetPrintFont(const Value: TPrintFont);
procedure MessageFocusEnter(var Msg: TMessage); message CM_Enter;
procedure MessageFocusExit(var Msg: TMessage); message CM_Exit;
procedure SetSelected(const Value: Boolean); protected
procedure Paint; override;
procedure MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
procedure MouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
procedure MouseUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
procedure MouseDoubleClick(Sender: TObject);
procedure Resize(Sender: TObject);
procedure EditExit(Sender: TObject);
procedure EditKeyPress(Sender: TObject; var Key: Char);
function MakeLogFont(PFType: TPrintFont): HFont;
function CheckEdge(P: TPoint): Integer;
public
constructor Create(AOwner: TComponent); override;
procedure Lock;
procedure UnLock;
procedure EditText;
property Active: Boolean read GetActive write SetActive Default True;
property Caption;
property Font;
property CharSpacing: Byte read GetCharSpacing write SetCharSpacing Default 0;
property PrintFont: TPrintFont read FPrintFont Write SetPrintFont;
property CustomPFWidth: Integer read FPFWTimes write FPFWTimes;
property CustomPFHeight: Integer read FPFHTimes write FPFHTimes;
property Selected: Boolean read FSelected write SetSelected;
property OnSelected: TNotifyEvent read FOnSelected write FOnSelected;
end;implementation
const
CTH_SIZE: Byte = 3;
Cursor_Type: array[0..8] of TCursor = (crDefault,crSizeNWSE,crSizeNS,crSizeNESW,crSizeWE,
crSizeNWSE,crSizeNS,crSizeNESW,crSizeWE);{ TTextObject }function TTextObject.CheckEdge(P: TPoint): Integer;
var
ii: Integer;
begin
Result := 0;
for ii := Low(FSmallRect) to High(FSmallRect) do
if (P.x >= FSmallRect[ii].Left) AND (P.x <= FSmallRect[ii].Right) AND (P.y >= FSmallRect[ii].Top ) AND (P.y <= FSmallRect[ii].Bottom) then
begin
Result := ii;
Break;
end;
end;constructor TTextObject.Create(AOwner: TComponent);
begin
inherited;
Parent := TWinControl(AOwner);
AutoSize := True;
FPrintFont := [pfNormal];
FillChar(FLogFont,SizeOf(TLogFont),0);
Font.Handle := MakeLogFont(FPrintFont);
AutoSize := False;
Caption := '广州中鸣显示';
Canvas.Font := Font;
FCanReSize := False; OnMouseDown := MouseDown;
OnMouseMove := MouseMove;
OnMouseUp := MouseUp;
OnDblClick := MouseDoubleClick;
OnResize := Resize; Height := Canvas.TextHeight(Caption) + 2 * CTH_SIZE;
Width := Canvas.TextWidth(Caption) + 2 * CTH_SIZE;
SetFocus;
end;procedure TTextObject.DrawCtHandle; //画出八个小方块
var
ii: Integer;
begin
//编辑状态只画虚线框
if FEditing then
with Canvas do
begin
Pen.Color := clLime;
Brush.Style := bsClear;
Pen.Style := psDashDot;
Rectangle(ClientRect);
end
else
with Canvas do
begin
Pen.Color := clLime;
Brush.Style := bsClear;
Pen.Style := psDot;
Rectangle(CTH_SIZE,CTH_SIZE,Width - CTH_SIZE,Height - CTH_SIZE);
Brush.Style := bsSolid;
Brush.Color := clLime;
Pen.Style := psSolid;
Pen.Color := clBlack;
for ii := Low(FSmallRect) to High(FSmallRect) do
Rectangle(FSmallRect[ii]);
end;
end;procedure TTextObject.EditExit(Sender: TObject);
begin
Caption := (Sender as TEdit).Text;
(Sender as TEdit).Visible := False;
FEditing := False;
Invalidate;
end;procedure TTextObject.EditKeyPress(Sender: TObject; var Key: Char);
begin
//Enter键完成编辑退出 ESC 取消编辑退出
if Key in [#13,#27] then
begin
if Key = #27 then
FEdit.Text := Caption;
Key := #0;
SetFocus;
end;
end;procedure TTextObject.EditText;
begin
FEditing := True;
if not Assigned(FEdit) then
begin
FEdit := TEdit.Create(Self);
with FEdit do
begin
Parent := Self;
ParentFont := True;
BorderStyle := bsNone;
AutoSelect := True;
Left := FClientRect.Left;
Top := FClientRect.Top;
Width := FClientRect.Right - Left;
Height := FClientRect.Bottom - Top; OnExit := EditExit;
OnKeyPress := EditKeyPress;
end;
end; with FEdit do
begin
Text := Self.Caption;
Visible := True;
BringToFront;
SetFocus;
end;
Invalidate; //重画
end;function TTextObject.GetActive: Boolean;
begin
Result := FActive;
end;function TTextObject.GetCharSpacing: Byte;
begin
Result := FCharSpacing div 70 * 180
end;function TTextObject.InchToPoint(Value: Byte): SmallInt;
begin
Result := Value * 70;
end;procedure TTextObject.Lock;
begin
DragMode := dmManual;
end;
const
BoolToInt: array[False..True] of Byte = (0,1);
var
iW,iH: Integer;
iWeight: Integer;
begin
//pfDbWidth,pfDbHeight,pfStrong,pfSmooth
iW := BASE_FONT_SIZE div 2;
iH := BASE_FONT_SIZE;
if PFType = [] then
PFType := [pfNormal];
if Not (pfNormal in PFType) then
begin
if pfDbWidth in PFType then
iW := BASE_FONT_SIZE;
if pfDbHeight in PFType then
iH := BASE_FONT_SIZE * 2; if pfCustom in PFType then
begin
iW := BASE_FONT_SIZE * FPFWTimes div 2;
iH := BASE_FONT_SIZE * FPFHTimes;
end;
end;
if pfBold in PFType then
iWeight := 700
else
iWeight := 400; with FLogFont do
begin
lfHeight := iH;
lfWidth := iW;
lfEscapement := GM_COMPATIBLE;
lfOrientation := GM_COMPATIBLE;
lfWeight := iWeight;
lfCharSet := GB2312_CHARSET;
lfQuality := 2;//ANTIALIASED_QUALITY;
lfPitchAndFamily := FF_ROMAN OR DEFAULT_PITCH;
lfUnderline := BoolToInt[pfUnderline in PFType];
lfItalic := BoolToInt[pfItalic in PFType];
lfStrikeOut := BoolToInt[pfStrikeOut in PFType];
StrPCopy(lfFaceName,'宋体');
end;
Result := CreateFontIndirect(fLogFont);
end;procedure TTextObject.MessageFocusEnter(var Msg: TMessage);
begin
if FEditing then Exit;
Selected := True;
end;procedure TTextObject.MessageFocusExit(var Msg: TMessage);
begin
if FEditing then Exit;
Selected := False;
end;procedure TTextObject.MouseDoubleClick(Sender: TObject);
begin
EditText;
end;procedure TTextObject.MouseDown(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
begin
GetCursorPos(FOldPos); //保存开始移动时鼠标全局坐标
FMouseDownArea := CheckEdge(Point(X,Y)); //计算区域
Selected := True;
end;procedure TTextObject.MouseDragMoveResize(CtrHandle: Integer); //通过鼠标拖啦移动或改变对象大小
var
NewPos: TPoint;
begin
if Cursor <> Cursor_Type[CtrHandle] then
Cursor := Cursor_Type[CtrHandle]; //换鼠标形状
GetCursorPos(NewPos); //取鼠标全局位置
try
if NewPos.x <> FOldPos.x then
begin
case CtrHandle of
0,1,8: SetBounds(Left + NewPos.x - FOldPos.x,Top,Width,Height);
7: SetBounds(Left + (NewPos.x - FOldPos.x),Top,Width,Height);
end;
case CtrHandle of
1,7,8: Width := Width - (NewPos.x - FOldPos.x);
3,4,5: Width := Width + (NewPos.x - FOldPos.x);
end;
end;
if NewPos.y <> FOldPos.y then
begin
case CtrHandle of
0,1,2,3: Top := Top + NewPos.y - FOldPos.y;
end;
case CtrHandle of
1,2,3: Height := Height - (NewPos.y - FOldPos.y);
5,6,7: Height := Height + (NewPos.y - FOldPos.y);
end;
end;
finally
FOldPos := NewPos;
end;
end;procedure TTextObject.MouseMove(Sender: TObject; Shift: TShiftState; X,Y: Integer);
begin
if ssLeft in Shift then
begin
//左键按下进行拖拉移动操作
MouseDragMoveResize(FMouseDownArea);
end
else
begin
//检查位置更换鼠标形状
if Cursor <> Cursor_Type[CheckEdge(Point(X,Y))] then
Cursor := Cursor_Type[CheckEdge(Point(X,Y))];
end;
end;procedure TTextObject.MouseUp(Sender: TObject; Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
begin
if Cursor <> crDefault then
Cursor := crDefault;
end;procedure TTextObject.Paint;
var
Rect: TRect;
begin
with Canvas do
begin
Brush.Style := bsClear;
FillRect(ClientRect);
Rect := FClientRect;
Font := Self.Font;
DrawText(Handle,PChar(Caption),Length(Caption),Rect, DT_LEFT);
end; if FSelected then
DrawCtHandle;
end;
function TTextObject.PointToInch(Value: SmallInt): Byte;
begin
Result := (Value div 70) AND $FF;
end;procedure TTextObject.Resize(Sender: TObject); //计算八个操控句柄位置
var
ii: Integer;
function GetDrawRect(X,Y: Integer): TRect;
begin
Result := Rect(X - CTH_SIZE,Y - CTH_SIZE,X + CTH_SIZE,Y + CTH_SIZE);
end;
begin
if Width < (3 * CTH_SIZE + 20) then
Width := CTH_SIZE * 3 + 20;
if Height < (3 * CTH_SIZE + 10) then
Height := CTH_SIZE * 3 + 10; FClientRect := Rect(ClientRect.Left + CTH_SIZE,
ClientRect.Top + CTH_SIZE,
ClientRect.Right - CTH_SIZE,
ClientRect.Bottom - CTH_SIZE);
if Assigned(FEdit) then
with FEdit do
begin
Left := FClientRect.Left;
Top := FClientRect.Top;
Width := FClientRect.Right - Left;
Height := FClientRect.Bottom - Top;
end; FSmallRect[1] := GetDrawRect(CTH_SIZE,CTH_SIZE);
FSmallRect[2] := GetDrawRect((Width - 1) div 2,CTH_SIZE);
FSmallRect[3] := GetDrawRect(Width - CTH_SIZE - 1,CTH_SIZE);
FSmallRect[4] := GetDrawRect(Width - CTH_SIZE - 1 ,(Height - 1) div 2);
FSmallRect[5] := GetDrawRect(Width - CTH_SIZE - 1,Height - CTH_SIZE - 1);
FSmallRect[6] := GetDrawRect((Width - 1) div 2,Height - CTH_SIZE - 1);
FSmallRect[7] := GetDrawRect(CTH_SIZE,Height - CTH_SIZE - 1);
FSmallRect[8] := GetDrawRect(CTH_SIZE,(Height - 1) div 2);
end;procedure TTextObject.SetActive(const Value: Boolean);
begin
if FActive <> Value then
begin
FActive := Value;
Invalidate;
end;
end;procedure TTextObject.SetCharSpacing(const Value: Byte);
begin
FCharSpacing := InchToPoint(Value);
Invalidate;
end;procedure TTextObject.SetPrintFont(const Value: TPrintFont);
var
iW,iH: Integer;
begin
//if FPrintFont <> Value then
begin
FPrintFont := Value;
Font.Handle := MakeLogFont(FPrintFont);
Canvas.Font := Font;
//重新计算大小 begin
iH := Canvas.TextHeight(Caption) + 2 * CTH_SIZE;
iW := Canvas.TextWidth(Caption) + 2 * CTH_SIZE;
if iW > Width then
Width := iW;
if iH > Height then
Height := iH;
end;
end;
end;procedure TTextObject.SetSelected(const Value: Boolean);
begin
if FSelected <> Value then
begin
FSelected := Value;
Invalidate;
if Selected AND Assigned(FOnSelected) then
FOnSelected(Self);
end;
end;procedure TTextObject.UnLock;
begin
DragMode := dmAutomatic;
end;end.