消息通讯
真窗口
1 2 3 4 5 6 7 8 9 10 |
#define WM_MYMSG (WM_USER+1000) LRESULT OnMyMsg(UINT uMsg, WPARAM wp, LPARAM lp, BOOL& bHandled) { return 0; } BEGIN_MSG_MAP_EX(CMainDlg) // my msg MESSAGE_HANDLER(WM_MYMSG, OnMyMsg) MSG_WM_CREATE(OnCreate) END_MSG_MAP() |
::SendMessage
SOUI控件
- 在
SOUI
中可以使用SWindow::SSendMessage
来向一个目标窗口发送一个消息来通讯,但不支持PostMessage
,目标窗口在SOUI
窗口的消息映射表中响应发送过来的消息。
1 2 3 |
SOUI_MSG_MAP_BEGIN() MSG_WM_PAINT_EX(OnPaint) SOUI_MSG_MAP_END() |
SOUI事件机制
- 每一个事件对应一个
EventArg
类,事件在控件中使用FireEvent
启动事件路由,应用程序可以在事件响应映射表中对各种事件统一处理,也可以使用subscribeEvent
来直接订阅特定SOUI
窗口的一个事件,直接将事件与事件处理函数关联起来。
1 2 3 4 5 6 7 8 9 10 |
#define EVT_SIW_IMAGE_CLICKED (EVT_EXTERNAL_BEGIN + 3050) #define EVT_SIW_IMAGE_CHANGED (EVT_EXTERNAL_BEGIN + 3051) m_pSlideImgWnd = FindChildByName2<SSlideImageWnd>(L"info_ads_slide"); if (m_pSlideImgWnd) { m_pSlideImgWnd->Clear(); m_pSlideImgWnd->SetVisible(FALSE, TRUE); m_pSlideImgWnd->GetEventSet()->subscribeEvent(EVT_SIW_IMAGE_CLICKED, Subscriber(&XYInfoAdsWnd::OnAdsImageClicked, this)); } |
Offset和Pos2type
- 当窗口大小不确定时,
SOUI
提供了pos2type
和offset
来处理相对位置。 offset
属性是SOUI
在通过pos
属性完成坐标定位后再将坐标进行偏移的属性。和pos
中一般使用象素为单位不同,offset
是以控件最后的大小为单位进行平移。
pos2type | offset |
center | -0.5,-0.5 |
lefttop | 0,0 |
leftmid | 0,-0.5 |
leftbottom | 0,-1 |
midtop | -0.5,0 |
midbottom | -0.5,-1 |
righttop | -1,0 |
rightmid | -1,-0.5 |
rightbottom | -1,-1 |
cache
问题
- 一般子窗口会比父窗口小,子窗口请求重绘时,要执行父窗口的绘制函数,如果父窗口没有根据当前的裁剪范围来确定自己的绘制范围,那么尽管有裁剪区简直了不会绘制超出边界,在实际执行过程中,超出裁剪区的绘制行为也可能极大的影响UI的性能。
方案
- 让每个窗口的绘制方法都实现只绘制在裁剪区的那部分。
- 实现起来比较麻烦,裁剪区的计算算法可能是一个瓶颈。
- 让每个窗口都保持背景窗口的内容,当窗口需要刷新时,直接把背景内容拿过来在上面画。
- SOUI中,使用了cache的机制。
- 当cache为0时,窗口的绘制和之前提到的流程是一致的,如果窗口比较大,需要一时半会的区域比较小,就会比较慢。
- 当cache为1时,窗口绘制的内容会被保存到一张缓存图上,当其他窗口刷新并导致该窗口重绘时,直接从缓存中复制出来。
PreTranslateMessage
- 在SOUI中实现PreTranslateMessage,我们首先需要实现一个接口:
1 2 3 |
struct IMessageFilter { virtual BOOL PreTranslateMessage(MSG* pMsg) = 0; }; |
- 向当前的MessageLoop注册该IMessageFilter
1 2 3 4 5 6 7 8 9 10 |
class SOUI_EXP SMessageLoop { public: SArray<IMessageFilter*> m_aMsgFilter; // Message filter operations BOOL AddMessageFilter(IMessageFilter* pMessageFilter); BOOL RemoveMessageFilter(IMessageFilter* pMessageFilter); //... }; |
- 获取当前消息循环
- 在SHostWnd 或者SHostDialog中可以调用SHostWnd::GetMsgLoop()方法获得
- 在SWindow中,则可以调用SWindow::GetContainer()->GetMsgLoop()获得
提供SOUI应用程序渲染性能
更高效的渲染引擎
- gdi
- gdi+
- skia
绘制缓存
- cache缓存机制
非背景混合技术
- bkgndBlend
- 1代表刷新时使用背景混合
- 0代表窗口刷新时直接刷新自己,而不请求父窗口刷新背景。
分层窗口
- SOUI采用XML定义UI,要定义分层窗口只需要一个layeredWindow="1"的属性即可
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ Dump分析:未捕获的异常,查看内存相关命令03/25
- ♥ Windows进程通信相关03/10
- ♥ 各平台调试方法总结记述一09/25
- ♥ SOUI源码:log4z06/24
- ♥ 51CTO:Linux C++网络编程三08/16
- ♥ Windows 核心编程 _ 进程二06/19