文中均以Delphi XE 10.3平台为例。
一:新建 Windows VCL Application 工程
1、File -> NEW -> 选 Windows VCL Application - delphi
2、先保存 File -> Save All (保存到你想保存的地方,这里以test目录为例)
二:使用 组件向导(New Component)创建TEdit组件模板
1、Component -> 选 New Component -> 在 搜索框 输入edit快速找到TEdit 选中TEdit -> Next;
2、设置 Class Name: 我这里设为TEditEx1
Palete Page: 表示组件放入哪个组件选项卡,这里可以先不管它,以后再讲。
Unit name: .pas单元保存的路径,选刚刚新建的test目录,文件名也改为EditEx1.pas -> Next;
3、选 Create Unit -> Finish。
4、File -> Save 保存EditEx1.pas 至 test目录
三:接下来就是写代码
在写之前先补充点知识
要修改Edit边框需要用到Windows系统WM_NCCALCSIZE和WM_NCPAINT这两个消息,从消息名字看来NC这个就代表着No Client也就是非客户区域,NCCALCSIZE也就是说明了计算非客户区和客户区的消息,而WM_NCPAINT消息,也就是非客户区域的绘制触发消息,所以就要截获这两个消息来绘制自己的边框取代Windows系统的绘制方式。
在Delphi中拦截系统消息非常简单,直接在消息的处理过程后面跟一个message关键字,然后加上消息常量就可以了!
Delphi中的消息处理简单介绍:
消息处理句柄方法声明为:
procedure Mymsgmethod(var message:Tmessage); message Msgtype;
消息的使用:
在DELPHI 中用户可以自定义消息及消息处理句柄消息处理句柄的定义有如下几个原则:
1、消息处理句柄方法必须是一个过程
2、方法声明后要有一个message关键字,然后加上消息常量
3、消息处理句柄方法不需要用override 命令来显式指明重载祖先的一个消息处理句柄
4、在消息处理句柄中一般先是用户自己对消息的处理用祖先类中对应此消息的处理句柄(有些情况下可能正相反).由于可能对祖先类中对此消息的处理句柄的名字和参数类型不清楚避免此麻烦调用Defaulthandler方法.(当然如果要屏蔽掉此消息了)。
由于Edit本来有就边框,只要使用WM_NCPAINT消息写代码重绘即可,无需再处理WM_NCCALCSIZE消息。
重载WM_NCPAINT消息:
回到EditEx1
添加引用 WinApi.Messages, WinApi.Windows;
protected 处输入代码:
procedure WMNCPAINT(var msg: TWMNCPaint); message WM_NCPAINT; // 按Ctrl+Shift+c 自动生成实现代码
// 下面为实现代码
procedure TEditEx1.WMNCPAINT(var msg: TWMNCPaint);
begin
// 这里写重绘代码
end;
EditEx1.pas完整代码:
unit EditEx1;
interface
uses
System.SysUtils, System.Classes, Vcl.Controls, Vcl.StdCtrls, WinApi.Messages, WinApi.Windows;
type
TEditEx1 = class(TEdit)
private
{ Private declarations }
protected
procedure WMNCPAINT(var msg: TWMNCPaint); message WM_NCPAINT;
public
{ Public declarations }
published
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Standard', [TEditEx1]);
end;
{ TEditEx1 }
procedure TEditEx1.WMNCPAINT(var msg: TWMNCPaint);
var
DC: HDC;
BorderBrush: HBRUSH;
R: TRect;
begin
inherited; // 必须继承Windows消息,让我们不处理的丢给Windows自己处理
DC:= GetWindowDC(Handle);
try
SetRect(R,0,0,Width,Height);
BorderBrush:= CreateSolidBrush(RGB(78,160,209));
FrameRect(Dc, R, BorderBrush);//绘制默认的边线框
DeleteObject(BorderBrush);
finally
ReleaseDC(Handle,DC)
end;
end;
end.
我们简单的实现了一个对Delphi自身的TEdit编辑框控件的一个扩充!但是我们并不能像Delphi自己的TEdit一样,能够在设计状态下进行设计,所以还得手动创建控件,然后才能使用。
手动创建控件方法:
进入Unit1单元
添加引用 EditEx1
添加声明
var
Form1: TForm1;
MyEditEx1: TEditEx1;
Unit1.pas完整代码:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, EditEx1;
type
TForm1 = class(TForm)
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
MyEditEx1: TEditEx1;
implementation
{$R *.dfm}
procedure TForm1.FormShow(Sender: TObject);
begin
// 动态创建TEditEx1
// TEditEx1.Create(),参数是一个AOwner: TComponent,只要是窗体上的组件都可以
MyEditEx1:= TEditEx1.Create(Form1); // 指明了owner,可以不释放内存,窗口关闭时由父组件销毁
with MyEditEx1 do
begin
Parent:= Form1; // 必须要在创建后指明父组件的名称,否则没法显示
Top:=20;
Left:=20;
Width:= 100;
Height:= 20;
Text:= '郴维网';
end;
end;
end.
效果图:





