#include "stdafx.h" namespace ui { WindowImplBase::WindowImplBase() { } WindowImplBase::~WindowImplBase() { } void WindowImplBase::OnFinalMessage(HWND hWnd) { __super::OnFinalMessage(hWnd); ReapObjects(GetRoot()); delete this; } LONG WindowImplBase::GetStyle() { LONG styleValue = ::GetWindowLong(GetHWND(), GWL_STYLE); styleValue &= ~WS_CAPTION; return styleValue; } UINT WindowImplBase::GetClassStyle() const { return CS_DBLCLKS; } std::wstring WindowImplBase::GetResourceID() const { return _T(""); } Control* WindowImplBase::CreateControl(const std::wstring& pstrClass) { return NULL; } LRESULT WindowImplBase::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { return FALSE; } LRESULT WindowImplBase::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; return 0; } LRESULT WindowImplBase::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; return 0; } LRESULT WindowImplBase::OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { if (::IsIconic(GetHWND())) bHandled = FALSE; return (wParam == 0) ? TRUE : FALSE; } LRESULT WindowImplBase::OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { return 0; } LRESULT WindowImplBase::OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; if (IsZoomed(m_hWnd)) { LPWINDOWPOS lpPos = (LPWINDOWPOS)lParam; if (lpPos->flags & SWP_FRAMECHANGED) // 第一次最大化,而不是最大化之后所触发的WINDOWPOSCHANGE { POINT pt = { 0, 0 }; HMONITOR hMontorPrimary = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); HMONITOR hMonitorTo = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONEAREST); if (hMonitorTo != hMontorPrimary) { // 解决无边框窗口在双屏下面(副屏分辨率大于主屏)时,最大化不正确的问题 MONITORINFO miTo = { sizeof(miTo), 0 }; GetMonitorInfo(hMonitorTo, &miTo); lpPos->x = miTo.rcWork.left; lpPos->y = miTo.rcWork.top; lpPos->cx = miTo.rcWork.right - miTo.rcWork.left; lpPos->cy = miTo.rcWork.bottom - miTo.rcWork.top; } } } return 0; } LRESULT WindowImplBase::OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { return 0; } LRESULT WindowImplBase::OnNcLButtonDbClick(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { /*if (!::IsZoomed(GetHWND())) { SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0); } else { SendMessage(WM_SYSCOMMAND, SC_RESTORE, 0); }*/ return 0; } LRESULT WindowImplBase::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); ::ScreenToClient(GetHWND(), &pt); UiRect rcClient; ::GetClientRect(GetHWND(), &rcClient); rcClient.Deflate(m_shadow.GetShadowCorner()); if (!::IsZoomed(GetHWND())) { UiRect rcSizeBox = GetSizeBox(); if (pt.y < rcClient.top + rcSizeBox.top) { if (pt.y >= rcClient.top) { if (pt.x < (rcClient.left + rcSizeBox.left) && pt.x >= rcClient.left) return HTTOPLEFT; else if (pt.x > (rcClient.right - rcSizeBox.right) && pt.x <= rcClient.right) return HTTOPRIGHT; else return HTTOP; } else return HTCLIENT; } else if (pt.y > rcClient.bottom - rcSizeBox.bottom) { if (pt.y <= rcClient.bottom) { if (pt.x < (rcClient.left + rcSizeBox.left) && pt.x >= rcClient.left) return HTBOTTOMLEFT; else if (pt.x > (rcClient.right - rcSizeBox.right) && pt.x <= rcClient.right) return HTBOTTOMRIGHT; else return HTBOTTOM; } else return HTCLIENT; } if (pt.x < rcClient.left + rcSizeBox.left) { if (pt.x >= rcClient.left) return HTLEFT; else return HTCLIENT; } if (pt.x > rcClient.right - rcSizeBox.right) { if (pt.x <= rcClient.right) return HTRIGHT; else return HTCLIENT; } } UiRect rcCaption = GetCaptionRect(); if (pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \ && pt.y >= rcClient.top + rcCaption.top && pt.y < rcClient.top + rcCaption.bottom) { Control* pControl = FindControl(pt); if (pControl) { if (dynamic_cast(pControl) || dynamic_cast(pControl) || dynamic_cast(pControl)) return HTCLIENT; else return HTCAPTION; } } return HTCLIENT; } LRESULT WindowImplBase::OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam; MONITORINFO oMonitor = {}; oMonitor.cbSize = sizeof(oMonitor); ::GetMonitorInfo(::MonitorFromWindow(GetHWND(), MONITOR_DEFAULTTONEAREST), &oMonitor); UiRect rcWork = oMonitor.rcWork; UiRect rcMonitor = oMonitor.rcMonitor; rcWork.Offset(-oMonitor.rcMonitor.left, -oMonitor.rcMonitor.top); UiRect rcMaximize = GetMaximizeInfo(); if (rcMaximize.GetWidth() > 0 && rcMaximize.GetHeight() > 0) { lpMMI->ptMaxPosition.x = rcWork.left + rcMaximize.left; lpMMI->ptMaxPosition.y = rcWork.top + rcMaximize.top; lpMMI->ptMaxSize.x = rcMaximize.GetWidth(); lpMMI->ptMaxSize.y = rcMaximize.GetHeight(); } else { // 计算最大化时,正确的原点坐标 lpMMI->ptMaxPosition.x = rcWork.left; lpMMI->ptMaxPosition.y = rcWork.top; lpMMI->ptMaxSize.x = rcWork.GetWidth(); lpMMI->ptMaxSize.y = rcWork.GetHeight(); } if (GetMaxInfo().cx != 0) { lpMMI->ptMaxTrackSize.x = GetMaxInfo(true).cx; } if (GetMaxInfo().cy != 0) { lpMMI->ptMaxTrackSize.y = GetMaxInfo(true).cy; } if (GetMinInfo().cx != 0) { lpMMI->ptMinTrackSize.x = GetMinInfo(true).cx; } if (GetMinInfo().cy != 0) { lpMMI->ptMinTrackSize.y = GetMinInfo(true).cy; } bHandled = FALSE; return 0; } LRESULT WindowImplBase::OnMouseWheel(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; return 0; } LRESULT WindowImplBase::OnMouseHover(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; return 0; } LRESULT WindowImplBase::OnDpiChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; // 重置全局 DPI 设定 DpiManager::GetInstance()->SetScale(LOWORD(wParam)); // 重置阴影范围 m_shadow.ResetShadowBox(); // TODO 对窗口大小进行进行改变,让所有控件重新根据 DPI 计算大小 return 0; } LRESULT WindowImplBase::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { CSize szRoundCorner = GetRoundCorner(); if (!::IsIconic(GetHWND()) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0)) { UiRect rcWnd; ::GetWindowRect(GetHWND(), &rcWnd); rcWnd.Offset(-rcWnd.left, -rcWnd.top); rcWnd.right++; rcWnd.bottom++; HRGN hRgn = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, szRoundCorner.cx, szRoundCorner.cy); ::SetWindowRgn(GetHWND(), hRgn, TRUE); ::DeleteObject(hRgn); } bHandled = FALSE; return 0; } LRESULT WindowImplBase::OnChar(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; return 0; } LRESULT WindowImplBase::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { if (wParam == SC_CLOSE) { bHandled = TRUE; SendMessage(WM_CLOSE); return 0; } BOOL bZoomed = ::IsZoomed(GetHWND()); LRESULT lRes = Window::HandleMessage(uMsg, wParam, lParam); if (::IsZoomed(GetHWND()) != bZoomed) { } return lRes; } LRESULT WindowImplBase::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { ::SetWindowLong(this->GetHWND(), GWL_STYLE, GetStyle()); Init(m_hWnd); 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; } LRESULT WindowImplBase::OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; return 0; } LRESULT WindowImplBase::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; return 0; } LRESULT WindowImplBase::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; return 0; } LRESULT WindowImplBase::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; return 0; } LRESULT WindowImplBase::OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; return 0; } LRESULT WindowImplBase::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; return 0; } LRESULT WindowImplBase::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { LRESULT lRes = 0; BOOL bHandled = TRUE; switch (uMsg) { case WM_CREATE: lRes = OnCreate(uMsg, wParam, lParam, bHandled); break; case WM_CLOSE: lRes = OnClose(uMsg, wParam, lParam, bHandled); break; case WM_DESTROY: lRes = OnDestroy(uMsg, wParam, lParam, bHandled); break; case WM_NCACTIVATE: lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); break; case WM_NCCALCSIZE: lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled); break; case WM_WINDOWPOSCHANGING: lRes = OnWindowPosChanging(uMsg, wParam, lParam, bHandled); break; case WM_NCPAINT: lRes = OnNcPaint(uMsg, wParam, lParam, bHandled); break; case WM_NCLBUTTONDBLCLK:lRes = OnNcLButtonDbClick(uMsg, wParam, lParam, bHandled); break; case WM_NCHITTEST: lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); break; case WM_GETMINMAXINFO: lRes = OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled); break; case WM_MOUSEWHEEL: lRes = OnMouseWheel(uMsg, wParam, lParam, bHandled); break; case WM_SIZE: lRes = OnSize(uMsg, wParam, lParam, bHandled); break; case WM_CHAR: lRes = OnChar(uMsg, wParam, lParam, bHandled); break; case WM_SYSCOMMAND: lRes = OnSysCommand(uMsg, wParam, lParam, bHandled); break; case WM_KEYDOWN: lRes = OnKeyDown(uMsg, wParam, lParam, bHandled); break; case WM_KILLFOCUS: lRes = OnKillFocus(uMsg, wParam, lParam, bHandled); break; case WM_SETFOCUS: lRes = OnSetFocus(uMsg, wParam, lParam, bHandled); break; case WM_LBUTTONUP: lRes = OnLButtonUp(uMsg, wParam, lParam, bHandled); break; case WM_LBUTTONDOWN: lRes = OnLButtonDown(uMsg, wParam, lParam, bHandled); break; case WM_MOUSEMOVE: lRes = OnMouseMove(uMsg, wParam, lParam, bHandled); break; case WM_MOUSEHOVER: lRes = OnMouseHover(uMsg, wParam, lParam, bHandled); break; case WM_DPICHANGED: lRes = OnDpiChanged(uMsg, wParam, lParam, bHandled); break; default: bHandled = FALSE; break; } if (bHandled) return lRes; return Window::HandleMessage(uMsg, wParam, lParam); } bool WindowImplBase::OnButtonClick(EventArgs* msg) { std::wstring sCtrlName = msg->pSender->GetName(); if (sCtrlName == _T("closebtn")) { Close(); } else if (sCtrlName == _T("minbtn")) { SendMessage(WM_SYSCOMMAND, SC_MINIMIZE, 0); } else if (sCtrlName == _T("maxbtn")) { Control* pMaxButton = (Control*)FindControl(L"maxbtn"); Control* pRestoreButton = (Control*)FindControl(L"restorebtn"); if (pMaxButton && pRestoreButton) { pMaxButton->SetVisible(false); pRestoreButton->SetVisible(true); } SendMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0); } else if (sCtrlName == _T("restorebtn")) { Control* pMaxButton = (Control*)FindControl(L"maxbtn"); Control* pRestoreButton = (Control*)FindControl(L"restorebtn"); if (pMaxButton && pRestoreButton) { pMaxButton->SetVisible(true); pRestoreButton->SetVisible(false); } SendMessage(WM_SYSCOMMAND, SC_RESTORE, 0); } return true; } void WindowImplBase::ActiveWindow() { if (::IsWindow(m_hWnd)) { if (::IsIconic(m_hWnd)) { ::ShowWindow(m_hWnd, SW_RESTORE); } else { if (!::IsWindowVisible(m_hWnd)) ::ShowWindow(m_hWnd, SW_SHOW); ::SetForegroundWindow(m_hWnd); } } } void WindowImplBase::SetTaskbarTitle(const std::wstring& title) { ::SetWindowTextW(m_hWnd, title.c_str()); } void WindowImplBase::ToTopMost(bool forever) { ASSERT(::IsWindow(m_hWnd)); ::SetWindowPos(m_hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); if (!forever) { ::SetWindowPos(m_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } } }