在duilib中嵌入win32控件或者MFC控件

    玩duilib的时候在网上看到其余文章在duilib中嵌入MFC的例子,屡试不行,总是显示不出MFC控件或者win32控件,后来本身研究了一番,发现问题所在,并拿出来分享一下。 ide

    首先duilib是什么这里很少说,自行百度。这个例子效果是这样的,在dui界面中能够嵌入win32的按钮,以下图:函数

点击win32按钮能够响应消息:ui

 

至于网上其余教程我试验不灵光的缘由是,duilib中使用UpdateLayeredWindow来支持窗口的透明效果,就是背景图片是个带透明通道的png图片的时候,就是有半透明渐变阴影的时候设置皮肤文件的属性bktrans:<Window size="544,394" caption="22,22,22,50" roundcorner="5,5" bktrans="true">this

只要这个是true,添加到主窗口的子窗口都隐藏不可见了。code

 

暂时想到的办法就是建立一个以桌面为父窗口的window贴到dui界面上,而后再把须要添加的win32控件之类的加到这个窗口上来。继承

 

代码吭哧吭哧撸起来教程

首先咱们这个须要是个dui控件能够支持皮肤文件编辑的,因此须要继承CControlUI,我不想像其余例子那样另外再建立window而后Attach,这样很麻烦,那么再继承自CWindowWnd就好了,那么咱们的类看起来是这样子的接口

class CFrameWndUI : public CControlUI, public CWindowWnd
public:
	CFrameWndUI();
	virtual ~CFrameWndUI();

	LPCTSTR GetWindowClassName() const;

protected:
	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override;

};

GetWindowClassName就返回个窗口类名了图片

LPCTSTR CFrameWndUI::GetWindowClassName() const
{
    return _T("CFrameWndUI");
}

咱们在构造函数里为本身建立一个窗口it

CFrameWndUI::CFrameWndUI()
{
    // 建立一个无标题无边框的窗口
    Create(NULL, _T("CFrameWndUI"), UI_WNDSTYLE_DIALOG & ~WS_CAPTION,  WS_EX_TOOLWINDOW, 0, 0, 0, 0);
}

要建立无标题的窗口就不能设置WS_CAPTION,扩展样式里面WS_EX_TOOLWINDOW为了让任务栏不出现窗口图标,不设置的话,画面就是这样

重写CControlUI的 virtual void DoInit();,在里面建立3个按钮

void CFrameWndUI::DoInit()
{
    // 建立win32类型的按钮
    // 参数HMENU借来传递按钮ID
    CreateWindow(_T("BUTTON"), _T("我是按钮1"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 0, 0, 80, 30, m_hWnd,
                 (HMENU)IDB_TEST1, CPaintManagerUI::GetInstance(), NULL);

	CreateWindow(_T("BUTTON"), _T("我是按钮2"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 0, 40, 80, 30, m_hWnd,
		(HMENU)IDB_TEST2, CPaintManagerUI::GetInstance(), NULL);

	CreateWindow(_T("BUTTON"), _T("我是按钮3"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 0, 80, 80, 30, m_hWnd,
		(HMENU)IDB_TEST3, CPaintManagerUI::GetInstance(), NULL);
}

接下来最重要的是根据主窗口的位置和控件大小设置窗口位置了,给类添加个私有函数AdjustRect,而且覆盖DoPaint,在DoPaint里面调用AdjustRect

class CFrameWndUI : public CControlUI, public CWindowWnd
public:
	CFrameWndUI();
	virtual ~CFrameWndUI();

	LPCTSTR GetWindowClassName() const;

	virtual void DoInit();

	virtual void DoPaint(HDC hDC, const RECT& rcPaint);

private:
	void AdjustRect(); // 调整本身的UI大小和坐标

};
void CFrameWndUI::AdjustRect()
{
    // 获取APP客户端区域
    CDuiRect rcApp;
    GetWindowRect(m_pManager->GetPaintWindow(), &rcApp);

    CDuiRect rcSelf(m_rcItem);

    rcSelf.left += rcApp.left;
    rcSelf.top += rcApp.top;

    // 是不是固定坐标
    if(m_bFloat)
    {
        rcSelf.right = m_cxyFixed.cx;
        rcSelf.bottom = m_cxyFixed.cy;
    }

    ::SetWindowPos(m_hWnd, NULL, rcSelf.left, rcSelf.top, rcSelf.right, rcSelf.bottom, SWP_NOACTIVATE);
}

void CFrameWndUI::DoPaint(HDC hDC, const RECT& rcPaint)
{
    __super::DoPaint(hDC, rcPaint);
    AdjustRect();
}

这里计算代码很简单,就是获取主窗口的坐标,而后加上控件坐标就是x,y了,当控件是float的时候,控件大小就是修正大小m_cxyFixed,不然就是自适应的大小。

控件如何自动建立就是新建的一个dui界面class CMainWnd : public WindowImplBase,继承自WindowImplBase就会有个virtual CControlUI* CreateControl(LPCTSTR pstrClass);里面判断控件类型,new一个就是了,皮肤文件里面<FrameWnd name="test" mouse="false" float="true"  pos="100,100,0,0" width="200" height="200" />就是这样便可

CControlUI* CMainWnd::CreateControl(LPCTSTR pstrClass)
{
	if (_tcsicmp(pstrClass, _T("FrameWnd")) == 0)
	{

		CFrameWndUI  *pUI = new CFrameWndUI();
		      
		return pUI;
	}

	return NULL;
}

 

如今运行看看,有效果了,

而后拖动主窗口看看,发现按钮并无跟随窗口移动

这里咱们须要再添加个处理,监听主窗口的WM_WINDOWPOSCHANGED消息,方法就是集成一个接口IMessageFilterUI,实现MessageHandler

class CFrameWndUI : public CControlUI, public CWindowWnd, public IMessageFilterUI
{
public:
	CFrameWndUI();
	virtual ~CFrameWndUI();

	LPCTSTR GetWindowClassName() const;

	virtual void DoInit();

	virtual void DoPaint(HDC hDC, const RECT& rcPaint);

	virtual LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled) override;

protected:
	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override;

private:
	void AdjustRect(); // 调整本身的UI大小和坐标
};

而后在DoInit注册消息监听

void CFrameWndUI::DoInit()
{
    // 添加主窗口消息过滤器
    m_pManager->AddMessageFilter(this);

    ...
}
LRESULT CFrameWndUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
{
    // 判断主窗口位置改变就调整窗口
    if(uMsg == WM_WINDOWPOSCHANGED)
    {
        AdjustRect();
    }

    return 0;
}

要处理win32按钮消息,就是在HandleMessage里处理WM_COMMAND消息便可

LRESULT CFrameWndUI::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LRESULT lRes = 0;
    BOOL bHandled = FALSE;

    switch(uMsg)
    {
    case WM_COMMAND:
        lRes = OnCommand(uMsg, wParam, lParam, bHandled);
        break;

    default:
        break;
    }

    if(bHandled)
    {
        return lRes;
    }

    return __super::HandleMessage(uMsg, wParam, lParam);
}

 

完整代码:

#pragma once

/*!
 * @file FrameWndUI.h
 * @date 2017/07/14 14:33
 *
 * @author 阿力
 *
 * @brief 将win32或者MFC的控件嵌入到duilib上面
 *
*/
class CFrameWndUI : public CControlUI, public CWindowWnd, public IMessageFilterUI
{
public:
	CFrameWndUI();
	virtual ~CFrameWndUI();

	LPCTSTR GetWindowClassName() const;

	virtual void DoInit();

	virtual void DoPaint(HDC hDC, const RECT& rcPaint);

	virtual LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled) override;

protected:
	virtual LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override;

