1. 程式人生 > 其它 >duilib設定透明視窗_duilib如何處理WM_CREATE 視窗建立訊息

duilib設定透明視窗_duilib如何處理WM_CREATE 視窗建立訊息

技術標籤:duilib設定透明視窗

7d1e51c9917a68544bc35743706e21ae.png 94102e95468cf7926547b13e3ca992ab.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;}
94102e95468cf7926547b13e3ca992ab.gif

在OnCreate中,duilib做了這樣幾件工作:

1)設定視窗樣式,取消視窗預設標題欄

::SetWindowLong(this->GetHWND(), GWL_STYLE, GetStyle());    LONG WindowImplBase::GetStyle(){LONG styleValue = ::GetWindowLong(GetHWND(), GWL_STYLE);styleValue &= ~WS_CAPTION;return styleValue;}
94102e95468cf7926547b13e3ca992ab.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);}
94102e95468cf7926547b13e3ca992ab.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;}
94102e95468cf7926547b13e3ca992ab.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;};
94102e95468cf7926547b13e3ca992ab.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;}
94102e95468cf7926547b13e3ca992ab.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(){}

這是虛擬函式,直接跳轉到派生類的初始化函式中

b6c0fd2e21310c77c10b5baf005464b1.png 94102e95468cf7926547b13e3ca992ab.gif

最後是最大最小還原按鈕的預設處理方式