📄 resizablelayout.cpp
字号:
ATOM atomWndClass = (ATOM)::GetClassLong(hWnd, GCW_ATOM);
if (atomWndClass == (ATOM)0x8002)
{
// send a message to the dialog box
hBrush = (HBRUSH)::SendMessage(hWnd, WM_CTLCOLORDLG,
(WPARAM)hDC, (LPARAM)hWnd);
}
else
{
// take the background brush from the window's class
hBrush = (HBRUSH)::GetClassLong(hWnd, GCL_HBRBACKGROUND);
}
// fill the clipped background
CRgn rgn;
GetClippingRegion(&rgn);
::FillRgn(hDC, rgn, hBrush);
}
void CResizableLayout::EraseBackground(CDC* pDC)
{
// HWND hWnd = GetResizableWnd()->GetSafeHwnd();
//
// // retrieve the background brush
// HBRUSH hBrush = NULL;
//
// // is this a dialog box?
// // (using class atom is quickier than using the class name)
// ATOM atomWndClass = (ATOM)::GetClassLong(hWnd, GCW_ATOM);
// if (atomWndClass == (ATOM)0x8002)
// {
// // send a message to the dialog box
// hBrush = (HBRUSH)::SendMessage(hWnd, WM_CTLCOLORDLG,
// (WPARAM)pDC->GetSafeHdc(), (LPARAM)hWnd);
// }
// else
// {
// // take the background brush from the window's class
// hBrush = (HBRUSH)::GetClassLong(hWnd, GCL_HBRBACKGROUND);
// }
//
// // fill the clipped background
// CRgn rgn;
// GetClippingRegion(&rgn);
//
// ::FillRgn(pDC->GetSafeHdc(), rgn, hBrush);
EraseBackground( pDC->GetSafeHdc() );
}
// support legacy code (will disappear in future versions)
void CResizableLayout::ClipChildren(CDC* pDC)
{
CRgn rgn;
GetClippingRegion(&rgn);
// the clipping region is in device units
rgn.OffsetRgn(-pDC->GetWindowOrg());
pDC->SelectClipRgn(&rgn);
}
void CResizableLayout::GetTotalClientRect(LPRECT lpRect)
{
GetResizableWnd()->GetClientRect(lpRect);
}
BOOL CResizableLayout::NeedsRefresh(const CResizableLayout::LayoutInfo& layout,
const CRect& rectOld, const CRect& rectNew)
{
if (layout.bMsgSupport)
{
REFRESHPROPERTY refresh;
refresh.rcOld = rectOld;
refresh.rcNew = rectNew;
if (Send_NeedsRefresh(layout.hWnd, &refresh))
return refresh.bNeedsRefresh;
}
int nDiffWidth = (rectNew.Width() - rectOld.Width());
int nDiffHeight = (rectNew.Height() - rectOld.Height());
// is the same size?
if (nDiffWidth == 0 && nDiffHeight == 0)
return FALSE;
// optimistic, no need to refresh
BOOL bRefresh = FALSE;
// window classes that need refresh when resized
if (layout.sWndClass == WC_STATIC)
{
DWORD style = ::GetWindowLong(layout.hWnd, GWL_STYLE);
switch (style & SS_TYPEMASK)
{
case SS_LEFT:
case SS_CENTER:
case SS_RIGHT:
// word-wrapped text
bRefresh = bRefresh || (nDiffWidth != 0);
// vertically centered text
if (style & SS_CENTERIMAGE)
bRefresh = bRefresh || (nDiffHeight != 0);
break;
case SS_LEFTNOWORDWRAP:
// text with ellipsis
if (style & SS_ELLIPSISMASK)
bRefresh = bRefresh || (nDiffWidth != 0);
// vertically centered text
if (style & SS_CENTERIMAGE)
bRefresh = bRefresh || (nDiffHeight != 0);
break;
case SS_ENHMETAFILE:
case SS_BITMAP:
case SS_ICON:
// images
case SS_BLACKFRAME:
case SS_GRAYFRAME:
case SS_WHITEFRAME:
case SS_ETCHEDFRAME:
// and frames
bRefresh = TRUE;
break;
}
}
// window classes that don't redraw client area correctly
// when the hor scroll pos changes due to a resizing
BOOL bHScroll = FALSE;
if (layout.sWndClass == WC_LISTBOX)
bHScroll = TRUE;
// fix for horizontally scrollable windows
if (bHScroll && (nDiffWidth > 0))
{
// get max scroll position
SCROLLINFO info;
info.cbSize = sizeof(SCROLLINFO);
info.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
if (::GetScrollInfo(layout.hWnd, SB_HORZ, &info))
{
// subtract the page size
info.nMax -= __max(info.nPage-1,0);
}
// resizing will cause the text to scroll on the right
// because the scrollbar is going beyond the right limit
if ((info.nMax > 0) && (info.nPos + nDiffWidth > info.nMax))
{
// needs repainting, due to horiz scrolling
bRefresh = TRUE;
}
}
return bRefresh;
}
BOOL CResizableLayout::LikesClipping(const CResizableLayout::LayoutInfo& layout)
{
if (layout.bMsgSupport)
{
CLIPPINGPROPERTY clipping;
if (Send_LikesClipping(layout.hWnd, &clipping))
return clipping.bLikesClipping;
}
DWORD style = ::GetWindowLong(layout.hWnd, GWL_STYLE);
// skip windows that wants background repainted
if (layout.sWndClass == TOOLBARCLASSNAME && (style & TBSTYLE_TRANSPARENT))
return FALSE;
else if (layout.sWndClass == WC_BUTTON)
{
CRect rect;
switch (style & _BS_TYPEMASK)
{
case BS_GROUPBOX:
return FALSE;
case BS_OWNERDRAW:
// ownerdraw buttons must return correct hittest code
// to notify their transparency to the system and this library
::GetWindowRect(layout.hWnd, &rect);
if ( HTTRANSPARENT == ::SendMessage(layout.hWnd,
WM_NCHITTEST, 0, MAKELPARAM(rect.left, rect.top)) )
return FALSE;
break;
}
return TRUE;
}
else if (layout.sWndClass == WC_STATIC)
{
switch (style & SS_TYPEMASK)
{
case SS_LEFT:
case SS_CENTER:
case SS_RIGHT:
case SS_SIMPLE:
case SS_LEFTNOWORDWRAP:
// text
case SS_BLACKRECT:
case SS_GRAYRECT:
case SS_WHITERECT:
// filled rects
case SS_ETCHEDHORZ:
case SS_ETCHEDVERT:
// etched lines
case SS_BITMAP:
// bitmaps
return TRUE;
break;
case SS_ICON:
case SS_ENHMETAFILE:
if (style & SS_CENTERIMAGE)
return FALSE;
return TRUE;
break;
default:
return FALSE;
}
}
// assume the others like clipping
return TRUE;
}
void CResizableLayout::CalcNewChildPosition(const CResizableLayout::LayoutInfo& layout,
const CRect &rectParent, CRect &rectChild, UINT& uFlags)
{
CWnd* pParent = GetResizableWnd();
::GetWindowRect(layout.hWnd, &rectChild);
::MapWindowPoints(NULL, pParent->m_hWnd, (LPPOINT)&rectChild, 2);
CRect rectNew;
// calculate new top-left corner
rectNew.left = layout.sizeMarginTL.cx + rectParent.Width() * layout.sizeTypeTL.cx / 100;
rectNew.top = layout.sizeMarginTL.cy + rectParent.Height() * layout.sizeTypeTL.cy / 100;
// calculate new bottom-right corner
rectNew.right = layout.sizeMarginBR.cx + rectParent.Width() * layout.sizeTypeBR.cx / 100;
rectNew.bottom = layout.sizeMarginBR.cy + rectParent.Height() * layout.sizeTypeBR.cy / 100;
// adjust position, if client area has been scrolled
rectNew.OffsetRect(rectParent.TopLeft());
// get the refresh property
BOOL bRefresh = layout.properties.bAskRefresh ?
NeedsRefresh(layout, rectChild, rectNew) : layout.properties.bCachedNeedsRefresh;
// set flags
uFlags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREPOSITION;
if (bRefresh)
uFlags |= SWP_NOCOPYBITS;
if (rectNew.TopLeft() == rectChild.TopLeft())
uFlags |= SWP_NOMOVE;
if (rectNew.Size() == rectChild.Size())
uFlags |= SWP_NOSIZE;
// update rect
rectChild = rectNew;
}
void CResizableLayout::InitResizeProperties(CResizableLayout::LayoutInfo &layout)
{
// check if custom window supports this library
// (properties must be correctly set by the window)
layout.bMsgSupport = Send_QueryProperties(layout.hWnd, &layout.properties);
// default properties
if (!layout.bMsgSupport)
{
// clipping property is assumed as static
layout.properties.bAskClipping = FALSE;
layout.properties.bCachedLikesClipping = LikesClipping(layout);
// refresh property is assumed as dynamic
layout.properties.bAskRefresh = TRUE;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -