看了作者在B站的视频 做一下知识点的总结

用一个简单的自定义控件来总结下所用的知识点

扩展一个DUI窗口的基本步骤知识点:
Step1:从SWindow中继承一个DUI的窗口类
Step2: 定义新DUI窗口类的类名
Step3: 在main中向SApplication中注册新的DUI类
Step4: 在XML布局中使用你定义的DUI窗口类

一些准备工作
自绘需要一个关键的函数那就是Paint函数

在自绘的类中 这样设置

protected:SOUI_MSG_MAP_BEGIN()MSG_WM_PAINT_EX(OnPaint)SOUI_MSG_MAP_END()protected:void OnPaint(IRenderTarget * pRT);    //绘制

在OnPaint中我使用的是GDI+进行绘制

GDI的初始化
首先包含头文件 #include <GdiPlus.h>
全局变量:ULONG_PTR m_gdiplusToken;
初始化操作:
    Gdiplus::GdiplusStartupInput StartupInput;
    GdiplusStartup(&m_gdiplusToken, &StartupInput, NULL);
资源回收:
    Gdiplus::GdiplusShutdown(m_gdiplusToken);

在函数OnPaint中使用GDI+
HDC hdc = pRT->GetDC();
Graphics g(hdc);

准备工作完成后 我们开始实例开发

功能:一个类似checkbox的按钮 记录状态,最后通过和Edit控件使用类似显示和隐藏密码的功能

步骤:

Step1: 编写控件代码
    这里使用的是OnpaitnEx中进行窗口的绘画

Step2: 增加控件的消息事件
    这个可以参考 EVT_CMD 类似的定义
    
Step3: 绑定消息
    一般在控件的构造函数中将消息加入到指定的一个类对象m_evtSet 窗口事件集合
    通过m_evtSet.addEvent(EVENTID(自定义事件类));
    然后在控件中触发该消息也就是Fire
    这里的例子在鼠标左键按下的时候触发
        EventCmd evt(this);
        FireEvent(evt);

Step4:触发消息
    类似于中心消息事件 
    两种方法:
        
    方法一:通过在初始化函数中调用(代码片段如下)
            SDrawRight *p = FindChildByName2<SDrawRight>("checktest");
            p->GetEventSet()->subscribeEvent(EVT_CHECKPINK, Subscriber(&CMainDlg::OnCheckTest, this));
            OnCheckTest这个函数的返回值是bool类型
    
    方法二:使用EVENT_NAME_HANDLER 来调用 通过自定义的消息,消息ID和消息函数 来组成
        或者使用EVENT_ID_HANDLER(使用这个需要在属性中加上一个id)
        OnCheckTestFun2这个函数的返回值是void类型

注意使用不同的方法 调用消息事件 函数定义的返回值也是不同的

