给你个橡皮条先,你拖动任何对象时,总得给出一个虚框吧:unit TrackerBand;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs;type TForm1 = class(TForm) procedure FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); private { Private declarations } public { Public declarations } end;var Form1: TForm1;implementation{$R *.dfm} type TDrawFlag = (dfToDraw,dfDrawing,dfDrawn); var TrackerBrush: TBrush = Nil; TrackerPen: TPen = Nil; HalfToneBrush:TBrush = Nil; OldDragRect: TRect = (Left:0;Top:0;Right:0;Bottom:0); procedure InitHalfToneBrush; var grayPattern:array[0..7] of WORD; grayBitmap:HBITMAP; I:Integer; begin if HalfToneBrush = Nil then begin HalfToneBrush := TBrush.Create; for I := 0 to 7 do grayPattern[i] := WORD(($5555 shl (I and 1))); grayBitmap := Windows.CreateBitmap(8, 8, 1, 1, @grayPattern); if (grayBitmap <> 0) then begin HalftoneBrush.Handle := Windows.CreatePatternBrush(grayBitmap); Windows.DeleteObject(grayBitmap); end; end; end;procedure DrawDragRect(DC:HDC;NewRect:TRect;DragFlag:TDrawFlag;BandWidth:Integer = 3); var rgnNew,rgnOld,rgnTemp:HRGN; SaveIndex: Integer; TempRect: TRect; begin SaveIndex := Windows.SaveDC(DC); try { Get the region which is the old border } if DragFlag = dfToDraw then rgnOld := 0 else begin TempRect := OldDragRect; rgnTemp := Windows.CreateRectRgnIndirect(TempRect); Windows.InflateRect(TempRect,BandWidth,BandWidth); rgnOld := Windows.CreateRectRgnIndirect(TempRect); Windows.CombineRgn(rgnOld,rgnOld,rgnTemp,RGN_XOR); Windows.DeleteObject(HRGN(rgnTemp)); end; { Get the region which is the new border } if DragFlag = dfDrawn then rgnNew := 0 else begin TempRect := NewRect; //RectNormalize(TempRect); OldDragRect := TempRect; rgnTemp := Windows.CreateRectRgnIndirect(TempRect); Windows.InflateRect(TempRect,BandWidth,BandWidth); rgnNew := Windows.CreateRectRgnIndirect(TempRect); Windows.CombineRgn(rgnNew,rgnNew,rgnTemp,RGN_XOR); Windows.DeleteObject(HRGN(rgnTemp)); end; { Get the different region between new and old } if rgnNew = 0 then rgnNew := Windows.CreateRectRgn(0,0,0,0); Windows.CombineRgn(rgnNew,rgnNew,rgnOld,RGN_XOR); { Draw into the border region which need to be updated } Windows.SelectClipRgn(DC,rgnNew); Windows.GetClipBox(DC,TempRect); Windows.SelectObject(DC,HalfToneBrush.Handle); with TempRect do Windows.PatBlt(DC,Left,Top,Right-Left,Bottom-Top,PATINVERT); if rgnOld <> 0 then Windows.DeleteObject(HRGN(rgnOld)); if rgnNew <> 0 then Windows.DeleteObject(HRGN(rgnNew)); { Remove the clip region } Windows.SelectClipRgn(DC,0); finally Windows.RestoreDC(DC,SaveIndex); end; end; procedure InitGlobalObjects; var HatchPattern: Array[0..7] of WORD; WPattern: WORD; I: Integer; HatchBitmap:HBITMAP; begin WPattern := $1111; if TrackerBrush = Nil then begin TrackerBrush := TBrush.Create; {Create the hatch pattern + bitmap} for I := 0 to 3 do begin HatchPattern[i] := WPattern; HatchPattern[i+4] := WPattern; WPattern := WPattern shl 1; end; HatchBitmap := Windows.CreateBitmap(8, 8, 1, 1, @HatchPattern); if HatchBitmap <> 0 then begin { Create black hatched brush } TrackerBrush.Handle := Windows.CreatePatternBrush(HatchBitmap); Windows.DeleteObject(HatchBitmap); end; if TrackerPen = Nil then begin TrackerPen := TPen.Create; {create black dotted pen} TrackerPen.Handle := CreatePen(PS_DOT, 0, RGB(0, 0, 0)); end; end; InitHalfToneBrush; OldDragRect := Rect(0,0,0,0); end;procedure ReleaseGlobalObjects; begin if HalfToneBrush <> Nil then HalfToneBrush.Free; if TrackerBrush <> Nil then TrackerBrush.Free; if TrackerPen <> Nil then TrackerPen.Free; end;procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin DrawDragRect(Canvas.Handle,Rect(X,Y,X,Y),dfToDraw,4); end;procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if ssLeft in Shift then DrawDragRect(Canvas.Handle,Rect(OldDragRect.Left,OldDragRect.Top,X,Y),dfDrawing,4); end;procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin DrawDragRect(Canvas.Handle,Rect(OldDragRect.Left,OldDragRect.Top,X,Y),dfDrawn,4); end;Initialization InitGlobalObjects; finalization ReleaseGlobalObjects;end.
到这里下个编辑平台,增加一点感性认识,很快就会了。
你以为你随便写一写就能实现这么麻烦的功能吗?如果仅仅是画一个小小的矩形,然后再使用鼠标拖动,改变大小的话,写写代码就可以实现,你做的东西总不至于是仅仅在Canvas上画一个矩形吧,你怎么也要考虑可以画圆,画矩形,画椭圆,画线,然后拖动,更改大小,删除,随随便便的写一些代码,会死人的。
你首先需要申请一块内存,内存中存储各个图形的性质,比如图形类型,中心位置,长度,宽度等等等等。然后在鼠标移动的时候,马上去内存中找,是否鼠标在一个图形的框上,如果在的话,立马更改图标,然后等待用户按下鼠标。
在用户按下鼠标的时候还需要有一个状态,标记当前是否选择了图形,并判断用户的操作(你还需要在上面放上一堆的快捷按钮,表示是移动,更改大小等)。
在判断用户的操作后,你才开始完成画新图形的功能,就是说,首先将原来的图形擦除(使用背景色重新画原来图形),然后再在新位置画新的图形。每次鼠标移动都要擦除和画。一直到用户鼠标放开为止。这样就完成了修改大小的功能。
但是,这些就够了吗?错,如果Canvas上有很多其他的图形,由于你擦除的时候是使用Canvas在上面画背景色的圆图形,如果要画的图形和别的图形有交叉,你在画背景色图形(擦除)的时候就把原来的图形擦除了。因此在擦除后你还需要判断是否有交叉的图形。如果有你还要画其他的图形。
图形移动也是这样的原理,相对简单一些。不过如果你想做的好,同样需要考虑这些问题。
另外,你还要考虑算法的问题。如果上面有10000个图形,且有些是交叉的,这样你在重新画的时候又要擦除,又要画新的,还要画旧的,你看看你的算法是否在用户忍受的时间中完成。
然后总体的思路就出来了:首先申请两个内存,一个存储当前的界面上有多少个图形,并给出图形的Rect范围(判断是否交叉),一个存储各个图形的参数。然后在鼠标移动的时候(如果键没有按下)判断是否移动到某一个图形的边界,或者如果用户选择移动的话判断用户选择的是哪一个图形(靠,更麻烦,因为如果图形交叉的话,你怎么判断?是否还要设置哪个图形在前面,哪个图形在后面?),并更改鼠标的样式。如果按键有按下,判断是否是更改大小或者移动位置。然后对鼠标的移动写程序(画旧的,画新的,画原来的)。
当然你还要考虑一个问题,就是Form.Canvas属性是不具有Paint功能的,就是说你在Form.Canvas上画一个图形,然后使用其他的界面覆盖该Form,然后在显示该Form,图形就没有了,因此你还有考虑Form的Repaint的时候该怎么办。
干脆你把需求给我详细描述一下,我帮你写一个框架算了。
针对你的要求
1.你需要在内存中有一个变量能够保存你当前画的矩形的参数.这一点想必你是有的.
2.当鼠标触发了MouseDown事件时,你需要根据鼠标的位置进行选中操作.针对你目前的要求,也就是调用一下PointInRect函数而已.
3.如果选中,则你的作法是在矩形的四个角再把四个小符号标记出来,对吧.但是你要有个变量记住,当前处于选中状态.
4.当你的鼠标再次触发MouseDown时,你需要判断当前是否处于选中状态,如果处于选中状态,你则需进一步判断是当前的鼠标位置是否又选中了你的矩形的四个角.如果选中则需要把这个状态记下来,或都说你的操作当前的状态的变化由一开始的图形选中,到编辑点的选中进入了编辑状态.
5.当你的鼠标处于编辑状态时,鼠标在移动的时候最好能够画出当前的图形的样子,这需要使用异或模式作图.
6异或模式的基本思路是,当你进入编辑状态以后,就需要把画笔设为异或模式.
然后在每次移动时用你鼠标选中点的对角点和鼠标的当前点画一个矩形,但是注意需要画两次,就是说你需要记住上一次MouseMove事件中的点的位置,首先用上一个位置画一次,由于是异或模式,因此刚好是把上一次画的图去除,再在新的位置上画一次.
7.你需要处理MouseUp事件,在MouseUp事件中,再把前面的图擦掉,最好把画笔改成原来的模式画出新的矩形.
8.简单的图形编辑就是这样了.
当然如果你需要处理大量的图形就不是这样简单了.
如果你确实需要处理大量的图形,建议你寻找专业的组件.我上面说的那个就不错.
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;type
TForm1 = class(TForm)
procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
procedure FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}
type
TDrawFlag = (dfToDraw,dfDrawing,dfDrawn);
var
TrackerBrush: TBrush = Nil;
TrackerPen: TPen = Nil;
HalfToneBrush:TBrush = Nil;
OldDragRect: TRect = (Left:0;Top:0;Right:0;Bottom:0);
procedure InitHalfToneBrush;
var grayPattern:array[0..7] of WORD;
grayBitmap:HBITMAP;
I:Integer;
begin
if HalfToneBrush = Nil then
begin
HalfToneBrush := TBrush.Create;
for I := 0 to 7 do
grayPattern[i] := WORD(($5555 shl (I and 1)));
grayBitmap := Windows.CreateBitmap(8, 8, 1, 1, @grayPattern);
if (grayBitmap <> 0) then
begin
HalftoneBrush.Handle := Windows.CreatePatternBrush(grayBitmap);
Windows.DeleteObject(grayBitmap);
end;
end;
end;procedure DrawDragRect(DC:HDC;NewRect:TRect;DragFlag:TDrawFlag;BandWidth:Integer = 3);
var rgnNew,rgnOld,rgnTemp:HRGN;
SaveIndex: Integer;
TempRect: TRect;
begin
SaveIndex := Windows.SaveDC(DC);
try
{ Get the region which is the old border }
if DragFlag = dfToDraw then rgnOld := 0
else begin
TempRect := OldDragRect;
rgnTemp := Windows.CreateRectRgnIndirect(TempRect);
Windows.InflateRect(TempRect,BandWidth,BandWidth);
rgnOld := Windows.CreateRectRgnIndirect(TempRect);
Windows.CombineRgn(rgnOld,rgnOld,rgnTemp,RGN_XOR);
Windows.DeleteObject(HRGN(rgnTemp));
end; { Get the region which is the new border }
if DragFlag = dfDrawn then rgnNew := 0
else begin
TempRect := NewRect;
//RectNormalize(TempRect);
OldDragRect := TempRect;
rgnTemp := Windows.CreateRectRgnIndirect(TempRect);
Windows.InflateRect(TempRect,BandWidth,BandWidth);
rgnNew := Windows.CreateRectRgnIndirect(TempRect);
Windows.CombineRgn(rgnNew,rgnNew,rgnTemp,RGN_XOR);
Windows.DeleteObject(HRGN(rgnTemp));
end; { Get the different region between new and old }
if rgnNew = 0 then rgnNew := Windows.CreateRectRgn(0,0,0,0);
Windows.CombineRgn(rgnNew,rgnNew,rgnOld,RGN_XOR); { Draw into the border region which need to be updated }
Windows.SelectClipRgn(DC,rgnNew);
Windows.GetClipBox(DC,TempRect);
Windows.SelectObject(DC,HalfToneBrush.Handle);
with TempRect do
Windows.PatBlt(DC,Left,Top,Right-Left,Bottom-Top,PATINVERT); if rgnOld <> 0 then Windows.DeleteObject(HRGN(rgnOld));
if rgnNew <> 0 then Windows.DeleteObject(HRGN(rgnNew)); { Remove the clip region }
Windows.SelectClipRgn(DC,0);
finally
Windows.RestoreDC(DC,SaveIndex);
end;
end;
procedure InitGlobalObjects;
var
HatchPattern: Array[0..7] of WORD;
WPattern: WORD;
I: Integer;
HatchBitmap:HBITMAP;
begin
WPattern := $1111;
if TrackerBrush = Nil then
begin
TrackerBrush := TBrush.Create;
{Create the hatch pattern + bitmap}
for I := 0 to 3 do
begin
HatchPattern[i] := WPattern;
HatchPattern[i+4] := WPattern;
WPattern := WPattern shl 1;
end; HatchBitmap := Windows.CreateBitmap(8, 8, 1, 1, @HatchPattern);
if HatchBitmap <> 0 then
begin
{ Create black hatched brush }
TrackerBrush.Handle := Windows.CreatePatternBrush(HatchBitmap);
Windows.DeleteObject(HatchBitmap);
end; if TrackerPen = Nil then
begin
TrackerPen := TPen.Create;
{create black dotted pen}
TrackerPen.Handle := CreatePen(PS_DOT, 0, RGB(0, 0, 0));
end;
end; InitHalfToneBrush;
OldDragRect := Rect(0,0,0,0);
end;procedure ReleaseGlobalObjects;
begin
if HalfToneBrush <> Nil then HalfToneBrush.Free;
if TrackerBrush <> Nil then TrackerBrush.Free;
if TrackerPen <> Nil then TrackerPen.Free;
end;procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
DrawDragRect(Canvas.Handle,Rect(X,Y,X,Y),dfToDraw,4);
end;procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if ssLeft in Shift then
DrawDragRect(Canvas.Handle,Rect(OldDragRect.Left,OldDragRect.Top,X,Y),dfDrawing,4);
end;procedure TForm1.FormMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
DrawDragRect(Canvas.Handle,Rect(OldDragRect.Left,OldDragRect.Top,X,Y),dfDrawn,4);
end;Initialization
InitGlobalObjects;
finalization
ReleaseGlobalObjects;end.
各位不要发垃圾邮件给我阿,谢谢 taxi(游少爷)