增加控件属性(TEdit) (50分)

  • 主题发起人 主题发起人 web_lance
  • 开始时间 开始时间
W

web_lance

Unregistered / Unconfirmed
GUEST, unregistred user!
需增加的属性:
 Transparent(True, False) → 透明效果
 //Alignment(taLeftJustify, taRightJustify, taCenter) → 水平对齐
 Layout(tlTop, tlCenter, tlBottom) → 垂直对齐

要求:
 1、属性需在对象监视器的Properties选项卡中出现,对其属性的改变,在设计/运行阶段都能体现;
 2、修改后的控件最好做到跟Delphi原有的控件表现一致,如在程序设计/运行时能够动态生成、移动控件时比较流畅等;

参考离线数据库的资料和StdCtrls,尝试为编辑框增加属性,但因本人水平有限,未能一一实现,还望各位仁兄多多帮忙。
(请贴出源码,如果不方便的可发E-mail至weblance@163.com,请注明标题是“控件源码”)

以下是本人借鉴已有的资料修改而成的控件代码:
注:1、水平对齐属性已完全可以实现,各位不必再考虑;
  2、垂直对齐属性本人不会实现;
  3、透明效果可以实现,但不理想。
 具体发现的问题有:
设计阶段 选择多个控件后,选择标记残留在控件上,Transparent=False时控件丢失边框;
 运行阶段 若控件获取焦点时也透明(//DoEnter),当修改字符时旧的内容会残留,失去焦点后正常;
(以下源码是发表时贴出,未作更改;上面的说明已作修改)

unit EditPro;

interface

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

const
TWM_Invalidate = WM_USER+1;

type
TEditPro = class(TEdit)
private
FAlignment: TAlignment;
procedure SetAlignment(Value: TAlignment);
procedure TInvalidate(var Message: TMessage); message TWM_Invalidate;
procedure CNCTLCOLOREDIT(var Message: TWMCTLCOLOREDIT); message CN_CTLCOLOREDIT;
procedure WMEraseBkgnd(var Message: TWMEraseBkgnd); message WM_ERASEBKGND;
procedure WMMove(var Message: TMessage); message WM_MOVE;
{ Private declarations }
protected
FTransparent: Boolean;
procedure CreateWnd; override;
procedure CreateParams(var Params: TCreateParams); override;
procedure DoExit; override;
procedure DoEnter; override;
{ Protected declarations }
public
constructor Create(AOwner: TComponent); override;
procedure Invalidate; override;
{ Public declarations }
published
property Alignment: TAlignment Read FAlignment Write SetAlignment Default taLeftJustify;
{ Published declarations }
end;

procedure Register;

implementation

constructor TEditPro.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
FTransparent := True;
end;

procedure TEditPro.CreateWnd;
begin
inherited CreateWnd;
if FTransparent then
begin
SetWindowLong(Parent.Handle, GWL_STYLE,
GetWindowLong(Parent.Handle, GWL_STYLE) and not WS_CLIPCHILDREN);
end;
end;

procedure TEditPro.SetAlignment(Value: TAlignment);
begin
if Value <> FAlignment then
begin
FAlignment := Value;
RecreateWnd;
end;
end;

procedure TEditPro.TInvalidate(var Message:TMessage);
var
r: TRect;
begin
if (Parent <> nil) and FTransparent 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 TEditPro.CNCTLCOLOREDIT(var Message: TWMCTLCOLOREDIT);
begin
if FTransparent then
with Message do
begin
SetBkMode(ChildDC, Windows.TRANSPARENT);
Result := GetStockObject(HOLLOW_BRUSH)
end
else inherited;
end;

procedure TEditPro.WMEraseBkgnd(var Message: TWMERASEBKGND);
begin
if FTransparent and not (csDesigning in ComponentState) then
PostMessage(Handle, TWM_Invalidate, 0, 0)
else inherited;
end;

procedure TEditPro.WMMove(var message: TMessage);
begin
inherited;
if FTransparent then SendMessage(Handle, TWM_Invalidate, 0, 0)
else Invalidate;
end;

procedure TEditPro.CreateParams(var Params: TCreateParams);
const
Alignments: array[TAlignment] of word = (DT_LEFT, DT_RIGHT, DT_CENTER);
begin
inherited CreateParams(Params);
if (CsDesigning in ComponentState) then Exit;
with Params do
begin
Style := Style or Alignments[FAlignment];
ExStyle := ExStyle or WS_EX_TRANSPARENT;
end;
end;

procedure TEditPro.DoExit;
begin
inherited;
FTransparent := True;
SetCursor(0);
RecreateWnd;
end;

procedure TEditPro.DoEnter;
var
exstyle, stdstyle: LongInt;
begin
inherited;
FTransparent := False;
StdStyle:= Windows.GetWindowLong(handle, GWL_EXSTYLE);
exStyle:= StdStyle and not WS_EX_TRANSPARENT;
Windows.SetWindowLong(handle, GWL_EXSTYLE, exStyle);
invalidate;
end;

procedure TEditPro.Invalidate;
begin
if FTransparent then SendMessage(Handle, TWM_Invalidate, 0, 0)
else inherited;
end;

procedure Register;
begin
RegisterComponents('Samples', [TEditPro]);
end;

end.
 
procedure TEditPro.CreateParams(var Params: TCreateParams);
const
Alignments: array[TAlignment] of word = (DT_LEFT, DT_RIGHT, DT_CENTER);
begin
inherited CreateParams(Params);
if (CsDesigning in ComponentState) then Exit;//你在这里写了如果控件处于设计期就退出,所以设计的时候是不会体现你所做的任何修改。去掉就行了
with Params do
begin
Style := Style or Alignments[FAlignment];
ExStyle := ExStyle or WS_EX_TRANSPARENT;
end;
end;
 
To 风中流云:
  多谢你的提示!可否再帮我考虑一下如何增加新属性吗(如题)?
 
private
FTransparent:boolean;
published//这里声明
property Transparent:boolean read FTransparent write setTransparent;方法同Alignment
 
我已经在对象监视器的Properties选项卡中添加了新属性,水平对齐属性基本上可以不管了,透明属性实现起来有点不理想,如果在获取焦点时也透明,当修改编辑框的内容时,旧的内容会残留在屏幕上。现在就差控件的宽度控制和垂直对齐的功能我不会实现,如果透明属性能够更完善一点就更好了。
 
可以参照有相关属性的控件
 
to web-lance:
请问可以实现换行吗?还有这个控件源代码可否发一份给我!谢谢!
 
你直接发个求控件的贴子不就行了。
 
因为我是昨天才注册的,还不能提问!
如果问题帮我解决的话,到时我另开贴加分!
 
To cherrylin:
  源码已在问题里贴出,你拷贝就是啦。至于修改的地方,请查看讨论。
 
to web_lance:

不知垂直对齐你有否做出来?
 
各位路过嘅仁兄,请多多关照小弟!
问题仲未解决吖。
 
后退
顶部