![594f9102e98c8311120e9b4103187c6b.png](https://i-blog.csdnimg.cn/blog_migrate/83158941fb6355cee95a6c1703d84e16.jpeg)
![83bc6cc8bd379c2649f650c47bc4c3d0.gif](https://i-blog.csdnimg.cn/blog_migrate/c414fa332f58658ef9bbe7da5db29f7a.gif)
LRESULT WindowImplBase::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){::SetWindowLong(this->GetHWND(), GWL_STYLE, GetStyle());Init(m_hWnd);AddPreMessageFilter(this);SetWindowResourcePath(GetSkinFolder());WindowBuilder builder;std::wstring strSkinFile = GetWindowResourcePath() + GetSkinFile();auto callback = nbase::Bind(&WindowImplBase::CreateControl, this, std::placeholders::_1);auto pRoot = (Box*)builder.Create(strSkinFile.c_str(), callback, this);ASSERT(pRoot && L"Faield to load xml file.");if (pRoot == NULL) {TCHAR szErrMsg[MAX_PATH] = { 0 };_stprintf_s(szErrMsg, L"Failed to load xml file %s", strSkinFile.c_str());MessageBox(NULL, szErrMsg, _T("Duilib"), MB_OK | MB_ICONERROR);return -1;}pRoot = m_shadow.AttachShadow(pRoot);AttachDialog(pRoot);InitWindow();if (pRoot->GetFixedWidth() == DUI_LENGTH_AUTO || pRoot->GetFixedHeight() == DUI_LENGTH_AUTO) {CSize maxSize(99999, 99999);CSize needSize = pRoot->EstimateSize(maxSize);if( needSize.cx < pRoot->GetMinWidth() ) needSize.cx = pRoot->GetMinWidth();if( pRoot->GetMaxWidth() >= 0 && needSize.cx > pRoot->GetMaxWidth() ) needSize.cx = pRoot->GetMaxWidth();if( needSize.cy < pRoot->GetMinHeight() ) needSize.cy = pRoot->GetMinHeight();if( needSize.cy > pRoot->GetMaxHeight() ) needSize.cy = pRoot->GetMaxHeight();::MoveWindow(m_hWnd, 0, 0, needSize.cx, needSize.cy, FALSE);}Control *pControl = (Control*)FindControl(L"closebtn");if (pControl) {Button *pCloseBtn = dynamic_cast(pControl);ASSERT(pCloseBtn);pCloseBtn->AttachClick(nbase::Bind(&WindowImplBase::OnButtonClick, this, std::placeholders::_1));}pControl = (Control*)FindControl(L"minbtn");if (pControl){Button* pMinBtn = dynamic_cast(pControl);ASSERT(pMinBtn);pMinBtn->AttachClick(nbase::Bind(&WindowImplBase::OnButtonClick, this, std::placeholders::_1));}pControl = (Control*)FindControl(L"maxbtn");if (pControl){Button* pMaxBtn = dynamic_cast(pControl);ASSERT(pMaxBtn);pMaxBtn->AttachClick(nbase::Bind(&WindowImplBase::OnButtonClick, this, std::placeholders::_1));}pControl = (Control*)FindControl(L"restorebtn");if (pControl){Button* pRestoreBtn = dynamic_cast(pControl);ASSERT(pRestoreBtn);pRestoreBtn->AttachClick(nbase::Bind(&WindowImplBase::OnButtonClick, this, std::placeholders::_1));}return 0;}
![83bc6cc8bd379c2649f650c47bc4c3d0.gif](https://i-blog.csdnimg.cn/blog_migrate/c414fa332f58658ef9bbe7da5db29f7a.gif)
在OnCreate中,duilib做了这样几件工作:
1)设置窗口样式,取消窗口默认标题栏
::SetWindowLong(this->GetHWND(), GWL_STYLE, GetStyle()); LONG WindowImplBase::GetStyle(){LONG styleValue = ::GetWindowLong(GetHWND(), GWL_STYLE);styleValue &= ~WS_CAPTION;return styleValue;}
![83bc6cc8bd379c2649f650c47bc4c3d0.gif](https://i-blog.csdnimg.cn/blog_migrate/c414fa332f58658ef9bbe7da5db29f7a.gif)
2)窗口句柄相关的初始化
void Window::Init(HWND hWnd){m_hWnd = hWnd;ASSERT(::IsWindow(hWnd));// Remember the window context we came fromm_hDcPaint = ::GetDC(hWnd);// We'll want to filter messages globally tooGlobalManager::AddPreMessage(this);m_renderContext = GlobalManager::CreateRenderContext();RegisterTouchWindowWrapper(hWnd, 0);}
![83bc6cc8bd379c2649f650c47bc4c3d0.gif](https://i-blog.csdnimg.cn/blog_migrate/c414fa332f58658ef9bbe7da5db29f7a.gif)
3)解析XML样式文件
WindowBuilder builder;std::wstring strSkinFile = GetWindowResourcePath() + GetSkinFile();auto callback = nbase::Bind(&WindowImplBase::CreateControl, this, std::placeholders::_1);auto pRoot = (Box*)builder.Create(strSkinFile.c_str(), callback, this);ASSERT(pRoot && L"Faield to load xml file.");if (pRoot == NULL) {TCHAR szErrMsg[MAX_PATH] = { 0 };_stprintf_s(szErrMsg, L"Failed to load xml file %s", strSkinFile.c_str());MessageBox(NULL, szErrMsg, _T("Duilib"), MB_OK | MB_ICONERROR);return -1;}
![83bc6cc8bd379c2649f650c47bc4c3d0.gif](https://i-blog.csdnimg.cn/blog_migrate/c414fa332f58658ef9bbe7da5db29f7a.gif)
其中,pRoot为XML样式中的根Box
duilib使用WindowBuilder类对XML进行解析
class UILIB_API WindowBuilder{public: WindowBuilder();Box* Create(STRINGorID xml, CreateControlCallback pCallback = CreateControlCallback(),Window* pManager = nullptr, Box* pParent = nullptr, Box* pUserDefinedBox = nullptr);Box* Create(CreateControlCallback pCallback = CreateControlCallback(), Window* pManager = nullptr,Box* pParent = nullptr, Box* pUserDefinedBox = nullptr); CMarkup* GetMarkup(); void GetLastErrorMessage(LPTSTR pstrMessage, SIZE_T cchMax) const; void GetLastErrorLocation(LPTSTR pstrSource, SIZE_T cchMax) const;private: Control* _Parse(CMarkupNode* parent, Control* pParent = NULL, Window* pManager = NULL);Control* CreateControlByClass(const std::wstring& strControlClass);void AttachXmlEvent(bool bBubbled, CMarkupNode& node, Control* pParent);private: CMarkup m_xml;CreateControlCallback m_createControlCallback;};
![83bc6cc8bd379c2649f650c47bc4c3d0.gif](https://i-blog.csdnimg.cn/blog_migrate/c414fa332f58658ef9bbe7da5db29f7a.gif)
4) 阴影BOX
pRoot = m_shadow.AttachShadow(pRoot);
Box*Shadow::AttachShadow(Box* pRoot){if (!m_bShadowAttached)return pRoot;m_pRoot = new ShadowBox();m_pRoot->GetLayout()->SetPadding(m_rcCurShadowCorner, false);int rootWidth = pRoot->GetFixedWidth();if (rootWidth > 0) {rootWidth += m_rcCurShadowCorner.left + m_rcCurShadowCorner.right;}m_pRoot->SetFixedWidth(rootWidth, true, false);int rootHeight = pRoot->GetFixedHeight();if (rootHeight > 0) {rootHeight += m_rcCurShadowCorner.top + m_rcCurShadowCorner.bottom;}m_pRoot->SetFixedHeight(rootHeight, false);if (m_bUseDefaultImage){CSize size(3, 3);pRoot->SetBorderRound(size);}m_pRoot->Add(pRoot);m_pRoot->SetBkImage(m_strImage);return m_pRoot;}
![83bc6cc8bd379c2649f650c47bc4c3d0.gif](https://i-blog.csdnimg.cn/blog_migrate/c414fa332f58658ef9bbe7da5db29f7a.gif)
如果不添加阴影时,直接返回
if (!m_bShadowAttached) return pRoot;
否则,生成一个BOX m_pRoot = new ShadowBox();作为根BOX
m_pRoot->Add(pRoot);
将从XML样式中获得的原根BOX作为阴影BOX的子容器。
也就是说,有阴影属性时,duilib内部暗自添了个顶层根BOX
5) 窗口初始化
pRoot = m_shadow.AttachShadow(pRoot); AttachDialog(pRoot); InitWindow();
virtual void InitWindow(){}
这是虚函数,直接跳转到派生类的初始化函数中
![548293e172cd2870986477ef7699f000.png](https://i-blog.csdnimg.cn/blog_migrate/58c0b3375a2b023c25a9992710c9363b.jpeg)
![83bc6cc8bd379c2649f650c47bc4c3d0.gif](https://i-blog.csdnimg.cn/blog_migrate/c414fa332f58658ef9bbe7da5db29f7a.gif)
最后是最大最小还原按钮的默认处理方式