上一节内容已经搭好了主框架,本章就在这个框架下添砖加瓦了。这一节主要讲SOUI的消息映射,在SOUI里使用了WTL的消息映射方式,当主窗口收到消息后会根据情况转发消息给SOUI的控件,在控件里我们使用本
//消息映射列表
SOUI_MSG_MAP_BEGIN()
SOUI_MSG_MAP_END()
来处理消息。在这之前添加关心的消息即可,所有可用消息查看msgcrack.h即可查看。对于一大多数消息直接 MSG_WM_XXXX(XXXX代表消息名比如MSG_WM_SIZE即可处理WM_SIZE消息)。而且这个消息信息已经被crack了,可以直接使用。
// void OnSize(UINT nType, CSize size)
#define MSG_WM_SIZE(func) \
if (uMsg == WM_SIZE) \
{ \
SetMsgHandled(TRUE); \
func((UINT)wParam, _WTYPES_NS::CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); \
lResult = 0; \
if(IsMsgHandled()) \
return TRUE; \
}
如上MSG_WM_SIZE的定义,上面注释的函数即是你需要用来处理这个消息的函数原型。这样就可以方便的处理各种消息。当然还提供了消息区间等其它方便处理的宏。
这里我们要自绘控件当然少不了处理绘制消息WM_PAINT。但是因为WM_PAINT默认情况下传入的是DC,但是SOUI是DUI,它定义了自己的绘制对像,所以它重定义了一个MSG_WM_PAINT_EX宏来处理绘制消息。代码如下:
#pragma once
#include <core\SWnd.h>
SNSBEGIN
class SCharts :
public SWindow
{
DEF_SOBJECT(SWindow, L"scharts")
public:
protected:
void OnPaint(IRenderTarget* pRT);
//属性列表
SOUI_ATTRS_BEGIN()
SOUI_ATTRS_END()
//消息映射列表
SOUI_MSG_MAP_BEGIN()
MSG_WM_PAINT_EX(OnPaint)
SOUI_MSG_MAP_END()
};
SNSEND
这样我们实现OnPaint即可实现自定义绘制。
下面绘制一个拆线图:
最后效果如下:
SCharts.h
#pragma once
#include <core\SWnd.h>
#include <vector>
SNSBEGIN
class SCharts :
public SWindow
{
DEF_SOBJECT(SWindow, L"scharts")
public:
protected:
void OnPaint(IRenderTarget* pRT);
void CalcPoint(std::vector<POINT>& ptList);
//属性列表
SOUI_ATTRS_BEGIN()
SOUI_ATTRS_END()
//消息映射列表
SOUI_MSG_MAP_BEGIN()
MSG_WM_PAINT_EX(OnPaint)
SOUI_MSG_MAP_END()
};
SNSEND
SCharts.cpp
#include "stdafx.h"
#include "SCharts.h"
#include <random>
void SCharts::OnPaint(IRenderTarget* pRT)
{
SPainter painter;
BeforePaint(pRT, painter);
std::vector<POINT> ptList;
std::default_random_engine random(time(NULL));
CRect rcClient;
GetClientRect(&rcClient);
std::uniform_int_distribution<int> dis1(0, rcClient.Height());
for (int i = 0; i < 500;i++) {
ptList.push_back({ i * 10,dis1(random)});
}
CalcPoint(ptList);
pRT->DrawLines(ptList.data(), ptList.size());
AfterPaint(pRT, painter);
}
void SCharts::CalcPoint(std::vector<POINT>& ptList)
{
CRect rcClient;
GetClientRect(&rcClient);
for (auto& pt : ptList)
{
pt.x +=rcClient.left ;
pt.y = rcClient.bottom - pt.y;
}
}
XML仅仅是简单的去掉了前面的背景色。
上面的绘制代码主要调用DrawLines来绘制多线条。
PS:BeforePaint和AfterPaint用于保存和恢复IRenderTarget的绘制对象。因为SOUI的调用是一层一层绘制的,如果你不恢复绘制对象将会影响后面的绘制。