private:
	void AdjustRect(); // 调整本身的UI大小和坐标
	virtual LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
};

FrameWndUI.cpp

#include "stdafx.h"
#include "FrameWndUI.h"

static CONST INT IDB_TEST1 = 0x121;
static CONST INT IDB_TEST2 = 0x122;
static CONST INT IDB_TEST3 = 0x123;

CFrameWndUI::CFrameWndUI()
{
    // 建立一个无标题无边框的窗口
    Create(NULL, _T("CFrameWndUI"), UI_WNDSTYLE_DIALOG & ~WS_CAPTION, WS_EX_LAYERED | WS_EX_TOOLWINDOW, 0, 0, 0, 0);

}

CFrameWndUI::~CFrameWndUI()
{
    if(m_pManager)
    {
        // 移除主窗口消息过滤器
        m_pManager->RemoveMessageFilter(this);
    }
}

LPCTSTR CFrameWndUI::GetWindowClassName() const
{
    return _T("CWndUI");
}

void CFrameWndUI::DoInit()
{
    // 添加主窗口消息过滤器
    m_pManager->AddMessageFilter(this);

    // 建立win32类型的按钮
    // 参数HMENU借来传递按钮ID
    CreateWindow(_T("BUTTON"), _T("我是按钮1"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 0, 0, 80, 30, m_hWnd,
                 (HMENU)IDB_TEST1, CPaintManagerUI::GetInstance(), NULL);

	CreateWindow(_T("BUTTON"), _T("我是按钮2"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 0, 40, 80, 30, m_hWnd,
		(HMENU)IDB_TEST2, CPaintManagerUI::GetInstance(), NULL);

	CreateWindow(_T("BUTTON"), _T("我是按钮3"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON, 0, 80, 80, 30, m_hWnd,
		(HMENU)IDB_TEST3, CPaintManagerUI::GetInstance(), NULL);
}

void CFrameWndUI::DoPaint(HDC hDC, const RECT& rcPaint)
{
    __super::DoPaint(hDC, rcPaint);
    AdjustRect();
}

LRESULT CFrameWndUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
{
    // 判断主窗口位置改变就调整窗口
    if(uMsg == WM_WINDOWPOSCHANGED)
    {
        AdjustRect();
    }

    return 0;
}

LRESULT CFrameWndUI::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LRESULT lRes = 0;
    BOOL bHandled = FALSE;

    switch(uMsg)
    {
    case WM_COMMAND:
        lRes = OnCommand(uMsg, wParam, lParam, bHandled);
        break;

    default:
        break;
    }

    if(bHandled)
    {
        return lRes;
    }

    return __super::HandleMessage(uMsg, wParam, lParam);
}

void CFrameWndUI::AdjustRect()
{
    // 获取APP客户端区域
    CDuiRect rcApp;
    GetWindowRect(m_pManager->GetPaintWindow(), &rcApp);

    CDuiRect rcSelf(m_rcItem);

    rcSelf.left += rcApp.left;
    rcSelf.top += rcApp.top;

    // 是不是固定坐标
    if(m_bFloat)
    {
        rcSelf.right = m_cxyFixed.cx;
        rcSelf.bottom = m_cxyFixed.cy;
    }

    ::SetWindowPos(m_hWnd, NULL, rcSelf.left, rcSelf.top, rcSelf.right, rcSelf.bottom, SWP_NOACTIVATE);
}

LRESULT CFrameWndUI::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	switch (LOWORD(wParam))
	{
	case IDB_TEST1:
		::MessageBox(NULL, _T("你点了按钮1"), _T(""), MB_OK);
		break;
	case IDB_TEST2:
		::MessageBox(NULL, _T("你点了按钮2"), _T(""), MB_OK);
		break;
	case IDB_TEST3:
		::MessageBox(NULL, _T("你点了按钮3"), _T(""), MB_OK);
		break;
	default:
		break;
	}

    return 0;
}
相关文章
相关标签/搜索