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则跟修改之前一样,但是可以支持自定义修改。