Delphi 组件开发教程指南(5)实现类QQ的编辑框

   距离上一篇系列的文章有一段时间了,假终于是放完了!现在咱继续在TEdit上做文章,同时来熟悉某些Windows的系统消息。现在我讲的是如何实现一个类似QQ编辑框的样式。

   再讲解之前,先回馈前几篇文章有些人提出的问题。通过前几篇文章,有很多人关注,同时也有人给了一些建议。所以我这里说明一下,我这个组件编写的教程指南过程可能不是和书上按部就班一样的讲解,我的着重点是如何编写一个组件,这个编写的着重点偏向于实现方式,也就是实现一个组件要涉及到的消息还有Delphi VCL的一些虚拟方法重载等等,至于有人提到的包的概念,我这里讲解的很粗略,甚至说是没有讲解,其实这个我有小括弧注释,给了一个cnpack的包的说明文档,那个讲的非常详细的。至于这个系列的文章讲解顺序(有人说应该先建立一个包,然后在添加组件实现单元,然后注册等),而我是先实现了一个组件,然后才建立的包,其实这个都不是问题的,编写组件的重点是在于组件的实现方式上面,这个包的建立以及注册到IDE上,只要稍微找找相关资料就能明白了,所以我也就没详细说明!另外有人说咋没讲组件编辑器,呵呵,那是因为还不到时候,看看我这个TEdit的扩充哪里有我自定义的特殊属性需要自己编写属性编辑器哈。所以还请暂时等待等待,总会讲到的!

    OK,那么咱们开始正文吧!这次,我们将打造一个类似QQ的TEdit样式的编辑框。先来看看QQ的编辑框的样式,首先QQ的编辑框无论在任何系统下,他都是他自己的呈现方式,也就是是平面的,在无皮肤的系统和有皮肤的系统下都是他自己的方式;其次,再来看看,鼠标移动上去的时候,外部多了一层边框,而且是高亮效果,似乎是颜色模糊化的。好,现在分析清楚了,那么我们就看看这个的实现需要的一些消息或者处理过程。

    第一步,平面效果。Windows系统有几个消息专门用来处理Windows组件的边框部位,那就是WM_NCCALCSIZE和WM_NCPAINT这两个消息,从消息名字看来NC这个就代表着No Client也就是非客户区域,NCCALCSIZE也就是说明了计算非客户区和客户区的消息,而WM_NCPAINT消息,也就是非客户区域的绘制触发消息,所以就要截获这两个消息来绘制自己的边框取代Windows系统的绘制方式。在Delphi中拦截系统消息非常简单,直接在消息的处理过程后面跟一个message关键字,然后加上消息常量就可以了!不像MFC要搞消息映射那么麻烦,声明代码如下

procedure WMNcCalcSize(var msg: TWMNCCalcSize);message WM_NCCALCSIZE;

msg参数为TWMNCCalcSize结构,其实也就是TMessage结构,可以相互转化的,这个结构为

 

 
  
TWMNCCalcSize = packed record
Msg: Cardinal;
CalcValidRects: BOOL;
CalcSize_Params: PNCCalcSizeParams;
Result: Longint;
end ;

 

这个结构体中msg就是WM_NCCALCSize的消息

CalcValidRects表示是否计算客户区的有效区域,如果为True,此时CalcSize_Params为一个rgrc: array[0..2] of TRect;的结构体,

rgrc[0]指向的是新的windows的RECT,rgrc[1]是之前的windows的RECT,rgrc[2]传入的是move/resize前的client rect。

如果本值为false的时候,指向的rect和TRUE时的rgrc[0]功能相同

CalcSize_Params是一结构体,这个结构体上面介绍CalcValidRects已经说明,Result指定消息返回值

关于本消息的详细解释清参考MSDN或者这个帖子,然而本篇,我们可以不用这个拦截这个消息,因为Delphi的Edit有一个BorderStyle属性默认为bsSingle也就是是有边框的,所以我们只用拦截WM_NCPaint这个消息,然后自己处理边框的绘制就OK了。

第二步,平面效果绘制过程,也不多说了,直接给出代码更加直观,下面给出代码实现过程 

 
  
