duilib自定义控件

在windows下开发界面,现在很多公司会用到duilib,这个库其实不难,只要你有win32和MFC的开发经验,很容易上手,但是很多新手没有MFC的经验,为了让新手们可以快速上手,解决工作上的问题。今天我跟大家说说在duilib下,如何自定义控件,并且可以根据主窗口大小改变自己的大小,至于使用场景很多地方都会用到,比如播放器。

好了我们先看一下,在duilib下如何定义一个自定义控件,在duilib下,所有的控件都派生于CControlUI,所以我们的自定义控件也要继承这个类,具体代码如下,很简单,自己看。

class CWndUI : public CControlUI
{
public:
	CWndUI() : m_hWnd(NULL){}

	virtual void SetVisible(bool bVisible = true)
	{
		__super::SetVisible(bVisible);
		::ShowWindow(m_hWnd, bVisible);
	}

	virtual void SetInternVisible(bool bVisible = true)
	{
		__super::SetInternVisible(bVisible);
		::ShowWindow(m_hWnd, bVisible);
	}

	virtual void SetPos(RECT rc)
	{
		__super::SetPos(rc);
		::SetWindowPos(m_hWnd, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOACTIVATE);
	}

	BOOL Attach(HWND hWndNew)
	{
		if (!::IsWindow(hWndNew))
		{
			return FALSE;
		}

		m_hWnd = hWndNew;
		return TRUE;
	}

	HWND Detach()
	{
		HWND hWnd = m_hWnd;
		m_hWnd = NULL;
		return hWnd;
	}

	HWND GetHWND()
	{
		return m_hWnd;
	}

protected:
	HWND m_hWnd;
};

现在,我们已经定义了自己的控件,看看在XML中如何使用,具体XML如下:



    
        
		
  				
					
					
				
		
    

在这个XML文件里,Wnd1就是我们的自定义控件,当duilib读取这个文件的时候,如果遇到不认识的控件,比如Wnd1,这时duilib框架会调用我们的CreateControl函数,所以我们需要在这个函数里完成自定义窗口的创建,绑定,具体代码如下:

virtual CControlUI* CreateControl(LPCTSTR pstrClassName)
{
	CDialogBuilder builder;
		
	if (_tcsicmp(pstrClassName, _T("Caption")) == 0)
	{
		CControlUI* pUI = builder.Create(_T("caption.xml"), NULL, NULL, &m_PaintManager, NULL);

		return pUI;
	}	
	else if (_tcsicmp(pstrClassName, _T("Wnd1")) == 0)
	{
		CWndUI  *pUI = new CWndUI;
		HWND    hWnd = CreateWindow(_T("MyWnd"), _T("win32"), WS_VISIBLE | WS_CHILD , 0, 0, 0, 0, m_PaintManager.GetPaintWindow(), NULL, NULL, NULL);			
		pUI->Attach(hWnd);
		pUI->OnSize += MakeDelegate(this, &CDuiFrameWnd::OnTargetSizeChanged);
		return pUI;
	}
	else if (_tcsicmp(pstrClassName, _T("StatusPanel")) == 0)
	{
		CControlUI* pUI = builder.Create(_T("status.xml"), NULL, NULL, &m_PaintManager, NULL);

		return pUI;
	}
		
	return WindowImplBase::CreateControl(pstrClassName);
}

至此我们的自定义控件就创建完成了,但是如果大家仔细观察,会发现在CreateWindow的时候,我们使用的是MyWnd窗口类,这个类是我们自己定义的窗口,它的功能就是定时在窗口填充红色,它的定义和窗口处理函数如下:

LRESULT CALLBACK WndDisplayProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	//  int wmId, wmEvent;  

	switch (message)
	{
	case WM_CREATE:
	{
		::SetTimer(hWnd, ID_TIMER_SHOW_PIC, 33, NULL);
	}

	break;

	case WM_DESTROY:
	{
		::KillTimer(hWnd, ID_TIMER_SHOW_PIC);
	}

	break;

	case WM_TIMER:
	{
		HDC hDC = ::GetDC(hWnd);

		RECT rc = { 0 };

		GetClientRect(hWnd, &rc); 

		HBRUSH hbr = ::CreateSolidBrush(RGB(0xff, 0x00, 0x00));

		::FillRect(hDC, &rc, hbr);

		::DeleteObject(hbr);

		::ReleaseDC(hWnd, hDC);
	}
	break;

	default:
		return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}

ATOM MyRegisterWnd(TCHAR *szClass, WNDPROC proc)
{
	WNDCLASS wcls;
	// check to see if class already registered  
	if (GetClassInfo(GetModuleHandle(NULL), szClass, &wcls))
	{
		return 1;// name already registered - ok if it was us  
	}
	// Use standard "button" control as a template.  
	GetClassInfo(NULL, _T("button"), &wcls);
	// set new values  
	wcls.style |= CS_DBLCLKS; // Make it to receive double clicks  
	wcls.lpfnWndProc = proc;
	wcls.hInstance = GetModuleHandle(NULL);
	wcls.lpszClassName = szClass;

	return RegisterClass(&wcls);
}

现在窗口已经创建完成,具体效果如下:

duilib自定义控件_第1张图片

中间红色的部分就是我们的自定义窗口,现在我们还需要处理一个细节,就是WM_SIZE消息,当我们改变主窗口大小的时候,自定义窗口也需要做相应的调整,这就需要我们给自定义窗口添加一个WM_SIZE消息处理函数,在前面的CreateControl中,我们已经为它绑定了一个SIZE消息处理函数,现在看看它的具体代码:

bool OnTargetSizeChanged(void* param)
{
	CWndUI * pUI = static_cast(m_PaintManager.FindControl(_T("wndMedia")));

	if (!pUI)
		return false;

	const RECT& rc_pos = pUI->GetPos();

	::MoveWindow(pUI->GetHWND(), rc_pos.left, rc_pos.top, rc_pos.right - rc_pos.left, rc_pos.bottom - rc_pos.top, TRUE);

	return true;
}

好了,到此一个自定义窗口就创建成功,并且可以响应WM_SIZE消息。需要代码的可以到下面去下载:

https://download.csdn.net/download/u011711997/10386074

你可能感兴趣的:(duilib杂谈)