关于自定义的shape控件响应热点和平滑拖放的问题(300分)

陈晨

Unregistered / Unconfirmed
GUEST, unregistred user!
我想自己做的shape控件具备如下功能,热点事件响应,
2,运行时可以像设计期一样平滑移动无闪烁,
Perform是在tcontrol里面定义的可是shape 里面应用却不可以,
twincontrol(shape).perform()不能用。
鼠标事件(如何)重载,
在线等待,
 
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls;

type
TForm1 = class(TForm)
Panel1: TPanel;
Button1: TButton;
procedure Panel1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure Button1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Panel1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
const
SC_DragMove = $F012; { a magic number }
begin
ReleaseCapture;
panel1.perform(WM_SysCommand, SC_DragMove, 0);
end;


procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
{$IFNDEF WIN32}
var
pt : TPoint;
{$ENDIF}
begin
if ssCtrl in Shift then begin
ReleaseCapture;
SendMessage(Button1.Handle, WM_SYSCOMMAND, 61458, 0);
{$IFNDEF WIN32}
GetCursorPos(pt);
SendMessage(Button1.Handle, WM_LBUTTONUP,MK_CONTROL,Longint(pt));
{$ENDIF}
end;
end;


end.
 
对于shape 不起作用
 
unit ZWShape;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls;

const MAX_STATION = 8;

type

TZWShape = class(TShape)
private
{ Private declarations }
old_x,old_y: integer;
can_move: boolean;
PicLeft,PicTop,TexLeft,TexTop: integer;
//ImgRect: TRect;

FPicture: TPicture;
FNumber: Cardinal;
FTouch: TNotifyEvent;

procedure SetPicture(Value: TPicture);
procedure SetNumber(Value: Cardinal);
//procedure WMEraseBkgnd(var Msg: TMessage); message WM_ERASEBKGND;
//procedure WMSize(var Msg: TWMSize); message WM_SIZE;
protected
{ Protected declarations }
procedure Paint; override;

public
{ Public declarations }
TextX, TextY: integer;
//Ctr: Ctr_T;
neighbor_x,neighbor_y:integer;
constructor Create(AOwner: TComponent);override;
destructor Destroy;override;
procedure MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);override;
procedure MouseUp(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);override;
procedure MouseMove(Shift: TShiftState; X,
Y: Integer); override;
function CenterX:integer;
function CenterY:integer;
published
{ Published declarations }
property Picture: TPicture read FPicture write SetPicture;
property Number: Cardinal read FNumber write SetNumber default 0;
property OnTouch : TNotifyEvent read FTouch write FTouch;
end;

procedure Register;

implementation

procedure Register;
begin
RegisterComponents('220', [TZWShape]);
end;

constructor TZWShape.Create(AOwner: TComponent);
begin

inherited Create(AOwner);
can_move := false;
FPicture := TPicture.Create;
Shape := stCircle;
Canvas.Font.Color := ClWhite;
Canvas.Font.Style := Canvas.Font.Style + [fsBold];
TextX := 0;
TextY := 0;
TexLeft := width div 2 - Canvas.Font.Height div 2 + TextX;
TexTop := height div 2 - Canvas.Font.Size div 2 + TextY;

end;


procedure TZWShape.MouseDown(Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
begin
old_x := x;
old_y := y;
can_move := true;
cursor := crSizeAll;
if assigned(OnMouseDown) then OnMouseDown(self,Button,shift,x,y);
end;

procedure TZWShape.MouseUp(Button: TMouseButton;Shift: TShiftState; X, Y: Integer);
begin

can_move := false;
cursor := crDefault;;
if assigned(OnMouseUp) then OnMouseUp(self,Button,shift,x,y);

end;

procedure TZWShape.MouseMove(Shift: TShiftState; X,
Y: Integer);
{var TemShape: TZWShape;
i: integer;}
begin
cursor := crSizeAll;
if can_move then
begin
Left := Left+x-old_x;
Top := Top+y-old_y;
end;

{for i:=0 to parent.ComponentCount-1 do
begin
if parent.Components.ClassName = 'TZWShape' then
begin
TemShape:= (parent.Components as TZWShape);
if TemShape.Number <> Number then
begin
neighbor_x := TemShape.CenterX;
neighbor_y := TemShape.CenterY;
if assigned(OnTouch) then OnTouch(self);
end;
end;
end;}

if assigned(OnMouseMove) then OnMouseMove(self,shift,x,y);

end;

procedure TZWShape.Paint;
var
SavedBrushStyle : TBrushStyle;
SavedBrushColor: TColor;
begin
SavedBrushStyle := Canvas.Brush.Style;
SavedBrushColor := Canvas.Brush.Color;
try
Canvas.Brush.Style := bsCross;
Canvas.Brush.Color := RGB(50,190,60);//clGreen;
Canvas.Pen.Color := RGB(50,190,60); //clGreen;
Canvas.Ellipse(ClientRect);

if assigned(FPicture) then
begin
//Canvas.StretchDraw(ImageRect,FPicture.Graphic);
Canvas.Draw(PicLeft,PicTop,Fpicture.Bitmap);

Canvas.TextOut(TexLeft,TexTop,inttostr(FNumber));
//if assigned(OnTouch) then OnTouch(self);
end;
finally
Canvas.Brush.Style := SavedBrushStyle;
Canvas.Brush.Color := SavedBrushColor;
end;
end;

{procedure TZWShape.WMSize(var Msg: TWMSize);
begin
inherited;
DeleteObject(FHRgn);
FHRgn := CreateEllipticRgn(ClientRect.Left, ClientRect.Top,
ClientRect.Right, ClientRect.Bottom);
SetWindowRgn(Handle, FHRgn, True);
end;}

procedure TZWShape.SetPicture(Value: TPicture);
begin

FPicture.Assign(Value);

//set transparent
Fpicture.Bitmap.TransparentMode := tmAuto;
Fpicture.Bitmap.TransparentColor := Fpicture.BitMap.canvas.pixels[5,5];
Fpicture.Bitmap.Transparent := true;

PicLeft := width div 2 - Value.Bitmap.Width div 2;
PicTop := height div 2 - Value.Bitmap.Height div 2;

TexLeft := width div 2 - Canvas.Font.Height div 2 + TextX;
TexTop := height div 2 - Canvas.Font.Size div 2 + TextY;

invalidate;

end;

procedure TZWShape.SetNumber(Value: Cardinal);
begin
FNumber := value;
end;

{procedure TZWShape.WMEraseBkgnd(var Msg: TMessage);
begin

inherited;
if assigned(OnTouch) then OnTouch(self);
end;}

function TZWShape.CenterX:integer;
begin
Result:=left + (width div 2);
end;

function TZWShape.CenterY:integer;
begin
Result:=top + (height div 2);
end;

destructor TZWShape.Destroy;
begin
FPicture.Free;
inherited Destroy;
end;

end.
 
TWinControl.perform(WM_SysCommand, $F012, 0);可以移动,但对TGraphicControl不起作用。
但可以用上面的笨办法,无论对TWinControl或TGraphicControl都有效。

另外要想拖动时无闪烁,应使TShape.parent.doublebuffered:=true;
 
如何在控件中实现热点呢?如何重载鼠标事件?(是不是要拦截鼠标事件?)
 
你没有看到上面代码中的:
procedure MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);override;
procedure MouseUp(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);override;
procedure MouseMove(Shift: TShiftState; X,
Y: Integer); override;
这就是重载鼠标事件。
实现热点,在MouseMove中处理就是了。
 
to:zw84611
谢谢呵呵呵。见面请你吃饭
 
顶部