delphi 可以自定义边框的文本框TSkinNormalEdit思路(QQ2011风格)
2012-01-12 10:39
260 查看
需求:
QQ我的资料中基本资料窗体中的文本框:
正常状态下,文本框只有一条看起来只有一个像素的边框,边框的颜色从上到下由深到浅的渐变,当鼠标定位到该文本框时,其边框会变粗,而且边框的颜色加亮显示
如下图所示:
实现思路:
一、准备两个边框素材图片,
一个是正常状态下的边框素材,
比如:
另一个是鼠标进入到文本框内的边框素材
比如:
二、需要的参数
首先是边框素材的绘制边距,分为左边距,右边距,上边距,下边距
边框素材根据边距的设置,使用九宫格缩放绘制到界面上
其次是边框的边距,也为左边距,右边距,上边距,下边框
代表的是文本框客户区(即输入区)的大小
默认的,边框素材的绘制边距和边框的边距是一样的
三、消息处理
边框属于文本框的非客户区域,在文本框的WM_NCPAINT中绘制
文本框的边框风格有两种:bsNone和bsSingle
bsNone即为无边框样式,不需要绘制边框,而且文本框的大小就是客户区的大小
bsSingle为单边框样式,默认边框为两个像素的宽
如果需要自定义文本框的边框宽度,那么需要处理WM_NCCALCSIZE消息
通过WM_NCCALCSIZE消息,使边框扩展为自己所设置的宽度
例(边框扩展一个像表):
[delphi] view plaincopy
procedure TSkinNormalEdit.WMNCCalcSize(varMessage: TWMNCCalcSize);
var
NCCalcSizeParams: PNCCalcSizeParams;
begin
Inherited;
if(BorderStyle=bsNone) then
begin
end
else
begin
NCCalcSizeParams:=Message.CalcSize_Params;
Inc(NCCalcSizeParams.rgrc0.Top,1);
Inc(NCCalcSizeParams.rgrc0.Left,1);
Dec(NCCalcSizeParams.rgrc0.Right,1);
Dec(NCCalcSizeParams.rgrc0.Bottom,1);
end;
end;
四、边框绘制时机
边框有两种状态,鼠标进入到文本框中和鼠标离开文本框
所以,要判断这两种状态
像一般的从TCustomControl或TGraphicControl继承过来的控件,
我们可以通过Delphi内部的管理消息CM_MOUSEENTER和CM_MOUSELEAVE消息处理
但是文本框包含非客户区(边框)和客户区
CM_MOUSEENTER和CM_MOUSELEAVE消息只是鼠标进入或是离开客户区才会响应
所以接下来要处理如何判断鼠标在非客户区中
非客户区的鼠标移动消息主要有三个
WM_NCMOUSEMOVE:非客户区鼠标移动
WM_NCHITTEST:非客户区鼠标移动在控件的哪个部位(标题栏?边框?边角?客户区等等)
WM_NCMOUSELEAVE:鼠标离开非客户区(但是文本框不触发这个消息)
综上,没有一个消息可以简单的标识鼠标是否在控件中
CM_MOUSEENTER可以判断鼠标进入控件的客户区
WM_NCHITTEST可以判断鼠标在控件的非客户区
CM_MOUSELEAVE不能判断鼠标离开控件的客户区
所以,用一个定时器加一个判断鼠标在客户区的过程组合
WM_NCHITTEST消息中,判断当鼠标进入第一次非客户区时,响应鼠标进入消息,重绘边框,设置定时器,判断鼠标是否会在100毫秒内离开文本框
CM_MOUSEENTER消息中,鼠标已经进入客户区了,重绘边框
CM_MOUSELEAVE 消息中,只是表明了鼠标离开客户区,所以要启动定时器,每100毫秒判断鼠标是否在文本框中,如果检测到鼠标离开文本框,那么需要响应鼠标离开,重绘边框
五、边框绘制
边框为非客户区,在文本框的WM_NCPAINT消息中绘制
比如:
QQ我的资料中基本资料窗体中的文本框:
正常状态下,文本框只有一条看起来只有一个像素的边框,边框的颜色从上到下由深到浅的渐变,当鼠标定位到该文本框时,其边框会变粗,而且边框的颜色加亮显示
如下图所示:
实现思路:
一、准备两个边框素材图片,
一个是正常状态下的边框素材,
比如:
另一个是鼠标进入到文本框内的边框素材
比如:
二、需要的参数
首先是边框素材的绘制边距,分为左边距,右边距,上边距,下边距
边框素材根据边距的设置,使用九宫格缩放绘制到界面上
其次是边框的边距,也为左边距,右边距,上边距,下边框
代表的是文本框客户区(即输入区)的大小
默认的,边框素材的绘制边距和边框的边距是一样的
三、消息处理
边框属于文本框的非客户区域,在文本框的WM_NCPAINT中绘制
文本框的边框风格有两种:bsNone和bsSingle
bsNone即为无边框样式,不需要绘制边框,而且文本框的大小就是客户区的大小
bsSingle为单边框样式,默认边框为两个像素的宽
如果需要自定义文本框的边框宽度,那么需要处理WM_NCCALCSIZE消息
通过WM_NCCALCSIZE消息,使边框扩展为自己所设置的宽度
例(边框扩展一个像表):
[delphi] view plaincopy
procedure TSkinNormalEdit.WMNCCalcSize(varMessage: TWMNCCalcSize);
var
NCCalcSizeParams: PNCCalcSizeParams;
begin
Inherited;
if(BorderStyle=bsNone) then
begin
end
else
begin
NCCalcSizeParams:=Message.CalcSize_Params;
Inc(NCCalcSizeParams.rgrc0.Top,1);
Inc(NCCalcSizeParams.rgrc0.Left,1);
Dec(NCCalcSizeParams.rgrc0.Right,1);
Dec(NCCalcSizeParams.rgrc0.Bottom,1);
end;
end;
四、边框绘制时机
边框有两种状态,鼠标进入到文本框中和鼠标离开文本框
所以,要判断这两种状态
像一般的从TCustomControl或TGraphicControl继承过来的控件,
我们可以通过Delphi内部的管理消息CM_MOUSEENTER和CM_MOUSELEAVE消息处理
但是文本框包含非客户区(边框)和客户区
CM_MOUSEENTER和CM_MOUSELEAVE消息只是鼠标进入或是离开客户区才会响应
所以接下来要处理如何判断鼠标在非客户区中
非客户区的鼠标移动消息主要有三个
WM_NCMOUSEMOVE:非客户区鼠标移动
WM_NCHITTEST:非客户区鼠标移动在控件的哪个部位(标题栏?边框?边角?客户区等等)
WM_NCMOUSELEAVE:鼠标离开非客户区(但是文本框不触发这个消息)
综上,没有一个消息可以简单的标识鼠标是否在控件中
CM_MOUSEENTER可以判断鼠标进入控件的客户区
WM_NCHITTEST可以判断鼠标在控件的非客户区
CM_MOUSELEAVE不能判断鼠标离开控件的客户区
所以,用一个定时器加一个判断鼠标在客户区的过程组合
WM_NCHITTEST消息中,判断当鼠标进入第一次非客户区时,响应鼠标进入消息,重绘边框,设置定时器,判断鼠标是否会在100毫秒内离开文本框
CM_MOUSEENTER消息中,鼠标已经进入客户区了,重绘边框
CM_MOUSELEAVE 消息中,只是表明了鼠标离开客户区,所以要启动定时器,每100毫秒判断鼠标是否在文本框中,如果检测到鼠标离开文本框,那么需要响应鼠标离开,重绘边框
五、边框绘制
边框为非客户区,在文本框的WM_NCPAINT消息中绘制
比如:
procedure TSkinNormalEdit.WMNCPaint(varMessage: TWMNCPaint); var tmpWindowDC:HDC; tmpBorderImage:IGPBitmap; tmpWindowCanvas:TCanvas; tmpBitmapGraphics:IGPGraphics; begin ifSelf.BorderStyle=bsNone then begin Inherited; end else begin tmpWindowDC:=GetWindowDC(Handle); Try if tmpWindowDC<>0 then begin tmpWindowCanvas:=TCanvas.Create; Try tmpWindowCanvas.Handle:=tmpWindowDC; FParentBackGroundBitmap.SetSize(Width,Height); if FIsBroderTransparent then begin //绘制文本框背景 DrawParentImageDefault(Self,FParentBackGroundBitmap.Canvas.Handle); end; //边框为png素材,使用GDI+绘制,需要获取绘制接口,需要引用gdiplus和gdiplushelpers单元 tmpBitmapGraphics:=FParentBackGroundBitmap.Canvas.ToGPGraphics; //根据鼠标状态判断边框图片 if Self.MouseInClient or CursorInControl then begin tmpBorderImage:=Self.FHoverBorderBitmap; end else begin tmpBorderImage:=Self.FNormalBorderBitmap; end; //再绘制背景 if tmpBorderImage<>nil then begin //九宫格绘制边框素材 TSkinHelper.StretchDrawImageBorderInRectByMargins(tmpBitmapGraphics, tmpBorderImage,TGPRect.Create(0,0,Width,Height), Self.FBorderDrawMargins.Left, Self.FBorderDrawMargins.Top, Self.FBorderDrawMargins.Right, Self.FBorderDrawMargins.Bottom); end; //绘制最外的边框 //左边框 BitBlt( tmpWindowDC,0,0,Self.FBorderMargins.Left,Height, FParentBackGroundBitmap.Canvas.Handle,0,0,SRCCOPY ); //右边框 BitBlt( tmpWindowDC,Width-Self.FBorderMargins.Right,0,Self.FBorderMargins.Right,Height, FParentBackGroundBitmap.Canvas.Handle,Width-Self.FBorderMargins.Right,0,SRCCOPY ); //上边框 BitBlt( tmpWindowDC,0,0,Width,Self.FBorderMargins.Top, FParentBackGroundBitmap.Canvas.Handle,0,0,SRCCOPY ); //下边框 BitBlt( tmpWindowDC,0,Height-Self.FBorderMargins.Bottom,Width,Self.FBorderMargins.Bottom, FParentBackGroundBitmap.Canvas.Handle,0,Height-Self.FBorderMargins.Bottom,SRCCOPY ); Finally FreeAndNil(tmpWindowCanvas); End; end; Finally ReleaseDC(Handle,tmpWindowDC); End; end; end;
相关文章推荐
- 纯CSS3实现自定义Tooltip边框涂鸦风格的教程
- 圆形图片带有边框可以自定义边框颜色
- 纯CSS3实现自定义涂鸦风格的边框
- Android 主页面顶部栏的通知Notification ,可以自定义通知消息栏的风格,并且点击通知栏进人本程序。
- 自定义UISearchBar 适配IOS6和IOS7 修改放大镜图标 修改光标颜色 修改边框颜色 placeholder颜色 设置文本框背景
- 手把手教你打造c#透明、自定义边框、可拖动、可以放大缩小的窗口
- 你也可以自己写一个可爱 & 小资风格的Android加载等待自定义View - 转
- 自定义view控件之TextView可以包含两种不同的字体风格
- 自定义文本框边框
- 纯CSS3实现自定义涂鸦风格的边框
- Delphi 弹出Windows风格的选择文件夹对话框, 还可以新建文件夹
- 圆形图片带有边框可以自定义边框颜色
- 纯CSS3实现自定义涂鸦风格的边框
- Delphi中创建一个可以改变大小的无边框窗口
- Android-如何给View添加边框,边框颜色和线的粗细可以自定义
- Android自定义Iphone风格的圆角边框开关按钮
- 自定义文本框/布局背景/虚线边框/背景选择器
- 用 表格可以实现有背景图片和的边框的文本框
- 你也可以自己写一个可爱 & 小资风格的Android加载等待自定义View
- Vex – 超轻量!可以轻松自定义的现代风格弹窗插件