delphi 可以自定义边框的文本框TSkinNormalEdit思路(QQ2011风格)
需求:
QQ我的资料中基本资料窗体中的文本框:
正常状态下,文本框只有一条看起来只有一个像素的边框,边框的颜色从上到下由深到浅的渐变,当鼠标定位到该文本框时,其边框会变粗,而且边框的颜色加亮显示
如下图所示:
实现思路:
一、准备两个边框素材图片,
一个是正常状态下的边框素材,
比如:
另一个是鼠标进入到文本框内的边框素材
比如:
二、需要的参数
首先是边框素材的绘制边距,分为左边距,右边距,上边距,下边距
边框素材根据边距的设置,使用九宫格缩放绘制到界面上
其次是边框的边距,也为左边距,右边距,上边距,下边框
代表的是文本框客户区(即输入区)的大小
默认的,边框素材的绘制边距和边框的边距是一样的
三、消息处理
边框属于文本框的非客户区域,在文本框的WM_NCPAINT中绘制
文本框的边框风格有两种:bsNone和bsSingle
bsNone即为无边框样式,不需要绘制边框,而且文本框的大小就是客户区的大小
bsSingle为单边框样式,默认边框为两个像素的宽
如果需要自定义文本框的边框宽度,那么需要处理WM_NCCALCSIZE消息
通过WM_NCCALCSIZE消息,使边框扩展为自己所设置的宽度
例(边框扩展一个像表):
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;
delphi 可以自定义边框的文本框TSkinNormalEdit思路(QQ2011风格)的更多相关文章
- vue学习(十七) 使用自定义指令 使文本框获得鼠标焦点
需求:当我们进入某个页面,页面中的第一个input会自动获得焦点 光标闪烁,代表可输入 <div id="app"> //v-focus 是自定义的 <input ...
- JavaScript中自定义函数以及文本框、radio、下拉框的值的获取,结合淘宝竞拍案例来理解。。。
淘宝竞拍案例: HTML部分代码: <form action="#" method="post"> <h2>欢迎进入淘宝竞拍</h ...
- [Swift通天遁地]二、表格表单-(15)自定义表单文本框内容的格式
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- css装饰文本框input
在web程序前端页面中,<input>恐怕是用的最多的html元素了,各个需要录入信息的场合都会用到它,一般都会用css来修饰一下使得它更好看. 原始的不加修饰的文本框像下面,有些单调,页 ...
- [转]让你的网页文本框增加光晕效果与提示,水印(类似QQ2011)
本文转自:http://www.cnblogs.com/xiaofengfeng/archive/2013/01/28/2880344.html 让你的网页文本框增加光晕效果(类似QQ2011) 我们 ...
- 用MVC的辅助方法自定义了两个控件:“可编辑的下拉框控件”和“文本框日历控件”
接触MVC也没多长时间,一开始学的时候绝得MVC结构比较清晰.后来入了门具体操作下来感觉MVC控件怎么这么少还不可以像ASP.net form那样拖拽.这样设计界面来,想我种以前没学过JS,Jquer ...
- C#Winform使用扩展方法自定义富文本框(RichTextBox)字体颜色
在利用C#开发Winform应用程序的时候,我们有可能使用RichTextBox来实现实时显示应用程序日志的功能,日志又分为:一般消息,警告提示 和错误等类别.为了更好地区分不同类型的日志,我们需要使 ...
- iOS不得姐项目--登录模块的布局,设置文本框占位文字颜色,自定义内部控件竖直排列的按钮
一.登录模块的布局 将一整部分切割成若干部分来完成,如图分成了三部分来完成 设置顶部状态栏为白色的方法 二.设置文本框占位文字颜色 <1>方法一与方法二实现原理是同一种,都是通过设置pla ...
- javascript当文本框获得焦点设置边框
javascript当文本框获得焦点设置边框:本章节介绍一下当文本框获得焦点以后如何设置文本框的边框样式,本来是一个非常简单的问题,但是有可能前台美工人员对javascript并不是太了解,所以还是通 ...
随机推荐
- SQL的多表查询(Navicat)
-- 部门表 CREATE TABLE dept ( id INT PRIMARY KEY PRIMARY KEY, -- 部门id dname VARCHAR(50), -- 部门名称 loc VA ...
- 使用cordova,监听安卓机物理返回按键,实现退出程序的功能
在使用html5开发app时,并不能像Android原生那样调取手机自身的方法.而cordova正好弥补了html5这一缺陷. 一,在cordova中文网http://cordova.axuer.co ...
- Mysql安装多版本数据库
1.下载对应版本压缩包 2.解压缩文件 3.到解压缩文件,添加my.ini文件,修改相关的配置,如端口,文件路径等 # For advice on how to change settings ple ...
- YII 中加入短信接口的函数
public function smsto($telphone,$message) { //短信接口用户名 $uid,如果没有或不能发送请与客服联系 $uid = 'zyd'; //短信接口密码 $p ...
- 2019河北省大学生程序设计竞赛(重现赛) L题-smart robot(深度优先搜索)
题目链接:https://ac.nowcoder.com/acm/contest/903/L 题意:给你 n * n的方阵,你可以从任意一个数字开始走,可以走上下左右四个方向,走过的数字会被拼合,拼合 ...
- 专题:LFS构建逻辑理解
严格来说,LFS只能称为“pseudo LFS”,WHY? 因为LFS归根结底,还是基于已有的操作系统平台构建而来,并非真正的从0开始,它没有突破所谓“鸡与蛋”的死循环:但它确实有助于理解Linux的 ...
- Django框架(七)—— 模板层:变量、过滤器、标签、自定义标签和过滤器
目录 模板层:变量.过滤器.标签.自定义标签和过滤器 一.模板层变量 1.语法 2.使用 二.模板层之过滤器 1.语法 2.常用过滤器 3.其他过滤器 三.模板值标签 1.for标签 2.if标签 3 ...
- JHipster研究
liquibase工作原理: master.xml用来维护所有变更记录文件引用 changelog文件夹用来保存具体的变更细节 系统启动时会比较master.xml中include的file,应用差异 ...
- 《深入理解Java虚拟机》- 重载与重写
这一节打算从“方法调用”的主题进行分析. 方法调用并不等同于方法执行,方法调用阶段唯一的任务就是确定被调用方法的版本(即调用哪一个方法),暂时还不设计方法内部的具体运行过程. 一.概念 解析调用:所有 ...
- C# Winform Dev控件之TileControl
tileControl 包含TileGroup TileGroup 包含 Tile Tile拖拽时代码 TilteControl的itemPress事件执行 或Tile的itemPress执行 Til ...