482 lines
14 KiB
C++
482 lines
14 KiB
C++
#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<Button*>(pControl) || dynamic_cast<ButtonBox*>(pControl) || dynamic_cast<RichEdit*>(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<Button*>(pControl);
|
||
ASSERT(pCloseBtn);
|
||
pCloseBtn->AttachClick(nbase::Bind(&WindowImplBase::OnButtonClick, this, std::placeholders::_1));
|
||
}
|
||
|
||
pControl = (Control*)FindControl(L"minbtn");
|
||
if (pControl) {
|
||
Button* pMinBtn = dynamic_cast<Button*>(pControl);
|
||
ASSERT(pMinBtn);
|
||
pMinBtn->AttachClick(nbase::Bind(&WindowImplBase::OnButtonClick, this, std::placeholders::_1));
|
||
}
|
||
|
||
pControl = (Control*)FindControl(L"maxbtn");
|
||
if (pControl) {
|
||
Button* pMaxBtn = dynamic_cast<Button*>(pControl);
|
||
ASSERT(pMaxBtn);
|
||
pMaxBtn->AttachClick(nbase::Bind(&WindowImplBase::OnButtonClick, this, std::placeholders::_1));
|
||
}
|
||
|
||
pControl = (Control*)FindControl(L"restorebtn");
|
||
if (pControl) {
|
||
Button* pRestoreBtn = dynamic_cast<Button*>(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);
|
||
}
|
||
}
|
||
} |