人
人生如路
Unregistered / Unconfirmed
GUEST, unregistred user!
控件要实现的功能:
。在运行时有设计时效果,即是可以拖动,可以改变大小;
。控件的外表,主要要求两个形状,一是圆,一是矩形;
。控件要求透明;
源代码如下:===========================================
unit DesignbleShape;
interface
uses
Classes, Windows, Messages, Controls, StdCtrls, Graphics, ExtCtrls, Dialogs,
Themes;
const
sc_DragMove: Longint = $F012;
WM_RbsInvalidate=WM_USER+1;
type
TDesignbleShape = class (TCustomControl)
private
FRectList: array [1..8] of TRect;
FPosList: array [1..8] of Integer;
FShape: TShapeType;
FBrush: TBrush;
FPen: TPen;
FPointColor: TColor;
procedure SetShape(const Value: TShapeType);
procedure SetBrush(const Value: TBrush);
procedure SetPen(const Value: TPen);
procedure SetPointColor(const Value: TColor);
procedure WmNcHitTest(var Msg: TWMNCHitTest); message wm_NcHitTest;
procedure WmSize(var Msg: TWMSize); message wm_Size;
procedure WmLButtonDown(var Msg: TWMLButtonDown); message wm_LButtonDown;
procedure WmMove(var Msg: TWMMove); message wm_Move;
procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;
procedure RbsInvalidate(var Message:TMessage); message WM_RbsInvalidate;
procedure CNCTLCOLOREDIT(var Message:TWMCTLCOLOREDIT); message CN_CTLCOLOREDIT;
procedure DoDrawBakground;
protected
procedure StyleChanged(Sender: TObject);
procedure CreateParams(var Params: TCreateParams); override;
procedure CreateHandle; override;
procedure CreateWnd; override;
procedure Do_Size;
procedure Paint; override;
public
constructor Create(AOwner: TComponent);override;
destructor Destroy;override;
property Shape: TShapeType read FShape write SetShape;
property Pen: TPen read FPen write SetPen;
property Brush: TBrush read FBrush write SetBrush;
property PointColor: TColor read FPointColor write SetPointColor;
property OnClick;
end;
implementation
// TDdhSizerControl methods
constructor TDesignbleShape.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle - [csOpaque];
Height := 100;
Width := 100;
FShape := stRectangle;
//create the list of positions
FPosList [1] := htTopLeft;
FPosList [2] := htTop;
FPosList [3] := htTopRight;
FPosList [4] := htRight;
FPosList [5] := htBottomRight;
FPosList [6] := htBottom;
FPosList [7] := htBottomLeft;
FPosList [8] := htLeft;
//
FPen := TPen.Create;
FPen.OnChange := StyleChanged;
FBrush := TBrush.Create;
FBrush.OnChange := StyleChanged;
FPointColor := clBlack;
//ParentBackground := False;
end;
procedure TDesignbleShape.CreateHandle;
begin
inherited CreateHandle;
SetFocus;
end;
procedure TDesignbleShape.CreateParams (var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle + ws_ex_Transparent;
end;
procedure TDesignbleShape.Paint;
var
I: Integer;
X, Y, W, H, S: Integer;
begin
DoDrawBakground;
with Canvas do
begin
Canvas.Brush.Color := clNone;
Canvas.Brush.Style := bsClear;
FillRect(ClientRect);
Pen.Assign(FPen);
Brush.Assign(FBrush);
X := Pen.Width div 2;
Y := X;
W := Width - Pen.Width + 1;
H := Height - Pen.Width + 1;
if Pen.Width = 0 then
begin
Dec(W);
Dec(H);
end;
if W < H then S := W else S := H;
if FShape in [stSquare, stRoundSquare, stCircle] then
begin
Inc(X, (W - S) div 2);
Inc(Y, (H - S) div 2);
W := S;
H := S;
end;
case FShape of
stRectangle, stSquare:
Rectangle(X, Y, X + W, Y + H);
stRoundRect, stRoundSquare:
RoundRect(X, Y, X + W, Y + H, S div 4, S div 4);
stCircle, stEllipse:
Ellipse(X, Y, X + W, Y + H);
end;
end;
Canvas.Brush.Color := PointColor;
Canvas.Brush.Style := bsSolid;
Canvas.Pen.Color := PointColor;
for I := 1 to 8 do
Canvas.Rectangle (FRectList .Left, FRectList .Top,
FRectList .Right, FRectList .Bottom);
end;
procedure TDesignbleShape.WmNcHitTest(var Msg: TWMNCHitTest);
var
Pt: TPoint;
I: Integer;
begin
inherited;
Pt := Point (Msg.XPos, Msg.YPos);
Pt := ScreenToClient (Pt);
Msg.Result := 0;
for I := 1 to 8 do
if PtInRect(FRectList, Pt) then
Msg.Result := FPosList ;
// if the return value was not set
if Msg.Result = 0 then
inherited;
end;
procedure TDesignbleShape.WmSize (var Msg: TWMSize);
begin
//inherited;
Do_Size;
end;
procedure TDesignbleShape.WmLButtonDown (var Msg: TWMLButtonDown);
begin
Perform(WM_SYSCOMMAND, sc_DragMove, 0);
end;
procedure TDesignbleShape.WmMove (var Msg: TWMMove);
begin
PostMessage(Handle, WM_RbsInvalidate,0,0)
//Paint;
end;
procedure TDesignbleShape.SetShape(const Value: TShapeType);
begin
if FShape <> Value then
begin
FShape := Value;
Invalidate;
end;
end;
procedure TDesignbleShape.SetBrush(const Value: TBrush);
begin
FBrush.Assign(Value);
end;
procedure TDesignbleShape.SetPen(const Value: TPen);
begin
FPen.Assign(Value);
end;
destructor TDesignbleShape.Destroy;
begin
FPen.Free;
FBrush.Free;
inherited;
end;
procedure TDesignbleShape.StyleChanged(Sender: TObject);
begin
Invalidate;
end;
procedure TDesignbleShape.SetPointColor(const Value: TColor);
begin
FPointColor := Value;
end;
procedure TDesignbleShape.Do_Size;
begin
//setup data structures
FRectList [1] := Rect(0, 0, 8, 8);
FRectList [2] := Rect(Width div 2 - 4, 0, Width div 2 + 4, 8);
FRectList [3] := Rect(Width - 8, 0, Width, 8);
FRectList [4] := Rect(Width - 8, Height div 2 - 4, Width, Height div 2 + 4);
FRectList [5] := Rect(Width - 8, Height - 8, Width, Height);
FRectList [6] := Rect(Width div 2 - 4, Height - 8, Width div 2 + 4, Height);
FRectList [7] := Rect(0, Height - 8, 8, Height);
FRectList [8] := Rect(0, Height div 2 - 4, 8, Height div 2 + 4);
end;
procedure TDesignbleShape.DoDrawBakground;
var
DesktopDC : HDC;
SelfDC : HDC;
ARect: TRect;
begin
DesktopDC := GetDC(0);
try
SelfDC := GetDC(Self.Handle);
try
ARect := GetClientRect;
Windows.ClientToScreen(Self.Handle, ARect.TopLeft);
Windows.ClientToScreen(Self.Handle, ARect.BottomRight);
BitBlt(SelfDC, 0, 0, Width, Height, DesktopDC, ARect.Left, ARect.Top, SRCCOPY);
finally
ReleaseDC(Self.Handle, SelfDC);
end;
finally
ReleaseDC(0, DesktopDC);
end;
end;
procedure TDesignbleShape.WMEraseBkgnd(var Message: TWmEraseBkgnd);
begin
//Message.Result := 1;
PostMessage(Handle, WM_RbsInvalidate,0,0)
end;
procedure TDesignbleShape.CNCTLCOLOREDIT(var Message: TWMCTLCOLOREDIT);
begin
// SetBkMode(ChildDC,Windows.TRANSPARENT);
// Result:=GetStockObject(HOLLOW_BRUSH)
end;
procedure TDesignbleShape.RbsInvalidate(var Message: TMessage);
var
R: TRect;
begin
if Parent <> nil then
begin
R:= ClientRect;
R.TopLeft := Parent.ScreenToClient(ClientToScreen(R.TopLeft));
R.BottomRight := Parent.ScreenToClient(ClientToScreen(R.BottomRight));
RedrawWindow(Handle,nil,0, RDW_FRAME + RDW_INVALIDATE);
end;
end;
procedure TDesignbleShape.CreateWnd;
begin
inherited;
SetWindowLong(Parent.Handle, GWL_STYLE, GetWindowLong(Parent.Handle, GWL_STYLE) and not WS_CLIPCHILDREN);
end;
end.
调用代码:========================================================
objDesignbleShape := TDesignbleShape.Create(Self);
objDesignbleShape.Parent := ScrollBox1;
objDesignbleShape.Top := 50;
objDesignbleShape.Left := 50;
objDesignbleShape.Height := 250;
objDesignbleShape.Width := 250;
objDesignbleShape.Pen.Width := 2;
objDesignbleShape.Pen.Color := clRed;
objDesignbleShape.Brush.Color := clWhite;
objDesignbleShape.Brush.Style := bsClear;
objDesignbleShape.PointColor := clYellow;
objDesignbleShape.Cursor := crSizeAll;
========================================================
现在的问题:
。要求一已实现,运行时有设计时效果;
。要求二也实现,为了简单,我只是简单的用了TShape的源码;
。要求三,在用鼠标点在八个点上面,可以改变大不,控件也是透明的;但是,在移动的时候,却不能做到透明;
其它现象:
。更改Shape值的时候,也不能透明;移动控件的时候,也不能透明;不透明的时候,用另外的Form挡它一下,再移开,它就透明了;
小弟想了很多办法了,实在是水平有限,怎么也试不出来。希望熟悉的朋友不吝赐教,先谢谢了。。。
。在运行时有设计时效果,即是可以拖动,可以改变大小;
。控件的外表,主要要求两个形状,一是圆,一是矩形;
。控件要求透明;
源代码如下:===========================================
unit DesignbleShape;
interface
uses
Classes, Windows, Messages, Controls, StdCtrls, Graphics, ExtCtrls, Dialogs,
Themes;
const
sc_DragMove: Longint = $F012;
WM_RbsInvalidate=WM_USER+1;
type
TDesignbleShape = class (TCustomControl)
private
FRectList: array [1..8] of TRect;
FPosList: array [1..8] of Integer;
FShape: TShapeType;
FBrush: TBrush;
FPen: TPen;
FPointColor: TColor;
procedure SetShape(const Value: TShapeType);
procedure SetBrush(const Value: TBrush);
procedure SetPen(const Value: TPen);
procedure SetPointColor(const Value: TColor);
procedure WmNcHitTest(var Msg: TWMNCHitTest); message wm_NcHitTest;
procedure WmSize(var Msg: TWMSize); message wm_Size;
procedure WmLButtonDown(var Msg: TWMLButtonDown); message wm_LButtonDown;
procedure WmMove(var Msg: TWMMove); message wm_Move;
procedure WMEraseBkgnd(var Message: TWmEraseBkgnd); message WM_ERASEBKGND;
procedure RbsInvalidate(var Message:TMessage); message WM_RbsInvalidate;
procedure CNCTLCOLOREDIT(var Message:TWMCTLCOLOREDIT); message CN_CTLCOLOREDIT;
procedure DoDrawBakground;
protected
procedure StyleChanged(Sender: TObject);
procedure CreateParams(var Params: TCreateParams); override;
procedure CreateHandle; override;
procedure CreateWnd; override;
procedure Do_Size;
procedure Paint; override;
public
constructor Create(AOwner: TComponent);override;
destructor Destroy;override;
property Shape: TShapeType read FShape write SetShape;
property Pen: TPen read FPen write SetPen;
property Brush: TBrush read FBrush write SetBrush;
property PointColor: TColor read FPointColor write SetPointColor;
property OnClick;
end;
implementation
// TDdhSizerControl methods
constructor TDesignbleShape.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ControlStyle := ControlStyle - [csOpaque];
Height := 100;
Width := 100;
FShape := stRectangle;
//create the list of positions
FPosList [1] := htTopLeft;
FPosList [2] := htTop;
FPosList [3] := htTopRight;
FPosList [4] := htRight;
FPosList [5] := htBottomRight;
FPosList [6] := htBottom;
FPosList [7] := htBottomLeft;
FPosList [8] := htLeft;
//
FPen := TPen.Create;
FPen.OnChange := StyleChanged;
FBrush := TBrush.Create;
FBrush.OnChange := StyleChanged;
FPointColor := clBlack;
//ParentBackground := False;
end;
procedure TDesignbleShape.CreateHandle;
begin
inherited CreateHandle;
SetFocus;
end;
procedure TDesignbleShape.CreateParams (var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle + ws_ex_Transparent;
end;
procedure TDesignbleShape.Paint;
var
I: Integer;
X, Y, W, H, S: Integer;
begin
DoDrawBakground;
with Canvas do
begin
Canvas.Brush.Color := clNone;
Canvas.Brush.Style := bsClear;
FillRect(ClientRect);
Pen.Assign(FPen);
Brush.Assign(FBrush);
X := Pen.Width div 2;
Y := X;
W := Width - Pen.Width + 1;
H := Height - Pen.Width + 1;
if Pen.Width = 0 then
begin
Dec(W);
Dec(H);
end;
if W < H then S := W else S := H;
if FShape in [stSquare, stRoundSquare, stCircle] then
begin
Inc(X, (W - S) div 2);
Inc(Y, (H - S) div 2);
W := S;
H := S;
end;
case FShape of
stRectangle, stSquare:
Rectangle(X, Y, X + W, Y + H);
stRoundRect, stRoundSquare:
RoundRect(X, Y, X + W, Y + H, S div 4, S div 4);
stCircle, stEllipse:
Ellipse(X, Y, X + W, Y + H);
end;
end;
Canvas.Brush.Color := PointColor;
Canvas.Brush.Style := bsSolid;
Canvas.Pen.Color := PointColor;
for I := 1 to 8 do
Canvas.Rectangle (FRectList .Left, FRectList .Top,
FRectList .Right, FRectList .Bottom);
end;
procedure TDesignbleShape.WmNcHitTest(var Msg: TWMNCHitTest);
var
Pt: TPoint;
I: Integer;
begin
inherited;
Pt := Point (Msg.XPos, Msg.YPos);
Pt := ScreenToClient (Pt);
Msg.Result := 0;
for I := 1 to 8 do
if PtInRect(FRectList, Pt) then
Msg.Result := FPosList ;
// if the return value was not set
if Msg.Result = 0 then
inherited;
end;
procedure TDesignbleShape.WmSize (var Msg: TWMSize);
begin
//inherited;
Do_Size;
end;
procedure TDesignbleShape.WmLButtonDown (var Msg: TWMLButtonDown);
begin
Perform(WM_SYSCOMMAND, sc_DragMove, 0);
end;
procedure TDesignbleShape.WmMove (var Msg: TWMMove);
begin
PostMessage(Handle, WM_RbsInvalidate,0,0)
//Paint;
end;
procedure TDesignbleShape.SetShape(const Value: TShapeType);
begin
if FShape <> Value then
begin
FShape := Value;
Invalidate;
end;
end;
procedure TDesignbleShape.SetBrush(const Value: TBrush);
begin
FBrush.Assign(Value);
end;
procedure TDesignbleShape.SetPen(const Value: TPen);
begin
FPen.Assign(Value);
end;
destructor TDesignbleShape.Destroy;
begin
FPen.Free;
FBrush.Free;
inherited;
end;
procedure TDesignbleShape.StyleChanged(Sender: TObject);
begin
Invalidate;
end;
procedure TDesignbleShape.SetPointColor(const Value: TColor);
begin
FPointColor := Value;
end;
procedure TDesignbleShape.Do_Size;
begin
//setup data structures
FRectList [1] := Rect(0, 0, 8, 8);
FRectList [2] := Rect(Width div 2 - 4, 0, Width div 2 + 4, 8);
FRectList [3] := Rect(Width - 8, 0, Width, 8);
FRectList [4] := Rect(Width - 8, Height div 2 - 4, Width, Height div 2 + 4);
FRectList [5] := Rect(Width - 8, Height - 8, Width, Height);
FRectList [6] := Rect(Width div 2 - 4, Height - 8, Width div 2 + 4, Height);
FRectList [7] := Rect(0, Height - 8, 8, Height);
FRectList [8] := Rect(0, Height div 2 - 4, 8, Height div 2 + 4);
end;
procedure TDesignbleShape.DoDrawBakground;
var
DesktopDC : HDC;
SelfDC : HDC;
ARect: TRect;
begin
DesktopDC := GetDC(0);
try
SelfDC := GetDC(Self.Handle);
try
ARect := GetClientRect;
Windows.ClientToScreen(Self.Handle, ARect.TopLeft);
Windows.ClientToScreen(Self.Handle, ARect.BottomRight);
BitBlt(SelfDC, 0, 0, Width, Height, DesktopDC, ARect.Left, ARect.Top, SRCCOPY);
finally
ReleaseDC(Self.Handle, SelfDC);
end;
finally
ReleaseDC(0, DesktopDC);
end;
end;
procedure TDesignbleShape.WMEraseBkgnd(var Message: TWmEraseBkgnd);
begin
//Message.Result := 1;
PostMessage(Handle, WM_RbsInvalidate,0,0)
end;
procedure TDesignbleShape.CNCTLCOLOREDIT(var Message: TWMCTLCOLOREDIT);
begin
// SetBkMode(ChildDC,Windows.TRANSPARENT);
// Result:=GetStockObject(HOLLOW_BRUSH)
end;
procedure TDesignbleShape.RbsInvalidate(var Message: TMessage);
var
R: TRect;
begin
if Parent <> nil then
begin
R:= ClientRect;
R.TopLeft := Parent.ScreenToClient(ClientToScreen(R.TopLeft));
R.BottomRight := Parent.ScreenToClient(ClientToScreen(R.BottomRight));
RedrawWindow(Handle,nil,0, RDW_FRAME + RDW_INVALIDATE);
end;
end;
procedure TDesignbleShape.CreateWnd;
begin
inherited;
SetWindowLong(Parent.Handle, GWL_STYLE, GetWindowLong(Parent.Handle, GWL_STYLE) and not WS_CLIPCHILDREN);
end;
end.
调用代码:========================================================
objDesignbleShape := TDesignbleShape.Create(Self);
objDesignbleShape.Parent := ScrollBox1;
objDesignbleShape.Top := 50;
objDesignbleShape.Left := 50;
objDesignbleShape.Height := 250;
objDesignbleShape.Width := 250;
objDesignbleShape.Pen.Width := 2;
objDesignbleShape.Pen.Color := clRed;
objDesignbleShape.Brush.Color := clWhite;
objDesignbleShape.Brush.Style := bsClear;
objDesignbleShape.PointColor := clYellow;
objDesignbleShape.Cursor := crSizeAll;
========================================================
现在的问题:
。要求一已实现,运行时有设计时效果;
。要求二也实现,为了简单,我只是简单的用了TShape的源码;
。要求三,在用鼠标点在八个点上面,可以改变大不,控件也是透明的;但是,在移动的时候,却不能做到透明;
其它现象:
。更改Shape值的时候,也不能透明;移动控件的时候,也不能透明;不透明的时候,用另外的Form挡它一下,再移开,它就透明了;
小弟想了很多办法了,实在是水平有限,怎么也试不出来。希望熟悉的朋友不吝赐教,先谢谢了。。。