控件实现的代码:(SDrawRight.h

#pragma once#include <core/Swnd.h>
#include <GdiPlus.h>namespace SOUI
{//自定义控件的事件处理
#define EVT_CHECKPINK (EVT_EXTERNAL_BEGIN + 999)class EventCheckPink : public TplEventArgs<EventCheckPink>{SOUI_CLASS_NAME(EventCheckPink, L"on_check")public:EventCheckPink(SOUI::SWindow* pSender) : TplEventArgs<EventCheckPink>(pSender){ }enum { EventID = EVT_CHECKPINK};BOOL bStatus = FALSE;};class SDrawRight : public SWindow{SOUI_CLASS_NAME(SDrawRight,L"check_right")public:SDrawRight();~SDrawRight();BOOL GetStatus() { return m_bflag; }private:void GetSelfAdaptionSize(Gdiplus::Rect &rc);void OnLButtonDown(UINT nFlags, CPoint point);protected:void OnPaint(SOUI::IRenderTarget * pRT);SOUI_MSG_MAP_BEGIN()MSG_WM_PAINT_EX(OnPaint)MSG_WM_LBUTTONDOWN(OnLButtonDown)SOUI_MSG_MAP_END()private:BOOL m_bflag;         //是否被选中的标志Gdiplus::Rect m_rect; //圆点所在的区域};}

实现部分: SDrawRight.cpp

#include "stdafx.h"
#include "SDrawRight.h"ULONG_PTR token;namespace SOUI
{SDrawRight::SDrawRight():m_bflag(FALSE){Gdiplus::GdiplusStartupInput input;Gdiplus::GdiplusStartup(&token, &input, NULL);m_evtSet.addEvent(EVENTID(EventCheckPink));   //增加一个消息事件 (自定义的)//m_evtSet.addEvent(EVENTID(EventCmd));}SDrawRight::~SDrawRight(){Gdiplus::GdiplusShutdown(token);}//自适应窗口大小void SDrawRight::GetSelfAdaptionSize(Gdiplus::Rect & rc){int width = rc.Width;int height = rc.Height;int xwidth = abs(width - height);int yheight = min(width, height);if (width >= height){width = height;}else{height = width;}//获取一个80%的框rc = Gdiplus::Rect(rc.X + xwidth + 0.1*width, rc.Y + 0.1*height, 0.8*width, 0.8*height);}void SDrawRight::OnLButtonDown(UINT nFlags, CPoint point){//SMessageBox(NULL, L"test", L"tip", MB_OK);//判断这个点 是否在区域内Gdiplus::Region reg(m_rect);if (reg.IsVisible(point.x, point.y)){m_bflag = !m_bflag;Invalidate();}//触发自定义消息  (自定义消息)EventCheckPink evt(this);evt.bStatus = m_bflag;FireEvent(evt);    //激活事件//使用系统定义的消息//EventCmd evt(this);//FireEvent(evt);}void SOUI::SDrawRight::OnPaint(SOUI::IRenderTarget * pRT){SWindow::OnPaint(pRT);using namespace Gdiplus;Gdiplus::Graphics g(pRT->GetDC());CRect rc = GetClientRect();int alpha = m_bflag ? 80 : 200;SolidBrush blackBrush(Color(alpha, 255, 157, 206));Gdiplus::Rect layoutRect_min(rc.left, rc.top, rc.Width(), rc.Height());GetSelfAdaptionSize(layoutRect_min); //自适应的一个大小调整g.SetSmoothingMode(Gdiplus::SmoothingModeHighQuality); //描边时消除锯齿g.FillEllipse(&blackBrush, layoutRect_min);m_rect = layoutRect_min;}}

这里需要补充一点,在点击的事件处理中 也可以使用系统自带的EVT_CMD这个消息事件 只需要在调用的地方 Fire就行

例如:

//使用系统定义的消息
        //EventCmd evt(this);
        //FireEvent(evt);

这个就是使用系统自带的点击消息事件

这里还将Edit控件扩展了一下 加一个长度限制的属性 然后加一个只允许接收数字(这个在Edit属性中有 number="1"就是只能允许输入数字)

SMyEdit.h

#pragma once#include <core/Swnd.h>namespace SOUI
{class SMyEdit : public SEdit{SOUI_CLASS_NAME(SMyEdit,L"Myedit")public:SMyEdit();~SMyEdit();protected:void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);SOUI_ATTRS_BEGIN()ATTR_INT(L"length", m_Length, FALSE)SOUI_ATTRS_END()SOUI_MSG_MAP_BEGIN()MSG_WM_CHAR(OnChar)SOUI_MSG_MAP_END()private:int m_Length;};}

SMyEdit.cpp

#include "stdafx.h"
#include "SMyEdit.h"namespace SOUI
{SMyEdit::SMyEdit() :m_Length(0){}SMyEdit::~SMyEdit(){}void SOUI::SMyEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags){if (this->GetWindowTextLengthW() < m_Length){if (isdigit(nChar)) //设置成只能读取数字{__super::OnChar(nChar, nRepCnt, nFlags);}}}
}

在XML中的使用:

<Myedit pos="256,72" size="96, 24" colorBkgnd="#FFFFFF" colorText="#000000" colorBorder="#BCC0CB" margin-x="1" margin-y="1" password="1" name="TestPassword" length="8"/>
<check_right pos="352,72" size="24, 24" name="checktest" trackMouseEvent="1" />

调用方法两种:

1.在CMainDlg::OnInitDialog中 直接使用

SDrawRight *p = FindChildByName2<SDrawRight>("checktest");
 p->GetEventSet()->subscribeEvent(EVT_CHECKPINK, Subscriber(&CMainDlg::OnCheckTest, this));

2. 使用类似事件中心的方法进行调用

EVENT_NAME_HANDLER(L"checktest", EVT_CHECKPINK, OnCheckTestFun2)

实现的函数如下:

//方法一调用
bool CMainDlg::OnCheckTest(EventArgs * pEvt)
{//SMessageBox(NULL, L"test", L"tip", MB_OK);EventCheckPink* pEven = sobj_cast<EventCheckPink>(pEvt);SASSERT(pEven);SMyEdit *pEdit = FindChildByName2<SMyEdit>(L"TestPassword");pEdit->SetAttribute(L"password", SStringT().Format(L"%d", (pEven->bStatus) ? 0 : 1)); //修改Edit的属性pEdit->Invalidate();return false;
}//方法二调用
void CMainDlg::OnCheckTestFun2(EventArgs * pEvt)
{EventCheckPink* pEven = sobj_cast<EventCheckPink>(pEvt);SASSERT(pEven);SMyEdit *pEdit = FindChildByName2<SMyEdit>(L"TestPassword");pEdit->SetAttribute(L"password", SStringT().Format(L"%d", (pEven->bStatus) ? 0 : 1)); //修改Edit的属性pEdit->Invalidate();
}

最后实现的效果图:

参考文章:https://github.com/SOUI2/soui/wiki/%E7%AC%AC%E4%BA%8C%E5%8D%81%E5%85%AB%E7%AF%87%EF%BC%9ASOUI%E4%B8%AD%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8E%A7%E4%BB%B6%E5%BC%80%E5%8F%91%E8%BF%87%E7%A8%8B
参考文章:https://blog.csdn.net/u012814856/article/details/77943271

SOUI控件的自绘和消息处理相关推荐

  1. CListCtrl控件的自绘操作

    1.CListCtrl控件 :OwnerDraw Fixed = True,创建一个CListCtrl类的派生类CMyListCtrl,同时创建一个CMyListCtrl控件类型变量:CMyListC ...

  2. winform 异步弹窗窗体_玩转控件:重写/重绘Dev中MessageBox弹窗控件

    很久没有更新博客了,本想着直接发一篇<手撕ERP>系列,从控件重写.重绘,到框架搭建,再到部分模块实现+业务的.但是每次动手的时候,都觉得难以下手.直接从数据库设计开始吧,模块设计还没定下 ...

  3. 玩转控件:重写/重绘Dev中MessageBox弹窗控件

    很久没有更新博客了,本想着直接发一篇<手撕ERP>系列,从控件重写.重绘,到框架搭建,再到部分模块实现+业务的.但是每次动手的时候,都觉得难以下手.直接从数据库设计开始吧,模块设计还没定下 ...

  4. MFC 对Button控件的重绘方法(多种)

    EosPro 之MFC 对 Button的绘制 自绘按钮 一.位图按钮的实现方法:首先,我们创建一个基于对话框的应用程序CmyDialogA.MFC的CBitmapButton类,这也是最简单的功能最 ...

  5. CTabCtrl控件从零开始自绘

    原理:每种控件都是一个窗口,建立CWnd 的派生类,在派生类的onpaint()函数中进行绘制5个标签,然后创建5个窗口,作为标签页的显示窗口.建立点击消息映射,通过点击不同的标签来显示不同的窗口 实 ...

  6. Windows API 关于控件的自绘——文本颜色、背景颜色、字体

    首先要将控件设置为可以自画,例如:要自画一个按钮,在窗口的WM_CREATE中创建类名为"BUTTON"的子窗口,风格必须包含BS_OWNERDRAW.然后在父窗口的WM_DRAW ...

  7. 一步一步实现自己的模拟控件(9)——消息处理

    这次我们将要给Widget增加一些状态,并使其能够接受出消息处理扩展,测试工程中实现了一个按钮的消息处理扩展. Widget状态: 之前的控件只是绘制了一个边框,并且总是会在窗口中显示.实际上我们往往 ...

  8. 循序渐进实现仿QQ界面(三):界面调色与控件自绘

    本篇讲述如何进行界面调色.界面调色一般有两种方法,调色板和HSL色彩变换.调色板局限于256色,这里不采用,因此用HSL色彩变换实现.首先要了解一下什么是HSL色彩空间,完整且详尽的知识请到维基百科去 ...

  9. vc循序渐进实现仿QQ界面(三):界面调色与控件自绘

    本篇讲述如何进行界面调色.界面调色一般有两种方法,调色板和HSL色彩变换.调色板局限于256色,这里不采用,因此用HSL色彩变换实现.首先要了解一下什么是HSL色彩空间,完整且详尽的知识请到维基百科 ...

  10. MFC自绘控件学习总结

    前言:从这学期开始就一直在学习自绘控件(mfc),目标是做出一款播放器界面,主要是为了打好基础,因为我基础实在是很烂....说说我自己心得体会以及自绘控件的方法吧,算是吐槽吧,说的不对和不全的地方,或 ...

最新文章

  1. Logback也爆漏洞了,总结下最近log相关的几个漏洞
  2. python判断是不是文件夹_Python判断文件和文件夹是否存在的方法
  3. tensorflow-gpu2.x无法检测到GPU设备
  4. 机器学习-算法背后的理论与优化(part6)--正则化的优缺点
  5. ASP.NET MVC入门---实例演示:通过ContentResult实现主题定制
  6. 参数化测试 junit_使用JUnit 5进行更清洁的参数化测试
  7. eclipse+tomcat开发web程序
  8. Flink算子(Filter、KeyBy、Reduce和Aggregate)
  9. oj交java代码_UvaOJ java输入代码
  10. 24c存储器读写软件_必知必会-存储器层次结构
  11. Nacos集群(一)节点启动初始化源码解析
  12. linux ac97声卡驱动下载,《声卡驱动》AC97声卡/创新/主板集成
  13. 《神经网络与深度学习从理论到实践-邱锡鹏》笔记(持续更行ing)
  14. 牛课网--直通BAT面试算法精讲课--送优惠码啦
  15. 磁盘阵列RAID卡组建设置
  16. python写植物大战僵尸简单版_写个最简单的植物大战僵尸修改器吧!c和python
  17. html代码标签优化与提速,HTML代码标签优化与提速
  18. 计算机底层02-计算机指令与指令集
  19. 性价比高的口粮酒推荐,聪明人都选这3款,口感醇厚,纯粮好喝
  20. 项目规范,介绍,规划与搭建,模块化开发,网站favicon,网站TDK

热门文章

  1. 四川大学计算机学院研究生推免细则,四川大学计算机学院2012届硕士研究生推荐免试实施细则...
  2. 怎么完全卸载赛门铁克_赛门铁克专用卸载工具
  3. oracle没有卸载,oracle卸载没有正确卸载怎么办??
  4. 微模块、冷通道监控系统解决方案
  5. 计算机无法预览文件,win10系统百度网盘文件无法预览的解决方法
  6. 学习编程必备常用英语单词
  7. C语言typedef用法详解
  8. 《Java从入门到放弃》系列文章改版中...
  9. [通信原理]关于QPSK信号包络起伏问题的研究
  10. 最新免费纯净版PE制作工具V2.1【更新说明】