Files
foobar2000-sdk/libPPUI/CDialogResizeHelper.cpp
2021-12-14 00:28:25 -07:00

195 lines
6.1 KiB
C++

#include "stdafx.h"
#include "CDialogResizeHelper.h"
#include "win32_op.h"
static BOOL GetChildWindowRect2(HWND wnd, HWND wndChild, RECT* child) {
RECT temp;
if (wndChild == NULL) return FALSE;
if (!GetWindowRect(wndChild, &temp)) return FALSE;
if (!MapWindowPoints(NULL, wnd, (POINT*)&temp, 2)) return FALSE;
*child = temp;
return TRUE;
}
static BOOL GetChildWindowRect(HWND wnd, UINT id, RECT* child) {
return GetChildWindowRect2(wnd, GetDlgItem(wnd, id), child);
}
bool CDialogResizeHelper::EvalRect(UINT id, CRect & out) const {
for( auto iter = m_runtime.begin(); iter != m_runtime.end(); ++ iter ) {
if ( iter->initData.id == id ) {
out = _EvalRect(*iter, this->CurrentSize() );
return true;
}
}
return false;
}
CRect CDialogResizeHelper::_EvalRect(runtime_t const & rt, CSize wndSize) const {
CRect rc = rt.origRect;
int delta_x = wndSize.cx - rt.origWindowSize.cx,
delta_y = wndSize.cy - rt.origWindowSize.cy;
const Param & e = rt.initData;
rc.left += pfc::rint32(e.snapLeft * delta_x);
rc.right += pfc::rint32(e.snapRight * delta_x);
rc.top += pfc::rint32(e.snapTop * delta_y);
rc.bottom += pfc::rint32(e.snapBottom * delta_y);
return rc;
}
CWindow CDialogResizeHelper::ResolveWnd(runtime_t const & rt) const {
if ( rt.userHWND != NULL ) return rt.userHWND;
return m_thisWnd.GetDlgItem( rt.initData.id );
}
CSize CDialogResizeHelper::CurrentSize() const {
CRect rc;
WIN32_OP_D( m_thisWnd.GetClientRect(rc) );
return rc.Size();
}
void CDialogResizeHelper::OnSize(UINT, CSize newSize)
{
if (m_thisWnd != NULL) {
HDWP hWinPosInfo = BeginDeferWindowPos((int)(m_runtime.size() + (m_sizeGrip != NULL ? 1 : 0)));
for (auto iter = m_runtime.begin(); iter != m_runtime.end(); ++ iter) {
CRect rc = _EvalRect(*iter, newSize);
hWinPosInfo = DeferWindowPos(hWinPosInfo, ResolveWnd(*iter), 0, rc.left, rc.top, rc.Width(), rc.Height(), SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
}
if (m_sizeGrip != NULL)
{
RECT rc, rc_grip;
if (m_thisWnd.GetClientRect(&rc) && m_sizeGrip.GetWindowRect(&rc_grip)) {
DWORD flags = SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOCOPYBITS;
if (IsZoomed(m_thisWnd)) flags |= SWP_HIDEWINDOW;
else flags |= SWP_SHOWWINDOW;
hWinPosInfo = DeferWindowPos(hWinPosInfo, m_sizeGrip, NULL, rc.right - (rc_grip.right - rc_grip.left), rc.bottom - (rc_grip.bottom - rc_grip.top), 0, 0, flags);
}
}
EndDeferWindowPos(hWinPosInfo);
//RedrawWindow(m_thisWnd, NULL, NULL, RDW_UPDATENOW | RDW_ALLCHILDREN);
}
SetMsgHandled(FALSE);
}
void CDialogResizeHelper::OnGetMinMaxInfo(LPMINMAXINFO info) const {
CRect r;
const DWORD dwStyle = m_thisWnd.GetWindowLong(GWL_STYLE);
const DWORD dwExStyle = m_thisWnd.GetWindowLong(GWL_EXSTYLE);
if (max_x && max_y)
{
r.left = 0; r.right = max_x;
r.top = 0; r.bottom = max_y;
MapDialogRect(m_thisWnd, &r);
AdjustWindowRectEx(&r, dwStyle, FALSE, dwExStyle);
info->ptMaxTrackSize.x = r.right - r.left;
info->ptMaxTrackSize.y = r.bottom - r.top;
}
if (min_x && min_y)
{
r.left = 0; r.right = min_x;
r.top = 0; r.bottom = min_y;
MapDialogRect(m_thisWnd, &r);
AdjustWindowRectEx(&r, dwStyle, FALSE, dwExStyle);
info->ptMinTrackSize.x = r.right - r.left;
info->ptMinTrackSize.y = r.bottom - r.top;
}
}
void CDialogResizeHelper::OnInitDialog(CWindow thisWnd) {
m_thisWnd = thisWnd;
const auto origSize = CurrentSize();
for( auto initIter = m_initData.begin(); initIter != m_initData.end(); ++ initIter ) {
CRect rc;
if (GetChildWindowRect(m_thisWnd, initIter->id, &rc)) {
runtime_t rt;
rt.origRect = rc;
rt.initData = * initIter;
rt.origWindowSize = origSize;
m_runtime.push_back( std::move(rt) );
}
}
AddSizeGrip();
SetMsgHandled(FALSE);
}
void CDialogResizeHelper::OnDestroy() {
m_runtime.clear();
m_sizeGrip = NULL; m_thisWnd = NULL;
SetMsgHandled(FALSE);
}
void CDialogResizeHelper::AddSizeGrip()
{
if (m_thisWnd != NULL && m_sizeGrip == NULL)
{
if (m_thisWnd.GetWindowLong(GWL_STYLE) & WS_POPUP) {
m_sizeGrip = CreateWindowEx(0, WC_SCROLLBAR, _T(""), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SBS_SIZEGRIP | SBS_SIZEBOXBOTTOMRIGHTALIGN,
0, 0, CW_USEDEFAULT, CW_USEDEFAULT,
m_thisWnd, (HMENU)0, NULL, NULL);
if (m_sizeGrip != NULL)
{
RECT rc, rc_grip;
if (m_thisWnd.GetClientRect(&rc) && m_sizeGrip.GetWindowRect(&rc_grip)) {
m_sizeGrip.SetWindowPos(NULL, rc.right - (rc_grip.right - rc_grip.left), rc.bottom - (rc_grip.bottom - rc_grip.top), 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
}
}
}
}
void CDialogResizeHelper::InitTable(const Param* table, size_t tableSize) {
m_initData.assign( table, table+tableSize );
}
void CDialogResizeHelper::InitTable(const ParamOld * table, size_t tableSize) {
m_initData.resize(tableSize);
for (size_t walk = 0; walk < tableSize; ++walk) {
const ParamOld in = table[walk];
Param entry = {};
entry.id = table[walk].id;
if (in.flags & CDialogResizeHelperCompat::X_MOVE) entry.snapLeft = entry.snapRight = 1;
else if (in.flags & CDialogResizeHelperCompat::X_SIZE) entry.snapRight = 1;
if (in.flags & CDialogResizeHelperCompat::Y_MOVE) entry.snapTop = entry.snapBottom = 1;
else if (in.flags & CDialogResizeHelperCompat::Y_SIZE) entry.snapBottom = 1;
m_initData[walk] = entry;
}
}
void CDialogResizeHelper::InitMinMax(const CRect & range) {
min_x = range.left; min_y = range.top; max_x = range.right; max_y = range.bottom;
}
void CDialogResizeHelper::AddControl(Param const & initData, CWindow wnd) {
CRect rc;
if ( wnd == NULL ) {
PFC_ASSERT( initData.id != 0 );
WIN32_OP_D(GetChildWindowRect(m_thisWnd, initData.id, rc));
} else {
WIN32_OP_D(GetChildWindowRect2(m_thisWnd, wnd, rc));
}
runtime_t rt;
rt.initData = initData;
rt.userHWND = wnd;
rt.origRect = rc;
rt.origWindowSize = this->CurrentSize();
m_runtime.push_back( std::move(rt) );
}
bool CDialogResizeHelper::RemoveControl(CWindow wnd) {
return pfc::remove_if_t( m_runtime, [wnd] (runtime_t const & rt) {
return rt.userHWND == wnd;
} ) > 0;
}
bool CDialogResizeHelper::HaveControl(CWindow wnd) const {
for( auto i = m_runtime.begin(); i != m_runtime.end(); ++ i ) {
if ( i->userHWND == wnd ) return true;
}
return false;
}