📄 childviewanimate.h
字号:
#pragma once
template <class T>
class CChildViewAnimate
{
public:
enum ViewAnimation
{
None, // Don't animate the child transitions
ScrollLeft, // Scroll the views to the left
ScrollRight, // Scroll the views to the right
ScrollUp, // Scroll the views up
ScrollDown // Scroll the views down
};
protected:
CViewBase* m_pView; // Current child view
DWORD m_dwMaxTick; // Maximum number of ticks to wait for when scrolling
// ScrollWait:
//
// Waits a fixed number of milliseconds between two scrolls
//
void ScrollWait(DWORD dwTickIni, DWORD dwTickEnd)
{
DWORD dwTickDel = dwTickEnd - dwTickIni;
if(dwTickDel > m_dwMaxTick)
{
m_dwMaxTick = dwTickDel;
}
else
{
// Preserve original timing (yes, this burns the CPU)
while(GetTickCount() - dwTickIni < m_dwMaxTick)
;
}
}
// ScrollHorizontal
//
// Horizontally scrolls the view
//
void ScrollHorizontal(CDC& dcCli, CRect& rc, CWindow wndNewView, ViewAnimation nAnimation, int dx)
{
int xScroll = nAnimation == ScrollLeft ? -dx : dx,
x,
nWidth = rc.Width(),
nHeight = rc.Height();
CRect rcInvalid(rc);
DWORD dwTickIni,
dwTickEnd;
// Calculate the ivalid rect
if(nAnimation == ScrollLeft)
rcInvalid.left = rc.Width() - dx;
else
rcInvalid.right = dx;
for(x = dx; x <= rc.Width(); x += dx)
{
dwTickIni = GetTickCount();
dcCli.ScrollDC(xScroll, 0, &rc, &rc, NULL, NULL);
dwTickEnd = GetTickCount();
ScrollWait(dwTickIni, dwTickEnd);
if(nAnimation == ScrollLeft)
wndNewView.MoveWindow(nWidth - x, rc.top, nWidth, nHeight, FALSE);
else
wndNewView.MoveWindow(-nWidth + x, rc.top, nWidth, nHeight, FALSE);
wndNewView.InvalidateRect(&rcInvalid, TRUE);
wndNewView.UpdateWindow();
}
}
// ScrollVertical
//
// Vertically scrolls the view
//
void ScrollVertical(CDC& dcCli, CRect& rc, CWindow wndNewView, ViewAnimation nAnimation, int dy)
{
int yScroll = nAnimation == ScrollUp ? -dy : dy,
y,
nWidth = rc.Width(),
nHeight = rc.Height();
CRect rcInvalid(rc);
DWORD dwTickIni,
dwTickEnd;
// Calculate the ivalid rect
if(nAnimation == ScrollUp)
rcInvalid.top = nHeight - dy;
else
rcInvalid.bottom = rc.top + dy;
for(y = dy; y <= nHeight; y += dy)
{
dwTickIni = GetTickCount();
dcCli.ScrollDC(0, yScroll, &rc, &rc, NULL, NULL);
dwTickEnd = GetTickCount();
ScrollWait(dwTickIni, dwTickEnd);
if(nAnimation == ScrollUp)
wndNewView.MoveWindow(0, rc.bottom - y, nWidth, nHeight, FALSE);
else
wndNewView.MoveWindow(0, rc.top - nHeight + y, nWidth, nHeight, FALSE);
wndNewView.InvalidateRect(&rcInvalid, FALSE);
wndNewView.UpdateWindow();
}
}
// AnimateView:
//
// Animates the child view transitioning
//
void AnimateView(CWindow wndNewView, ViewAnimation nAnimation)
{
T* pT = static_cast<T*>(this);
int dx = 16,
dy = 16;
CDC dcMem;
CClientDC dc(pT->m_hWnd);
CBitmap bmp;
CRect rc;
HDC hClientDC;
CWindow wndOldView(pT->m_hWndClient);
// Repaint the current view
wndOldView.Invalidate(FALSE);
wndOldView.UpdateWindow();
hClientDC = pT->GetDC();
//pT->GetClientRect(&rc);
wndOldView.GetWindowRect(&rc);
pT->ScreenToClient(&rc);
// Create a bitmap snapshot of the old view
dcMem.CreateCompatibleDC();
bmp.CreateCompatibleBitmap(dcMem, rc.Width(), rc.Height());
dcMem.SelectBitmap(bmp);
dcMem.BitBlt(0, 0, rc.Width(), rc.Height(), hClientDC, 0, 0, SRCCOPY);
pT->ReleaseDC(hClientDC);
wndNewView.MoveWindow(rc.Width(), rc.top, rc.Width(), rc.Height(), FALSE);
wndNewView.ShowWindow(SW_SHOW);
dc.BitBlt(0, rc.top, rc.Width(), rc.Height(), dcMem, 0, 0, SRCCOPY);
wndOldView.ShowWindow(SW_HIDE);
m_dwMaxTick = 0;
switch(nAnimation)
{
case ScrollLeft:
case ScrollRight:
ScrollHorizontal(dc, rc, wndNewView, nAnimation, dx);
break;
case ScrollUp:
case ScrollDown:
ScrollVertical(dc, rc, wndNewView, nAnimation, dy);
break;
}
}
public:
CChildViewAnimate()
: m_pView (NULL),
m_dwMaxTick (0)
{
}
// ChildPreTranslateMessage
//
// PreTranslateMessage handler.
// Call this from the main form.
//
BOOL ChildPreTranslateMessage(MSG *pMsg)
{
if(m_pView != NULL)
return m_pView->PreTranslateMessage(pMsg);
return FALSE;
}
// SwitchToView
//
// Switches the current view to a new one.
// Returns the old view or NULL if switching to the same view.
//
CViewBase* SwitchToView(CViewBase *pView, ViewAnimation nAnimation)
{
CWindow wndOldView (m_pView->GetHWND()),
wndNewView (pView->GetHWND());
CViewBase* pOldView (m_pView);
// Don't change to self.
if(pView == m_pView)
return NULL;
T* pT = static_cast<T*>(this);
if(nAnimation != None)
AnimateView(wndNewView, nAnimation);
// Perform the child view switch
pT->m_hWndClient = wndNewView;
wndOldView.ShowWindow(SW_HIDE);
wndOldView.SetWindowLongPtr(GWL_ID, 0);
m_pView = pView;
wndNewView.SetWindowLongPtr(GWL_ID, ATL_IDW_PANE_FIRST);
wndNewView.SetFocus();
pT->UpdateLayout();
// If we did not animate the new child view, make
// sure it is visible and updated.
if(nAnimation == None)
{
wndNewView.ShowWindow(SW_SHOW);
wndNewView.Invalidate(FALSE);
wndNewView.UpdateWindow();
}
return pOldView;
}
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -