zoukankan      html  css  js  c++  java
  • 实现类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消息而已。

    现在我们看看实现效果

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

  • 相关阅读:
    用户访问集群架构的流程
    HTTP请求方法 HTTP的响应方法
    数据报文
    什么是HTTP? 什么是超文本? 什么是URL?
    HTTP协议原理
    C语言之数据类型③——字符与字符串
    C语言之数据类型②——浮点类型
    C语言之数据类型①——整数类型
    uniapp自定义小程序左上角的图标并且添加自定义事件
    在uniapp中使用iconfont
  • 原文地址:https://www.cnblogs.com/key-ok/p/3380821.html
Copyright © 2011-2022 走看看