procedure TEdit1.WMNCPAINT( var msg: TWMNCPaint);
var
DC: HDC;
BorderBrush: HBRUSH;
R: TRect;
begin
DC :
= GetWindowDC(Handle);
try
SetRect(R,
0 , 0 ,Width,Height);
if FMouseIn then
begin
BorderBrush :
= CreateSolidBrush(RGB( 123 , 228 , 255 ));//创建画刷
FrameRect(Dc, R, BorderBrush);
//绘制外部的高亮边框
DeleteObject(BorderBrush);
InflateRect(R,
- 1 , - 1 );
end
else
begin
InflateRect(R,
- 1 , - 1 );
BorderBrush :
= CreateSolidBrush(ColortoRGB(Color));
FrameRect(Dc, R, BorderBrush);//这个是因为如果鼠标不在上面,就要用本身的颜色填充内部线框

DeleteObject(BorderBrush);
InflateRect(R,
1 , 1 );
end ;
BorderBrush :
= CreateSolidBrush(RGB( 78 , 160 , 209 ));
FrameRect(Dc, R, BorderBrush);
// 绘制默认的边线框
DeleteObject(BorderBrush);
finally
ReleaseDC(Handle,DC)
end ;
end ;

 这个绘制过程就完成了,但是这个还不够,运行就会发现,此时只有一个平面效果,鼠标移动上去和离开没有任何效果的,所以此时还要加上鼠标的处理效果,有两个消息CM_MOUSEENTER和CM_MOUSELEAVE表示鼠标进入控件和鼠标离开控件时候触发!所以我们拦截这两个消息,然后鼠标进入的时候改变一个状态,然后发送一个重新绘制边线框的消息让它触发WM_NCPaint消息,于是我实现一个过程发送边框重绘消息

 

 
  
procedure TEdit1.InvalidateNC;
begin
if Parent = nil then Exit;
SendMessage(Handle, WM_NCPAINT,
0 , 0 );
end ;

,然后就是两个鼠标消息的处理了

 
  
procedure TEdit1.CMMouseEnter( var msg: TMessage);
begin
inherited ;
FMouseIn :
= True;
InvalidateNC;
end ;

procedure TEdit1.CMMouseLeave( var msg: TMessage);
begin
inherited ;
FMouseIn :
= False;
InvalidateNC;
end ;

实现过程都很简单仅仅是发送一个WM_NCPAINT消息而已。

现在我们看看实现效果

2010050410502720.gif,可以试试去掉系统的皮肤之后是个什么效果,另外我这个颜色已经写死了,有兴趣的可以试试换换颜色!另外,可以试试WM_NCCALCSIZE中处理一下,然后看看效果!

 

Delphi组件开发教程指南目录

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Delphi编写的即时通信程序,QQ聊天,源码内包括了控件补盯配置方法说明和各个模块的代码等。   一个自我感觉很好的通信程序,它的特点:   1.数据包格式全部自己定义。    所有的定义和通信核心全部在COMM文件夹中。   2.能处理大量客户端同时通信的情况,客户和服务端共用相同的通信对象,并且可以实现互传。   3.通信细节全部封装在几个通用的中,隐藏了交互通信的所有处理细节,如断包处理,超时重发等功能。   4.数据通信和数据具体应用完全分离,扩展性良好,本例中只做一个上传文件的例子,你可以在不用改动通信核心的情况下,可以实现远程控制所需的任何功能,并且不需要考虑通信细节。具体方法可以参考:CommSrvApps 单元的TSrvApp_File,只需写一个新即可:    TSrvApp_File = class(TServerAppObject)    public    function ProcessData(ABuf: PChar; ASize: integer): integer; override;    end;    通过以上配合通信核心实现了远程实时传送一个文件就像copy那么简单。   其它:   此程序是我自己开发的连锁超市方案中数据交换的应用实例,所以客户端和服务端的代码有点多,但多是与通信本身无关,所实现的功能是将本地Local文件夹与远程Remote文件夹的.rs文件互相进行传送。   程序配置方法:   1.本程序在Delphi6下编译通过,其它版本没有测试。   2.请先安装"控件补丁"中的控件包。   3.编译Client或Server时,请先设置Search Path指向comm 文件夹。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值