📄 scrollwnd.cpp
字号:
CScrollBar* pBar;
DWORD dwStyle = GetStyle();
pBar = GetScrollBarCtrl(SB_VERT);
if ((pBar != NULL && !pBar->IsWindowEnabled()) ||
(pBar == NULL && !(dwStyle & WS_VSCROLL)))
{
// vertical scroll bar not enabled
sizeScroll.cy = 0;
}
pBar = GetScrollBarCtrl(SB_HORZ);
if ((pBar != NULL && !pBar->IsWindowEnabled()) ||
(pBar == NULL && !(dwStyle & WS_HSCROLL)))
{
// horizontal scroll bar not enabled
sizeScroll.cx = 0;
}
// adjust current x position
xOrig = x = GetScrollPos(SB_HORZ);
int xMax = GetScrollLimit(SB_HORZ);
x += sizeScroll.cx;
if (x < 0)
x = 0;
else if (x > xMax)
x = xMax;
// adjust current y position
yOrig = y = GetScrollPos(SB_VERT);
int yMax = GetScrollLimit(SB_VERT);
y += sizeScroll.cy;
if (y < 0)
y = 0;
else if (y > yMax)
y = yMax;
// did anything change?
if (x == xOrig && y == yOrig)
return FALSE;
if (bDoScroll)
{
// do scroll and update scroll positions
ScrollWindow(-(x-xOrig), -(y-yOrig));
//Invalidate();
if (x != xOrig)
SetScrollPos(SB_HORZ, x);
if (y != yOrig)
SetScrollPos(SB_VERT, y);
}
return TRUE;
}
void CScrollWnd::OnPaint()
{
CPaintDC dc(this); // device context for painting
CDC MemDC;
MemDC.CreateCompatibleDC(&dc);
CBitmap MemBMP;
CRect rc;
GetClientRect(rc);
MemBMP.CreateCompatibleBitmap(&dc, rc.Width(), rc.Height());
CBitmap* pOldBmp = MemDC.SelectObject(&MemBMP);
MemDC.PatBlt(0, 0, rc.Width(), rc.Height(), WHITENESS);
int nSavedDC = MemDC.SaveDC();
OnPrepareDC(&MemDC);
OnDraw(&MemDC);
MemDC.RestoreDC(nSavedDC);
dc.BitBlt(0, 0, rc.Width(), rc.Height(), &MemDC, 0, 0, SRCCOPY);
MemDC.SelectObject(pOldBmp);
// OnDraw(&dc);
}
/////////////////////////////////////////////////////////////////////////////
void CScrollWnd::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
if (m_nMapMode == MM_SCALETOFIT)
{
// force recalculation of scale to fit parameters
SetScaleToFitSize(m_totalLog);
}
else
{
// UpdateBars() handles locking out recursion
UpdateBars();
}
}
/////////////////////////////////////////////////////////////////////////////
// CScrollWnd scrolling
void CScrollWnd::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg())
return; // eat it
// ignore scroll bar msgs from other controls
if (pScrollBar != GetScrollBarCtrl(SB_HORZ))
return;
OnScroll(MAKEWORD(nSBCode, -1), nPos);
}
void CScrollWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (pScrollBar != NULL && pScrollBar->SendChildNotifyLastMsg())
return; // eat it
// ignore scroll bar msgs from other controls
if (pScrollBar != GetScrollBarCtrl(SB_VERT))
return;
OnScroll(MAKEWORD(-1, nSBCode), nPos);
}
BOOL CScrollWnd::OnMouseWheel(UINT fFlags, short zDelta, CPoint point)
{
// we don't handle anything but scrolling just now
if (fFlags & (MK_SHIFT | MK_CONTROL))
return FALSE;
// we can't get out of it--perform the scroll ourselves
return DoMouseWheel(fFlags, zDelta, point);
}
// This function isn't virtual. If you need to override it,
// you really need to override OnMouseWheel() here or in
// CSplitterWnd.
BOOL CScrollWnd::DoMouseWheel(UINT fFlags, short zDelta, CPoint point)
{
UNUSED_ALWAYS(point);
UNUSED_ALWAYS(fFlags);
// if we have a vertical scroll bar, the wheel scrolls that
// if we have _only_ a horizontal scroll bar, the wheel scrolls that
// otherwise, don't do any work at all
DWORD dwStyle = GetStyle();
CScrollBar* pBar = GetScrollBarCtrl(SB_VERT);
BOOL bHasVertBar = ((pBar != NULL) && pBar->IsWindowEnabled()) ||
(dwStyle & WS_VSCROLL);
pBar = GetScrollBarCtrl(SB_HORZ);
BOOL bHasHorzBar = ((pBar != NULL) && pBar->IsWindowEnabled()) ||
(dwStyle & WS_HSCROLL);
if (!bHasVertBar && !bHasHorzBar)
return FALSE;
BOOL bResult = FALSE;
UINT uWheelScrollLines = 10;//_AfxGetMouseScrollLines();
int nToScroll;
int nDisplacement;
if (bHasVertBar)
{
nToScroll = ::MulDiv(-zDelta, uWheelScrollLines, WHEEL_DELTA);
if (nToScroll == -1 || uWheelScrollLines == WHEEL_PAGESCROLL)
{
nDisplacement = m_pageDev.cy;
if (zDelta > 0)
nDisplacement = -nDisplacement;
}
else
{
nDisplacement = nToScroll * m_lineDev.cy;
nDisplacement = min(nDisplacement, m_pageDev.cy);
}
bResult = OnScrollBy(CSize(0, nDisplacement), TRUE);
}
else if (bHasHorzBar)
{
nToScroll = ::MulDiv(-zDelta, uWheelScrollLines, WHEEL_DELTA);
if (nToScroll == -1 || uWheelScrollLines == WHEEL_PAGESCROLL)
{
nDisplacement = m_pageDev.cx;
if (zDelta > 0)
nDisplacement = -nDisplacement;
}
else
{
nDisplacement = nToScroll * m_lineDev.cx;
nDisplacement = min(nDisplacement, m_pageDev.cx);
}
bResult = OnScrollBy(CSize(nDisplacement, 0), TRUE);
}
if (bResult)
UpdateWindow();
return bResult;
}
/////////////////////////////////////////////////////////////////////////////
// Getting information
CPoint CScrollWnd::GetScrollPosition() const // logical coordinates
{
if (m_nMapMode == MM_SCALETOFIT)
{
return CPoint(0, 0); // must be 0,0
}
CPoint pt = GetDeviceScrollPosition();
// pt may be negative if m_bCenter is set
if (m_nMapMode != MM_TEXT)
{
ASSERT(m_nMapMode > 0); // must be set
CWindowDC dc(NULL);
dc.SetMapMode(m_nMapMode);
dc.DPtoLP((LPPOINT)&pt);
}
return pt;
}
CPoint CScrollWnd::GetDeviceScrollPosition() const
{
CPoint pt(GetScrollPos(SB_HORZ), GetScrollPos(SB_VERT));
ASSERT(pt.x >= 0 && pt.y >= 0);
if (m_bCenter)
{
CRect rect;
GetClientRect(&rect);
// if client area is larger than total device size,
// the scroll positions are overridden to place origin such that
// output is centered in the window
// GetDeviceScrollPosition() must reflect this
if (m_totalDev.cx < rect.Width())
pt.x = -((rect.Width() - m_totalDev.cx) / 2);
if (m_totalDev.cy < rect.Height())
pt.y = -((rect.Height() - m_totalDev.cy) / 2);
}
return pt;
}
void CScrollWnd::GetDeviceScrollSizes(int& nMapMode, SIZE& sizeTotal, SIZE& sizePage, SIZE& sizeLine) const
{
if (m_nMapMode <= 0)
TRACE0("Warning: CScrollWnd::GetDeviceScrollSizes returning invalid mapping mode.\n");
nMapMode = m_nMapMode;
sizeTotal = m_totalDev;
sizePage = m_pageDev;
sizeLine = m_lineDev;
}
void CScrollWnd::SetScrollSizes(int nMapMode, SIZE sizeTotal,
const SIZE& sizePage, const SIZE& sizeLine)
{
ASSERT(sizeTotal.cx >= 0 && sizeTotal.cy >= 0);
ASSERT(nMapMode > 0);
ASSERT(nMapMode != MM_ISOTROPIC && nMapMode != MM_ANISOTROPIC);
int nOldMapMode = m_nMapMode;
m_nMapMode = nMapMode;
m_totalLog = sizeTotal;
//BLOCK: convert logical coordinate space to device coordinates
{
CWindowDC dc(NULL);
ASSERT(m_nMapMode > 0);
dc.SetMapMode(m_nMapMode);
// total size
m_totalDev = m_totalLog;
dc.LPtoDP((LPPOINT)&m_totalDev);
m_pageDev = sizePage;
dc.LPtoDP((LPPOINT)&m_pageDev);
m_lineDev = sizeLine;
dc.LPtoDP((LPPOINT)&m_lineDev);
if (m_totalDev.cy < 0)
m_totalDev.cy = -m_totalDev.cy;
if (m_pageDev.cy < 0)
m_pageDev.cy = -m_pageDev.cy;
if (m_lineDev.cy < 0)
m_lineDev.cy = -m_lineDev.cy;
} // release DC here
// now adjust device specific sizes
ASSERT(m_totalDev.cx >= 0 && m_totalDev.cy >= 0);
if (m_pageDev.cx == 0)
m_pageDev.cx = m_totalDev.cx / 10;
if (m_pageDev.cy == 0)
m_pageDev.cy = m_totalDev.cy / 10;
if (m_lineDev.cx == 0)
m_lineDev.cx = m_pageDev.cx / 10;
if (m_lineDev.cy == 0)
m_lineDev.cy = m_pageDev.cy / 10;
if (m_hWnd != NULL)
{
// window has been created, invalidate now
UpdateBars();
if (nOldMapMode != m_nMapMode)
Invalidate(TRUE);
}
}
/////////////////////////////////////////////////////////////////////////////
// Set mode and scaling/scrolling sizes
void CScrollWnd::SetScaleToFitSize(SIZE sizeTotal)
{
// Note: It is possible to set sizeTotal members to negative values to
// effectively invert either the X or Y axis.
ASSERT(m_hWnd != NULL);
m_nMapMode = MM_SCALETOFIT; // special internal value
m_totalLog = sizeTotal;
// reset and turn any scroll bars off
if (m_hWnd != NULL && (GetStyle() & (WS_HSCROLL|WS_VSCROLL)))
{
SetScrollPos(SB_HORZ, 0);
SetScrollPos(SB_VERT, 0);
EnableScrollBarCtrl(SB_BOTH, FALSE);
ASSERT((GetStyle() & (WS_HSCROLL|WS_VSCROLL)) == 0);
}
CRect rectT;
GetClientRect(rectT);
m_totalDev = rectT.Size();
if (m_hWnd != NULL)
{
// window has been created, invalidate
UpdateBars();
Invalidate(TRUE);
}
}
void CScrollWnd::ScrollToPosition(POINT pt) // logical coordinates
{
ASSERT(m_nMapMode > 0); // not allowed for shrink to fit
if (m_nMapMode != MM_TEXT)
{
CWindowDC dc(NULL);
dc.SetMapMode(m_nMapMode);
dc.LPtoDP((LPPOINT)&pt);
}
// now in device coordinates - limit if out of range
int xMax = GetScrollLimit(SB_HORZ);
int yMax = GetScrollLimit(SB_VERT);
if (pt.x < 0)
pt.x = 0;
else if (pt.x > xMax)
pt.x = xMax;
if (pt.y < 0)
pt.y = 0;
else if (pt.y > yMax)
pt.y = yMax;
ScrollToDevicePosition(pt);
}
/////////////////////////////////////////////////////////////////////////////
// Other helpers
void CScrollWnd::FillOutsideRect(CDC* pDC, CBrush* pBrush)
{
ASSERT_VALID(pDC);
ASSERT_VALID(pBrush);
// fill rect outside the image
CRect rect;
GetClientRect(rect);
ASSERT(rect.left == 0 && rect.top == 0);
rect.left = m_totalDev.cx;
if (!rect.IsRectEmpty())
pDC->FillRect(rect, pBrush); // vertical strip along the side
rect.left = 0;
rect.right = m_totalDev.cx;
rect.top = m_totalDev.cy;
if (!rect.IsRectEmpty())
pDC->FillRect(rect, pBrush); // horizontal strip along the bottom
}
void CScrollWnd::ResizeParentToFit(BOOL bShrinkOnly)
{
// adjust parent rect so client rect is appropriate size
ASSERT(m_nMapMode != MM_NONE); // mapping mode must be known
// determine current size of the client area as if no scrollbars present
CRect rectClient;
GetWindowRect(rectClient);
CRect rect = rectClient;
CalcWindowRect(rect);
rectClient.left += rectClient.left - rect.left;
rectClient.top += rectClient.top - rect.top;
rectClient.right -= rect.right - rectClient.right;
rectClient.bottom -= rect.bottom - rectClient.bottom;
rectClient.OffsetRect(-rectClient.left, -rectClient.top);
ASSERT(rectClient.left == 0 && rectClient.top == 0);
// determine desired size of the Wnd
CRect rectWnd(0, 0, m_totalDev.cx, m_totalDev.cy);
if (bShrinkOnly)
{
if (rectClient.right <= m_totalDev.cx)
rectWnd.right = rectClient.right;
if (rectClient.bottom <= m_totalDev.cy)
rectWnd.bottom = rectClient.bottom;
}
CalcWindowRect(rectWnd, CWnd::adjustOutside);
rectWnd.OffsetRect(-rectWnd.left, -rectWnd.top);
ASSERT(rectWnd.left == 0 && rectWnd.top == 0);
if (bShrinkOnly)
{
if (rectClient.right <= m_totalDev.cx)
rectWnd.right = rectClient.right;
if (rectClient.bottom <= m_totalDev.cy)
rectWnd.bottom = rectClient.bottom;
}
// dermine and set size of frame based on desired size of Wnd
CRect rectFrame;
CFrameWnd* pFrame = GetParentFrame();
ASSERT_VALID(pFrame);
pFrame->GetWindowRect(rectFrame);
CSize size = rectFrame.Size();
size.cx += rectWnd.right - rectClient.right;
size.cy += rectWnd.bottom - rectClient.bottom;
pFrame->SetWindowPos(NULL, 0, 0, size.cx, size.cy,
SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
}
CScrollWnd::CScrollWnd()
{
m_nMapMode = MM_NONE;
m_bInsideUpdate = FALSE;
m_bCenter = FALSE;
}
CScrollWnd::~CScrollWnd()
{
}
BOOL CScrollWnd::Create(CWnd *pParent, const RECT &rc, DWORD dwStyle, UINT nID)
{
return CWnd::Create(NULL, NULL, dwStyle, rc, pParent, nID);
}
void CScrollWnd::ClientToDocument(CPoint &pt)
{
ASSERT(m_nMapMode > 0); // not allowed for shrink to fit
CPoint ptScr = GetDeviceScrollPosition();
pt += ptScr;
if (m_nMapMode != MM_TEXT)
{
CWindowDC dc(NULL);
dc.SetMapMode(m_nMapMode);
dc.DPtoLP((LPPOINT)&pt);
}
}
void CScrollWnd::DocumentToClient(CPoint &pt)
{
ASSERT(m_nMapMode > 0); // not allowed for shrink to fit
CPoint ptScr = GetDeviceScrollPosition();
if (m_nMapMode != MM_TEXT)
{
CWindowDC dc(NULL);
dc.SetMapMode(m_nMapMode);
dc.LPtoDP((LPPOINT)&pt);
}
pt -= ptScr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -