头文件
class CourseSituationView :
public CScrollView
{
DECLARE_DYNCREATE(CourseSituationView)
protected:
//DECLARE_MESSAGE_MAP()//CDialog中调用CScrollView不知道为什么不响应message map,只能自己响应WiondowProc
public:
CourseSituationView();
~CourseSituationView();
virtual void OnInitialUpdate();
private:
virtual void OnDraw(CDC *);//OnDraw不会主动触发,是CView在OnPaint的后面自动调用的虚函数
LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
BOOL OnEraseBkgnd(CDC *pDC);
HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor);
VOID OnPaint();
private:
int maxControlID;
COLORREF m_bkColor;
CBrush m_Brush;
};
cpp文件
CourseSituationView::CourseSituationView()
{
m_bkColor = RGB(0xff, 0xff, 0xff);
m_Brush.CreateSolidBrush(m_bkColor);
}
CourseSituationView::~CourseSituationView()
{
}
VOID CourseSituationView::OnDraw(CDC* pDC)
{
//CommonLog::getInstance()->WriteLog(LogLevel_debug, _T("scroll view on draw"));
//onDraw时cview的成员函数,会在onPaint的最后调用
}
VOID CourseSituationView::OnPaint()
{
CommonLog::getInstance()->WriteLog(LogLevel_debug, _T("scroll view paint"));
//onDraw时cview的成员函数,会在onPaint的最后调用
CScrollView::OnPaint();
}
BOOL CourseSituationView::OnEraseBkgnd(CDC *pDC)
{
CPaintDC dc(this);
RECT rect;
GetClientRect(&rect);
CBrush brush(RGB(0xff, 0x63, 0x21));
dc.FillRect(&rect, &brush);
return FALSE;
}
HBRUSH CourseSituationView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CScrollView::OnCtlColor(pDC, pWnd, nCtlColor);
TODO: 在此更改 DC 的任何特性
//CommonLog::getInstance()->WriteLog(LogLevel_debug, _T("course situation view onctlcolor"));
//if (nCtlColor == CTLCOLOR_STATIC)
//{
// //pDC->SetBkMode(TRANSPARENT);//设置透明,实际上没有真正的透明
// return (HBRUSH)::GetStockObject(WHITE_BRUSH);//设置背景色,透明应该用NULL_BRUSH
//}
//else if (nCtlColor == CTLCOLOR_DLG)
//{
// return m_Brush;
//}
// TODO: 如果默认的不是所需画笔,则返回另一个画笔
return m_Brush;
}
void CourseSituationView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize size, sizePage, sizeLine;
size.cx = 500;
size.cy = 600;
SetScrollSizes(MM_TEXT, size/*, sizePage, sizeLine*/);
}
void CourseSituationView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
SCROLLINFO si;
memset(&si, 0, sizeof(si));
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
GetScrollInfo(SB_VERT, &si);
int scrollPos = si.nPos;
int step = 10;
switch (nSBCode)
{
case SB_TOP:
si.nPos = si.nMin; break;
case SB_BOTTOM:
si.nPos = si.nMax; break;
case SB_LINEUP:
si.nPos -= step; break;
case SB_LINEDOWN:
si.nPos += step; break;
case SB_PAGEUP:
si.nPos -= si.nPage; break;
case SB_PAGEDOWN:
si.nPos += si.nPage; break;
case SB_THUMBTRACK:
si.nPos = si.nTrackPos; break;
default: break;
}
if (si.nPos >= (si.nMax + 1 - (int)si.nPage)) //****注意:在这儿滚动框滚到最底部了,其位置却是si.nMax+1-(int)si.nPage,而不是si.nMax, 其原因我也没去深究。
si.nPos = (si.nMax + 1 - (int)si.nPage);
else if (si.nPos <= si.nMin)
si.nPos = si.nMin;
si.fMask = SIF_ALL;
si.fMask = SIF_POS;
SetScrollInfo(SB_VERT, &si);
if (scrollPos != si.nPos)
::ScrollWindow(m_hWnd, 0, scrollPos - si.nPos, NULL, NULL);
UpdateWindow();
}
void CourseSituationView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
SCROLLINFO si;
memset(&si, 0, sizeof(si));
si.cbSize = sizeof(SCROLLINFO);
si.fMask = SIF_ALL;
GetScrollInfo(SB_HORZ, &si);
int scrollPos = si.nPos;
int step = 10;
switch (nSBCode)
{
case SB_LEFT:
si.nPos = si.nMin; break;
case SB_RIGHT:
si.nPos = si.nMax; break;
case SB_LINELEFT:
si.nPos -= step; break;
case SB_LINERIGHT:
si.nPos += step; break;
case SB_PAGELEFT:
si.nPos -= si.nPage; break;
case SB_PAGERIGHT:
si.nPos += si.nPage; break;
case SB_THUMBTRACK:
si.nPos = si.nTrackPos; break;
default: break;
}
if (si.nPos > (si.nMax + 1 - (int)si.nPage)) //****注意:在这儿滚动框滚到最底部了,其位置却是si.nMax+1-(int)si.nPage,而不是si.nMax, 其原因我也没去深究。
si.nPos = si.nMax + 1 - (int)si.nPage;
else if (si.nPos < si.nMin)
si.nPos = si.nMin;
si.fMask = SIF_ALL;
si.fMask = SIF_POS;
SetScrollInfo(SB_HORZ, &si);
if (scrollPos != si.nPos)
::ScrollWindow(m_hWnd, scrollPos - si.nPos, 0, NULL, NULL);
UpdateWindow();
}
LRESULT CourseSituationView::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONDOWN:
{
break;
}
case WM_PAINT:
{
OnPaint();
break;
}
case WM_ERASEBKGND:
{
return OnEraseBkgnd((CDC*)wParam);
break;
}
case WM_CTLCOLOR:
{
break;
}
case WM_CTLCOLORSTATIC://static的onctlcolor,还可以接收其他需要onctlcolor的消息
{
HDC hdcStatic = (HDC)wParam;
CDC *pDC = CDC::FromHandle(hdcStatic);
//SetTextColor(hdcStatic, RGB(255, 255, 255));
//SetBkColor(hdcStatic, RGB(0, 0, 0));
//HBRUSH hbrBkgnd = CreateSolidBrush(RGB(0, 0, 0));
//return (INT_PTR)hbrBkgnd;
HWND hWnd = (HWND)lParam;
CWnd* pWnd = CWnd::FromHandle(hWnd);
return (INT_PTR)OnCtlColor(pDC, pWnd, CTLCOLOR_STATIC);
}
case WM_COMMAND:
{
break;
}
case WM_VSCROLL:
{
UINT nSBCode = LOWORD(wParam);
UINT nPos = HIWORD(wParam);
CScrollBar* pScrollBar = (CScrollBar*)lParam;
OnVScroll(nSBCode, nPos, pScrollBar);
break;
}
default:
break;
}
return CView::DefWindowProcW(message, wParam, lParam);
}
1、在onDraw不是消息触发的,是CView在OnPaint中调用的虚函数
2、滚动需要自己处理部分事情,否则会出现滚动条自动回退到0
3、设置滚动区域SetScrollSizes,详见OnInitialUpdate中的实现
4、我是在CDialogEx的子类中调用的CScrollView,不知道为什么
BEGIN_MESSAGE_MAP(CourseSituationView, CScrollView)
ON_WM_VSCROLL()
ON_WM_ERASEBKGND()
ON_WM_CTLCOLOR()
ON_WM_PAINT()
END_MESSAGE_MAP()
不能响应,只能无奈响应WindowProc,然后根据消息自己调用OnCtlColor、OnPaint
5、要在OnDraw中自己处理刷新,不然会出现花屏,一个绘图被拉的老长。怎么处理还不想深究