📄 atlscrl.h
字号:
// Helper functions
void PrepareDC(CDCHandle dc)
{
ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0);
dc.SetMapMode(MM_ANISOTROPIC);
dc.SetWindowExt(m_sizeLogAll);
dc.SetViewportExt(m_sizeAll);
dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y);
}
void ViewDPtoLP(LPPOINT lpPoints, int nCount = 1)
{
ATLASSERT(lpPoints);
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
CWindowDC dc(pT->m_hWnd);
pT->PrepareDC(dc.m_hDC);
dc.DPtoLP(lpPoints, nCount);
}
void ViewLPtoDP(LPPOINT lpPoints, int nCount = 1)
{
ATLASSERT(lpPoints);
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
CWindowDC dc(pT->m_hWnd);
pT->PrepareDC(dc.m_hDC);
dc.LPtoDP(lpPoints, nCount);
}
void ClientToDevice(POINT &pt)
{
pt.x += m_ptOffset.x;
pt.y += m_ptOffset.y;
}
void DeviceToClient(POINT &pt)
{
pt.x -= m_ptOffset.x;
pt.y -= m_ptOffset.y;
}
void CenterOnPoint(POINT pt)
{
T* pT = static_cast<T*>(this);
RECT rect;
pT->GetClientRect(&rect);
int xOfs = pt.x - (rect.right / 2) + m_ptOffset.x;
if(xOfs < 0)
{
xOfs = 0;
}
else
{
int xMax = max((int)(m_sizeAll.cx - rect.right), 0);
if(xOfs > xMax)
xOfs = xMax;
}
int yOfs = pt.y - (rect.bottom / 2) + m_ptOffset.y;
if(yOfs < 0)
{
yOfs = 0;
}
else
{
int yMax = max((int)(m_sizeAll.cy - rect.bottom), 0);
if(yOfs > yMax)
yOfs = yMax;
}
CScrollImpl< T >::SetScrollOffset(xOfs, yOfs);
}
void CenterOnLogicalPoint(POINT ptLog)
{
T* pT = static_cast<T*>(this);
pT->ViewLPtoDP(&ptLog);
pT->DeviceToClient(ptLog);
pT->CenterOnPoint(ptLog);
}
BOOL PtInDevRect(POINT pt)
{
RECT rc = { 0, 0, m_sizeAll.cx, m_sizeAll.cy };
::OffsetRect(&rc, -m_ptOffset.x, -m_ptOffset.y);
return ::PtInRect(&rc, pt);
}
void NormalizeRect(RECT& rc)
{
if(rc.left > rc.right)
{
int r = rc.right;
rc.right = rc.left;
rc.left = r;
}
if(rc.top > rc.bottom)
{
int b = rc.bottom;
rc.bottom = rc.top;
rc.top = b;
}
}
void DrawTrackRect()
{
T* pT = static_cast<T*>(this);
const SIZE sizeLines = { 2, 2 };
RECT rc = m_rcTrack;
pT->NormalizeRect(rc);
if(!::IsRectEmpty(&rc))
{
::MapWindowPoints(pT->m_hWnd, NULL, (LPPOINT)&rc, 2);
CWindowDC dc(NULL);
dc.DrawDragRect(&rc, sizeLines, NULL, sizeLines);
}
}
void NotifyParentZoomChanged()
{
T* pT = static_cast<T*>(this);
int nId = pT->GetDlgCtrlID();
NMHDR nmhdr = { pT->m_hWnd, nId, ZSN_ZOOMCHANGED };
::SendMessage(pT->GetParent(), WM_NOTIFY, (WPARAM)nId, (LPARAM)&nmhdr);
}
BEGIN_MSG_MAP(CZoomScrollImpl)
MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
MESSAGE_HANDLER(WM_CAPTURECHANGED, OnCaptureChanged)
ALT_MSG_MAP(1)
COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
END_MSG_MAP()
LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
ATLASSERT(m_sizeLogAll.cx >= 0 && m_sizeLogAll.cy >= 0);
ATLASSERT(m_sizeAll.cx >= 0 && m_sizeAll.cy >= 0);
if(wParam != NULL)
{
CDCHandle dc = (HDC)wParam;
int nMapModeSav = dc.GetMapMode();
dc.SetMapMode(MM_ANISOTROPIC);
SIZE szWindowExt = { 0, 0 };
dc.SetWindowExt(m_sizeLogAll, &szWindowExt);
SIZE szViewportExt = { 0, 0 };
dc.SetViewportExt(m_sizeAll, &szViewportExt);
POINT ptViewportOrg = { 0, 0 };
dc.SetViewportOrg(-m_ptOffset.x, -m_ptOffset.y, &ptViewportOrg);
pT->DoPaint(dc);
dc.SetMapMode(nMapModeSav);
dc.SetWindowExt(szWindowExt);
dc.SetViewportExt(szViewportExt);
dc.SetViewportOrg(ptViewportOrg);
}
else
{
CPaintDC dc(pT->m_hWnd);
pT->PrepareDC(dc.m_hDC);
pT->DoPaint(dc.m_hDC);
}
return 0;
}
LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
if(m_nZoomMode == ZOOMMODE_IN && !m_bTracking)
{
T* pT = static_cast<T*>(this);
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if(pT->PtInDevRect(pt))
{
pT->SetCapture();
m_bTracking = true;
::SetRect(&m_rcTrack, pt.x, pt.y, pt.x, pt.y);
}
}
bHandled = FALSE;
return 0;
}
LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
if(m_bTracking)
{
T* pT = static_cast<T*>(this);
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if(pT->PtInDevRect(pt))
{
pT->DrawTrackRect();
m_rcTrack.right = pt.x;
m_rcTrack.bottom = pt.y;
pT->DrawTrackRect();
}
}
bHandled = FALSE;
return 0;
}
LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
::ReleaseCapture();
if(m_nZoomMode == ZOOMMODE_OUT)
{
T* pT = static_cast<T*>(this);
pT->Zoom(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), m_fZoomScale - m_fZoomDelta);
pT->NotifyParentZoomChanged();
}
bHandled = FALSE;
return 0;
}
LRESULT OnCaptureChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
if(m_bTracking)
{
m_bTracking = false;
T* pT = static_cast<T*>(this);
pT->DrawTrackRect();
pT->Zoom(m_rcTrack);
pT->NotifyParentZoomChanged();
::SetRectEmpty(&m_rcTrack);
}
bHandled = FALSE;
return 0;
}
LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
if(LOWORD(lParam) == HTCLIENT && m_nZoomMode != ZOOMMODE_OFF)
{
T* pT = static_cast<T*>(this);
if((HWND)wParam == pT->m_hWnd)
{
DWORD dwPos = ::GetMessagePos();
POINT pt = { GET_X_LPARAM(dwPos), GET_Y_LPARAM(dwPos) };
pT->ScreenToClient(&pt);
if(pT->PtInDevRect(pt))
{
::SetCursor(::LoadCursor(NULL, IDC_CROSS));
return 1;
}
}
}
bHandled = FALSE;
return 0;
}
};
///////////////////////////////////////////////////////////////////////////////
// CZoomScrollWindowImpl - Implements scrolling window with zooming
template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
class ATL_NO_VTABLE CZoomScrollWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CZoomScrollImpl< T >
{
public:
BEGIN_MSG_MAP(CZoomScrollWindowImpl)
MESSAGE_HANDLER(WM_SETCURSOR, CZoomScrollImpl< T >::OnSetCursor)
MESSAGE_HANDLER(WM_VSCROLL, CScrollImpl< T >::OnVScroll)
MESSAGE_HANDLER(WM_HSCROLL, CScrollImpl< T >::OnHScroll)
MESSAGE_HANDLER(WM_MOUSEWHEEL, CScrollImpl< T >::OnMouseWheel)
#if !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
MESSAGE_HANDLER(m_uMsgMouseWheel, CScrollImpl< T >::OnMouseWheel)
#endif // !((_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400))
MESSAGE_HANDLER(WM_MOUSEHWHEEL, CScrollImpl< T >::OnMouseHWheel)
MESSAGE_HANDLER(WM_SETTINGCHANGE, CScrollImpl< T >::OnSettingChange)
MESSAGE_HANDLER(WM_SIZE, CScrollImpl< T >::OnSize)
MESSAGE_HANDLER(WM_PAINT, CZoomScrollImpl< T >::OnPaint)
MESSAGE_HANDLER(WM_PRINTCLIENT, CZoomScrollImpl< T >::OnPaint)
MESSAGE_HANDLER(WM_LBUTTONDOWN, CZoomScrollImpl< T >::OnLButtonDown)
MESSAGE_HANDLER(WM_MOUSEMOVE, CZoomScrollImpl< T >::OnMouseMove)
MESSAGE_HANDLER(WM_LBUTTONUP, CZoomScrollImpl< T >::OnLButtonUp)
MESSAGE_HANDLER(WM_CAPTURECHANGED, CZoomScrollImpl< T >::OnCaptureChanged)
ALT_MSG_MAP(1)
COMMAND_ID_HANDLER(ID_SCROLL_UP, CScrollImpl< T >::OnScrollUp)
COMMAND_ID_HANDLER(ID_SCROLL_DOWN, CScrollImpl< T >::OnScrollDown)
COMMAND_ID_HANDLER(ID_SCROLL_PAGE_UP, CScrollImpl< T >::OnScrollPageUp)
COMMAND_ID_HANDLER(ID_SCROLL_PAGE_DOWN, CScrollImpl< T >::OnScrollPageDown)
COMMAND_ID_HANDLER(ID_SCROLL_TOP, CScrollImpl< T >::OnScrollTop)
COMMAND_ID_HANDLER(ID_SCROLL_BOTTOM, CScrollImpl< T >::OnScrollBottom)
COMMAND_ID_HANDLER(ID_SCROLL_LEFT, CScrollImpl< T >::OnScrollLeft)
COMMAND_ID_HANDLER(ID_SCROLL_RIGHT, CScrollImpl< T >::OnScrollRight)
COMMAND_ID_HANDLER(ID_SCROLL_PAGE_LEFT, CScrollImpl< T >::OnScrollPageLeft)
COMMAND_ID_HANDLER(ID_SCROLL_PAGE_RIGHT, CScrollImpl< T >::OnScrollPageRight)
COMMAND_ID_HANDLER(ID_SCROLL_ALL_LEFT, CScrollImpl< T >::OnScrollAllLeft)
COMMAND_ID_HANDLER(ID_SCROLL_ALL_RIGHT, CScrollImpl< T >::OnScrollAllRight)
END_MSG_MAP()
};
#endif // !_WIN32_WCE
///////////////////////////////////////////////////////////////////////////////
// CScrollContainer
template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
class ATL_NO_VTABLE CScrollContainerImpl : public CScrollWindowImpl< T, TBase, TWinTraits >
{
public:
DECLARE_WND_CLASS_EX(NULL, 0, -1)
typedef CScrollWindowImpl< T, TBase, TWinTraits > _baseClass;
// Data members
ATL::CWindow m_wndClient;
bool m_bAutoSizeClient;
bool m_bDrawEdgeIfEmpty;
// Constructor
CScrollContainerImpl() : m_bAutoSizeClient(true), m_bDrawEdgeIfEmpty(false)
{
// Set CScrollWindowImpl extended style
SetScrollExtendedStyle(SCRL_SCROLLCHILDREN);
}
// Attributes
HWND GetClient() const
{
return m_wndClient;
}
HWND SetClient(HWND hWndClient, bool bClientSizeAsMin = true)
{
ATLASSERT(::IsWindow(m_hWnd));
HWND hWndOldClient = m_wndClient;
m_wndClient = hWndClient;
SetRedraw(FALSE);
SetScrollSize(1, 1, FALSE);
if(m_wndClient.m_hWnd != NULL)
{
m_wndClient.SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
if(bClientSizeAsMin)
{
RECT rect = { 0 };
m_wndClient.GetWindowRect(&rect);
if((rect.right - rect.left) > 0 && (rect.bottom - rect.top) > 0)
SetScrollSize(rect.right - rect.left, rect.bottom - rect.top, FALSE);
}
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
}
SetRedraw(TRUE);
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ALLCHILDREN);
return hWndOldClient;
}
// Message map and handlers
BEGIN_MSG_MAP(CScrollContainerImpl)
MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
MESSAGE_HANDLER(WM_SIZE, OnSize)
CHAIN_MSG_MAP(_baseClass)
FORWARD_NOTIFICATIONS()
ALT_MSG_MAP(1)
CHAIN_MSG_MAP_ALT(_baseClass, 1)
END_MSG_MAP()
LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
if(m_wndClient.m_hWnd != NULL)
m_wndClient.SetFocus();
return 0;
}
LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
return 1; // no background needed
}
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
BOOL bTmp = TRUE;
LRESULT lRet = _baseClass::OnSize(uMsg, wParam, lParam, bTmp);
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
return lRet;
}
// Overrides for CScrollWindowImpl
void DoPaint(CDCHandle dc)
{
if(!m_bAutoSizeClient || m_wndClient.m_hWnd == NULL)
{
T* pT = static_cast<T*>(this);
RECT rect = { 0 };
pT->GetContainerRect(rect);
if(m_bDrawEdgeIfEmpty && m_wndClient.m_hWnd == NULL)
dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
dc.FillRect(&rect, COLOR_APPWORKSPACE);
}
}
void ScrollToView(POINT pt)
{
CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(pt);
}
void ScrollToView(RECT& rect)
{
CScrollWindowImpl< T, TBase, TWinTraits >::ScrollToView(rect);
}
void ScrollToView(HWND hWnd) // client window coordinates
{
T* pT = static_cast<T*>(this);
pT; // avoid level 4 warning
ATLASSERT(::IsWindow(pT->m_hWnd));
ATLASSERT(m_wndClient.IsWindow());
RECT rect = { 0 };
::GetWindowRect(hWnd, &rect);
::MapWindowPoints(NULL, m_wndClient.m_hWnd, (LPPOINT)&rect, 2);
ScrollToView(rect);
}
// Implementation - overrideable methods
void UpdateLayout()
{
ATLASSERT(::IsWindow(m_hWnd));
if(m_bAutoSizeClient && m_wndClient.m_hWnd != NULL)
{
T* pT = static_cast<T*>(this);
RECT rect = { 0 };
pT->GetContainerRect(rect);
m_wndClient.SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOMOVE);
}
else
{
Invalidate();
}
}
void GetContainerRect(RECT& rect)
{
GetClientRect(&rect);
if(rect.right < m_sizeAll.cx)
rect.right = m_sizeAll.cx;
if(rect.bottom < m_sizeAll.cy)
rect.bottom = m_sizeAll.cy;
}
};
class CScrollContainer : public CScrollContainerImpl<CScrollContainer>
{
public:
DECLARE_WND_CLASS_EX(_T("WTL_ScrollContainer"), 0, -1)
};
}; // namespace WTL
#endif // __ATLSCRL_H__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -