Introduction
This
vc++
article
explains how
to
scroll
text
on a fixed
image
background
in
VC++
6.0. I have
searched the
internet but
could not
find any
simple
article
on this.
So, I
started
experimenting
on this and
finally
found a
solution.
Well, I have
tested this
on WinXP
only.
Although the
primary aim
of this
article
is to
display
scrolling
text
on fixed
background,
it also
covers how
to
draw
a
background
with a
bitmap
brush.
Create an MFC
Doc/View
Project
Create an MFC
doc/view
project and
select
CScrollView
as the base
view class.
We have
selected
CScrollView
as base for
our view
class
because it
handles all
the
scrolling
stuff. Now
add a bitmap
resource
which you
want as
window
background.
Now create a
CBitmap
variable to
load your
bitmap
resource in
your frame
window
class.
Collapse
Copy
Code
class CMainFrame : public CFrameWnd
{
protected:
CMainFrame();
DECLARE_DYNCREATE(CMainFrame)
.
.
.
CBitmap m_bmBG;
In the
PreCreateWindow()
virtual
function,
change the
extended
style as
follows:
Collapse
Copy
Code
cs.dwExStyle |= WS_EX_COMPOSITED;
WS_EX_COMPOSITED
is an
Windows
extended
style
and MSDN
says that
this style
makes
painting all
descendants
of a window
in
bottom-to-top
painting
order using
double-buffering.
It will
serve our
purpose. In
OnCreate()
handler
function,
load our
bitmap.
Collapse
Copy
Code
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
.
.
m_bmBG.LoadBitmap(IDB_BITMAP1);
return 0;
}
Add
WM_ERASEBKGND
Windows
message
handler.
Here, we
will be
creating
pattern
brush
from our
bitmap
and select
it into the
device
context and
fill the
client area.
The code
looks like
this:
Collapse
Copy
Code
BOOL CMainFrame::OnEraseBkgnd(CDC* pDC)
{
CBrush hbr,*phbrOld;
CRect rect;
hbr.CreatePatternBrush(&m_bmBG);
phbrOld= pDC->SelectObject(&hbr);
GetClientRect(&rect);
pDC->FillRect(&rect,&hbr);
pDC->SelectObject(phbrOld);
hbr.DeleteObject();
return TRUE;
}
Don't forget
to add the
following
line in
Mainfrm.h:
Collapse
Copy
Code
#define WS_EX_COMPOSITED 0x02000000L
In the view
class handle
WM_CREATE
message and
in the
handler, add
the
following
code:
Collapse
Copy
Code
int CTransscrollView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CScrollView::OnCreate(lpCreateStruct) == -1)
return -1;
CClientDC dc(this);
m_ftTimes.CreatePointFont(500,"Times New Roman",&dc);
CFont *pOldFont;
pOldFont = dc.SelectObject(&m_ftTimes);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
m_nLineHt = tm.tmHeight + tm.tmExternalLeading;
dc.SelectObject(pOldFont);
return 0;
}
We have
created
50 point
Times New
Roman
font
and selected
into our
client
dc
.
Calculate
the line
height and
store it.
Don't forget
to create
CFont
m_ftTimes
and
int
m_nLineHt
class
variables.
Now handle
WM_ERASEBKGND
message.
Just return
TRUE
in the
message
handler.
Change the
OnInitialUpdate()
function,
change the
code.
Collapse
Copy
Code
void CTransscrollView::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
CSize sizeTotal;
sizeTotal.cx = 500;
sizeTotal.cy = 25 * m_nLineHt;
SetScrollSizes(MM_TEXT, sizeTotal);
}
We are going
to display
25 lines. We
are creating
a view large
enough to
show these
lines.
In
OnDraw()
,
we are going
to draw only
those lines
which will
become
visible when
scrolling.
Initially
all the
lines will
be drawn.
Collapse
Copy
Code
void CTransscrollView::OnDraw(CDC* pDC)
{
CTransscrollDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CFont *pOldFont;
int ct;
pDC->SetBkMode(TRANSPARENT);
int start = GetDeviceScrollPosition().y /m_nLineHt -1;
if (start < 0) start =0;
CRect rcClient;
GetClientRect(&rcClient);
ct = start + rcClient.Height()/m_nLineHt + 3;
if( ct > 25) ct=25;
pOldFont = pDC->SelectObject(&m_ftTimes);
pDC->SetTextColor(RGB(255,12,146));
for(int i=start;i<ct;i++)
{
CString s;
s.Format("I am line %d on a fixed background",i+1);
pDC->TextOut(0,i * m_nLineHt,s);
}
pDC->SelectObject(pOldFont);
}
As we know
on
scrolling,
ScrollWindow()
scrolls the
window
contents, we
need to
draw
only the
lines that
come to
visibility.
So we have
calculated
the starting
line number
and the
ending line
that will be
visible. We
have drawn
only those
lines. Note
that
initially
all lines
will be
drawn.