duilib源码修改之WindowImplBase类OnCreate函数

问题:

duilib默认新建窗体的左上角为屏幕左上角,无法自己输入参数修改,如下 代码:

#include "stdafx.h"
#include "MainFrame.h"

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int nCmdShow)
{
	CPaintManagerUI::SetInstance(hInstance);


	CWndShadow::Initialize(hInstance);
	CMainFrame* pFrame = new CMainFrame();  //自己的窗口类继承自WindowImpBase
	if (pFrame == NULL)
		return 0;
	DWORD dwStyle = UI_WNDSTYLE_FRAME;
	dwStyle = dwStyle^WS_MAXIMIZEBOX;
	pFrame->Create(NULL, _T("mywindow"), dwStyle, WS_EX_STATICEDGE | WS_EX_APPWINDOW, 1, 1, 0, 0);  //倒数第3第4个参数可以设置duilib左上角的坐标,倒数第1第2个参数因为继承了WindowImpBase,
	                                                                                               //WindowImpBase类中在创建窗口大小时会取xml文件中的窗口大小数据,顾此处两个参数值无效。
	pFrame->CenterWindow();
	::ShowWindow(*pFrame, SW_SHOW);

	CPaintManagerUI::MessageLoop();

	::CoUninitialize();
	return 0;
}

在上面代码中pFrame->Create函数中最后四个参数无效,输入也不会生效,这是由于窗口创建已经在基类WindowImpBase中的OnCreate函数中触发,而且在次函数中还会设置窗口的初始位置,由于设置窗口位置(SetWindowPos)的Rect是从GetClientRect获取的,因此导致Rect结构top和left都为0,即窗口的位置的左上角坐标始终为(0,0)。

代码如下:(下面已经做了修改,注释部分)

LRESULT WindowImplBase::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
	styleValue &= ~WS_CAPTION;
	::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
	RECT rcWindow;
	//::GetClientRect(*this, &rcClient);         //此处做了修改,因为使用GetClientRect为获得控件相自身的坐标大小,top和left都为0,导致无法设置窗口的左上角坐标
	::GetWindowRect(*this, &rcWindow);
	::SetWindowPos(*this, NULL, rcWindow.left, rcWindow.top, rcWindow.right - rcWindow.left, \
		rcWindow.bottom - rcWindow.top, SWP_FRAMECHANGED);

	m_PaintManager.Init(m_hWnd);
	m_PaintManager.AddPreMessageFilter(this);

	CDialogBuilder builder;
	CDuiString strResourcePath=m_PaintManager.GetResourcePath();
	if (strResourcePath.IsEmpty())
	{
		strResourcePath=m_PaintManager.GetInstancePath();
		strResourcePath+=GetSkinFolder().GetData();
	}
	m_PaintManager.SetResourcePath(strResourcePath.GetData());

	switch(GetResourceType())
	{
	case UILIB_ZIP:
		m_PaintManager.SetResourceZip(GetZIPFileName().GetData(), true);
		break;
	case UILIB_ZIPRESOURCE:
		{
			HRSRC hResource = ::FindResource(m_PaintManager.GetResourceDll(), GetResourceID(), _T("ZIPRES"));
			if( hResource == NULL )
				return 0L;
			DWORD dwSize = 0;
			HGLOBAL hGlobal = ::LoadResource(m_PaintManager.GetResourceDll(), hResource);
			if( hGlobal == NULL ) 
			{
#if defined(WIN32) && !defined(UNDER_CE)
				::FreeResource(hResource);
#endif
				return 0L;
			}
			dwSize = ::SizeofResource(m_PaintManager.GetResourceDll(), hResource);
			if( dwSize == 0 )
				return 0L;
			m_lpResourceZIPBuffer = new BYTE[ dwSize ];
			if (m_lpResourceZIPBuffer != NULL)
			{
				::CopyMemory(m_lpResourceZIPBuffer, (LPBYTE)::LockResource(hGlobal), dwSize);
			}
#if defined(WIN32) && !defined(UNDER_CE)
			::FreeResource(hResource);
#endif
			m_PaintManager.SetResourceZip(m_lpResourceZIPBuffer, dwSize);
		}
		break;
	}

	CControlUI* pRoot=NULL;
	if (GetResourceType()==UILIB_RESOURCE)
	{
		STRINGorID xml(_ttoi(GetSkinFile().GetData()));
		pRoot = builder.Create(xml, _T("xml"), this, &m_PaintManager);
	}
	else
		pRoot = builder.Create(GetSkinFile().GetData(), (UINT)0, this, &m_PaintManager);
	ASSERT(pRoot);
	if (pRoot==NULL)
	{
		MessageBox(NULL,_T("加载资源文件失败"),_T("Duilib"),MB_OK|MB_ICONERROR);
		ExitProcess(1);
		return 0;
	}
	m_PaintManager.AttachDialog(pRoot);
	m_PaintManager.AddNotifier(this);

	InitWindow();
	return 0;
}

修改

如上面代码所示,改用::GetWindowRect(*this, &rcWindow)替换

::GetClientRect(*this, &rcClient);   

两者的区别可以参考以下文章:

GetWindowRect与GetClientRect 的区别

修改之后,可以在pFrame->Create函数中指定倒数第三个与第四个参数设置窗体的左上角初始位置,设置为0,0则跟修改之前一样,但是可以支持自定义修改。

你可能感兴趣的:(windows,c/c++,DuiLib)