Исправлено форматирование текста. — SchweinDeBurg
На CView создаю дочернее окно с помощью CreateWindow. Класс окна CMyControl — наследник CWnd. Помещаю в
CMyControl объект CScrollBar, в CMyControl::OnCreate вызываю CScrollBar::Create.
Скроллбар создаётся. Сообщения от него обрабатываю в CMyControl::OnVScroll (т.к. только вертикальный
скроллбар), но чё то не получается. Т.е. окно скролится но не правильно: если скролить вниз, при первом
нажатии часть изображения снизу остается на месте остальное двигается, при повторных нажатиях история
повторяется с учетом сдвига окна. В итоге получается окно зарисовано многократно скопированной той самой
нижней частью изображения. Ничего не понимаю.
Вот код:
/*************************** MyControl.h*************************************/
#define OTSTUP 5
#define ICON_SIZE 16
#define TITLE_SIZE 45
#define INFO_SIZE 200
#define IP_TABLE_WIDTH 375
#define IP_TABLE_HEIGTH 166
#define ROW_HEIGHT 32
LRESULT CALLBACK MyWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
class CMyControl : public CWnd
{
public:
CMyControl();
static BOOL RegisterWndClass(HINSTANCE hInstance);
...
private:
bool IsOpen; // Открыто ли окно
CScrollBar scroll;
protected:
//{{AFX_MSG(CMyControl)
.....
afx_msg void OnPaint();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
/********************** MyControl.cpp **********************/
#include "stdafx.h"
#include "MyControl.h"
...
BEGIN_MESSAGE_MAP(CMyControl, CWnd)
//{{AFX_MSG_MAP(CMyControl)
...
// другие сообщения
...
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_VSCROLL()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
...
void CMyControl::OnPaint()
{
CPaintDC dc(this);
// Рисуем прямоугольник размером с окно
CRect rect;
GetClientRect(rect);
HBRUSH hOldBr,hBrush=CreateSolidBrush(RGB(190,211,233));
HPEN hOldPen,hPen=CreatePen(PS_SOLID,2,RGB(46,89,133));
hOldBr=(HBRUSH)dc.SelectObject(hBrush);
hOldPen=(HPEN)dc.SelectObject(hPen);
dc.SetBkColor(RGB(190,211,233));
dc.Rectangle(rect);
if(IsOpen) // Если открыта дополнительная часть окна (типа "Подробнее...")
{ // то рисуем еще линию отделяющую заголовок от нее
dc.MoveTo(0,44);
dc.LineTo(rect.right,44);
}
....
if(IsOpen)
{
DrawIpHdr(dc,rect,CurY); // Рисование в доп. части окна.
// там же будет прокрутка
}
dc.SelectObject(OldFont);
font.DeleteObject();
dc.SelectObject(hOldBr);
DeleteObject(hBrush);
dc.SelectObject(hOldPen);
DeleteObject(hPen);
// Do not call CWnd::OnPaint() for painting messages
}
void CMyControl::DrawIpHdr(CPaintDC &dc,CRect rect,int &CurY)
{
// здесь что-то рисуем
}
int CMyControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
CRect rect(2,45,18,244);
scroll.Create(SBS_VERT|WS_CHILD|WS_VISIBLE,rect,this,100);
SCROLLINFO scrlInfo;
scrlInfo.cbSize=sizeof(SCROLLINFO);
scrlInfo.fMask=SIF_ALL;
scrlInfo.nMin=0;
scrlInfo.nMax=400;
scrlInfo.nPage=50;
scrlInfo.nPos=0;
scrlInfo.nTrackPos = 2;
scroll.SetScrollInfo(&scrlInfo);
return 0;
}
void CMyControl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
static pos=0;
CRect Wndrect;
GetClientRect(Wndrect);
SCROLLINFO info;
pScrollBar->GetScrollInfo(&info);
switch(nSBCode)
{
.......
case SB_LINEDOWN:
if(pos<=info.nMax-10)
{
pos+=10;
pScrollBar->SetScrollPos(pos);
ScrollWindow(0,-10,CRect(18,TITLE_SIZE+10,Wndrect.right-2,TITLE_SIZE+198));
// CRect(...) - область прокрутки
}
else
{
int ost=pos-info.nMax;
pos=info.nMax;
pScrollBar->SetScrollPos(pos);
ScrollWindow(0,ost,CRect(18,TITLE_SIZE+10,Wndrect.right-2,TITLE_SIZE+198));
// CRect(...) - область прокрутки
}
break;
case SB_LINEUP:
if(pos>=info.nMin+10)
{
pos-=10;
pScrollBar->SetScrollPos(pos);
ScrollWindow(0,10,CRect(18,TITLE_SIZE,Wndrect.right-2,TITLE_SIZE+188));
// CRect(...) - область прокрутки
}
else
{
int ost=pos-info.nMin;
pos=info.nMin;
pScrollBar->SetScrollPos(pos);
ScrollWindow(0,ost,CRect(18,TITLE_SIZE,Wndrect.right-2,TITLE_SIZE+188));
// CRect(...) - область прокрутки
}
break;
default:;
}
CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
}
И ещё вопросик: Как изменить цвет ScrollBar'а если не устраивает стандартный серый?
Здравствуйте, sjman, Вы писали:
[]
S>И ещё вопросик: Как изменить цвет ScrollBar'а если не устраивает стандартный серый?
Я бы так сделал...
// Перерисовка
void CChildView::OnPaint()
{
CPaintDC dc(this); // device context for painting
CRect rcClient;
GetClientRect(&rcClient);
CRect rect(50,50,400,400);
dc.SetViewportOrg(0,-m_nVOffset);
dc.FillSolidRect(&rect, 0x0000FF);
dc.SetViewportOrg(0,0);
dc.FillSolidRect(0,0,rcClient.right,20, 0xFAC0FF);
dc.TextOut(20,1,"Ехал Грека через реку, цап за руку Греку рак! :-))");
}
int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
// инициализация скролбара
SCROLLINFO scrlInfo;
scrlInfo.cbSize=sizeof(SCROLLINFO);
scrlInfo.fMask=SIF_ALL;
scrlInfo.nMin=0;
scrlInfo.nMax=1000;
scrlInfo.nPage=400;
scrlInfo.nPos=0;
scrlInfo.nTrackPos = 0;
SetScrollInfo(SB_VERT, &scrlInfo);
return 0;
}
// m_nVOffset - переменная-член класса CChildView
void CChildView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
CRect rcClient;
GetClientRect(&rcClient);
rcClient.top+=20;
// calc new y position
int yOrig = GetScrollPos(SB_VERT);
int nDelta=0;
// ну тут получаем дельту
switch (nSBCode)
{
case SB_TOP:
nDelta = 0;
break;
case SB_BOTTOM:
nDelta = INT_MAX;
break;
case SB_LINEUP:
nDelta = -10;
break;
case SB_LINEDOWN:
nDelta = 10;
break;
case SB_PAGEUP:
nDelta = -100;
break;
case SB_PAGEDOWN:
nDelta = 100;
break;
case SB_THUMBTRACK:
nDelta = nPos-yOrig;
break;
}
m_nVOffset+=nDelta; // ставим оффсет
SetScrollPos(SB_VERT, m_nVOffset); // ЫуеЫскщддЗщы
ScrollWindow(0, -nDelta, 0, &rcClient); // скрол
CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
}
А цвет я не знаю как поменять! Это вроде нельзя сделать. Можно соорудить свой скролбар... или через CScrollBar::OnPaint рисуй сам.