参照官方的指导文档,显示一个最简单windows窗口。入口源文件先加上这几句代码:

// 必须放在所有头文件包含之前. 预处理指令,编译优化,排除windows头文件(windows.h)中较少使用的组件
#define WIN32_LEAN_AND_MEAN	
// 必须放在所有头文件包含之前.  兼容性控制宏. 禁用微软对不安全函数(如scanf、strcpy等)的编译警告
#define _CRT_SECURE_NO_DEPRECATE

#include <duilib/UIlib.h>
#include <windows.h>
#include <objbase.h>

using namespace DuiLib;

官方demo还有这一段(我没加这一段):

#ifdef _DEBUG
#   ifdef _UNICODE
#       pragma comment(lib, "..\\bin\\DuiLib_ud.lib")
#   else
#       pragma comment(lib, "..\\bin\\DuiLib_d.lib")
#   endif
#else
#   ifdef _UNICODE
#       pragma comment(lib, "..\\bin\\DuiLib_u.lib")
#   else
#       pragma comment(lib, "..\\bin\\DuiLib.lib")
#   endif
#endif

然后下面是窗口实例和消息响应:

// 窗口实例及消息响应部分
class CFrameWindowWnd : public CWindowWnd, public INotifyUI
{
public:
    CFrameWindowWnd() {};

    // 窗口唯一标识符
    LPCTSTR GetWindowClassName() const { return _T("UIMainFrame"); };

    // 定义窗口类样式。 UI_CLASSSTYLE_FRAME:窗口大小改变时触发重绘,通常用于带标题栏、边框的标准窗体。
    // CS_DBLCLKS‌:Windows 标准样式,启用窗口对鼠标双击消息的响应能力
    UINT GetClassStyle() const { return UI_CLASSSTYLE_FRAME | CS_DBLCLKS; };

    // 处理窗口生命周期终结
    void OnFinalMessage(HWND /*hWnd*/) { delete this; };

    // 核心功能:控件事件分发、消息传递枢纽
    void Notify(TNotifyUI& msg)
    {
        if (msg.sType == _T("click")) {
            if (msg.pSender->GetName() == _T("I服了You")) { // 即点击的根控件root,代码见下面
                Close(); // 关闭窗口
            }
        }
    }

    LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        if (uMsg == WM_CREATE) { // 成功创建窗口后, 系统会立即发送 WM_CREATE 消息, 标志着窗口句柄已有效但尚未显示
            m_pm.Init(m_hWnd); // 绑定窗口句柄,初始化绘图环境
            CControlUI* root = new CButtonUI;
            root->SetName(_T("I服了You"));
            root->SetBkColor(0xFFcccccc);
            m_pm.AttachDialog(root); // 关联控件树根节点,启动界面渲染. 根控件与绘图管理器关联. 这里根控件为root
            m_pm.AddNotifier(this); // 注册事件监听器,接收控件通知(如 Notify 消息)
            return 0;
        }
        else if (uMsg == WM_DESTROY) { // 窗口销毁
            ::PostQuitMessage(0); // 0表示正常退出
        }
        
        LRESULT lRes = 0;
        // 将 Windows 消息(uMsg)交由 CPaintManagerUI 处理(即交给对应控件处理),若返回 true 表示消息已被消费,直接返回处理结果
        if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes)) return lRes;
        return CWindowWnd::HandleMessage(uMsg, wParam, lParam); // 基类默认处理消息的流程
    }

public:
    CPaintManagerUI m_pm; // 承担界面绘制、消息处理和控件管理的核心职责
};

再下面是程序入口:

// 程序入口及Duilib初始化部分
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow)
{
    CPaintManagerUI::SetInstance(hInstance);
    CPaintManagerUI::SetResourcePath(CPaintManagerUI::GetInstancePath());

    CFrameWindowWnd* pFrame = new CFrameWindowWnd();
    if (pFrame == NULL) return 0;
    pFrame->Create(NULL, _T("别人笑我太疯癫,我笑他人看不穿"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE);
    pFrame->ShowWindow(true);
    pFrame->CenterWindow(); // 窗口居中显示
    CPaintManagerUI::MessageLoop();

    return 0;
}

运行结果:

ok .  点击页面窗口消失。 如果不想显示系统标题栏,需加上WM_NCACTIVATE、WM_NCCALCSIZE、WM_NCPAINT 这几个消息处理,窗口实例和消息响应这部分改为如下代码:

// 窗口实例及消息相应部分
class CFrameWindowWnd : public CWindowWnd, public INotifyUI
{
public:
    CFrameWindowWnd() {};

    // 窗口唯一标识符
    LPCTSTR GetWindowClassName() const { return _T("UIMainFrame"); };

    // 定义窗口类样式。 UI_CLASSSTYLE_FRAME:窗口大小改变时触发重绘,通常用于带标题栏、边框的标准窗体。
    // CS_DBLCLKS‌:Windows 标准样式,启用窗口对鼠标双击消息的响应能力
    UINT GetClassStyle() const { return UI_CLASSSTYLE_FRAME | CS_DBLCLKS; };

    // 处理窗口生命周期终结
    void OnFinalMessage(HWND /*hWnd*/) { delete this; };

    // 核心功能:控件事件分发、消息传递枢纽
    void Notify(TNotifyUI& msg)
    {
        if (msg.sType == _T("click")) {
            if (msg.pSender->GetName() == _T("I服了You")) { // 即点击的根控件root,代码见下面
                Close(); // 关闭窗口
            }
        }
    }

    LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        if (uMsg == WM_CREATE) { // 成功创建窗口后, 系统会立即发送 WM_CREATE 消息, 标志着窗口句柄已有效但尚未显示
            m_pm.Init(m_hWnd); // 绑定窗口句柄,初始化绘图环境
            CControlUI* root = new CButtonUI;
            root->SetName(_T("I服了You"));
            root->SetBkColor(0xFFcccccc);
            m_pm.AttachDialog(root); // 关联控件树根节点,启动界面渲染. 根控件与绘图管理器关联. 这里根控件为root
            m_pm.AddNotifier(this); // 注册事件监听器,接收控件通知(如 Notify 消息)
            return 0;
        }
        else if (uMsg == WM_DESTROY) { // 窗口销毁
            ::PostQuitMessage(0); // 0表示正常退出
        }
        // 不想使用系统的标题栏和边框这些非客户区绘制,加上下面这俩分支(WM_NCACTIVATE、WM_NCCALCSIZE、WM_NCPAINT 消息)的处理
        else if (uMsg == WM_NCACTIVATE) { // 窗口获得焦点或失去焦点时收到该消息
            if (!::IsIconic(m_hWnd)) {
                // TRUE: 允许系统将非客户区绘制为失活状态(灰色标题栏)
                // FALSE: 阻止系统默认的激活状态绘制,可能用于实现自定义标题栏样式
                return (wParam == 0) ? TRUE : FALSE;
            }
        }
        else if (uMsg == WM_NCCALCSIZE) { // 当窗口大小或位置发生变化时,系统会发送该消息
            return 0; // 返回0屏蔽系统默认的标题栏计算. 这使得开发者可以用客户区完全模拟自定义标题栏,实现更灵活的界面设计
        }
        else if (uMsg == WM_NCPAINT) { // 用于非客户区绘制的消息,在duilib中主要用于屏蔽系统默认标题栏以实现自定义界面
            return 0;
        }
        LRESULT lRes = 0;
        // 将 Windows 消息(uMsg)交由 CPaintManagerUI 处理(即交给对应控件处理),若返回 true 表示消息已被消费,直接返回处理结果
        if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes)) return lRes;
        return CWindowWnd::HandleMessage(uMsg, wParam, lParam); // 基类默认处理消息的流程
    }

public:
    CPaintManagerUI m_pm; // 承担界面绘制、消息处理和控件管理的核心职责
};

运行结果:

ok. 后续再看下用自定义xml布局写页面。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