滚动字幕闪烁(已使用双缓)

七十二寨寨主 2010-05-31 01:55:02
RT,
在窗体上用GDI+画的滚动字幕,在滚动的时候,会觉得有闪烁,每次1.0f的像素,已经使用图像的双缓,我确定双缓没有问题。

也许用闪烁不够准确,应该说是抖动,给人一种抖动的感觉,但幅度很小,只是恰好能让人感觉出来的那种。

有谁做过这方面的东西?或有什么建议,望指点。
...全文
527 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
l360220954 2011-10-11
  • 打赏
  • 举报
回复
CString str = L"这里显示滚动广告,谢谢!";
SelectObject(memDC.GetSafeHdc(), (HFONT)(*font));

CSize textSize = memDC.GetTextExtent(str); //计算单行文本的宽
CRect scrollRect = rectAD;
if(-1*m_offsetX > textSize.cx)
m_offsetX = rectAD.Width();
scrollRect.OffsetRect(m_offsetX, 0);

memDC.SetTextColor(RGB(0, 0, 0));
memDC.SetBkMode(TRANSPARENT);
//========================================================
memDC.DrawText(str, &scrollRect, DT_SINGLELINE|DT_LEFT|DT_VCENTER);

dc.BitBlt(0,0,rectAD.Width(),rectAD.Height(),&memDC,0,0,SRCCOPY);


我这里应该也是使用的双缓冲啊,怎么也还是不起作用呢,到底是怎么回事哦!
golden_maple 2010-06-06
  • 打赏
  • 举报
回复
双缓存使用有问题,详细见《Visual C++ 6编程实例与技巧》
tesling 2010-06-05
  • 打赏
  • 举报
回复
滚动频率太高,调低一点就行,0.1s滚动一次即可,人眼分不出来的。
===================================
每次向上滚动1.0个像素,0.003秒滚动一次,如果时间再短,的确肉眼不会明显感觉到闪,但速度太快了,那不是我想要的效果
houhq 2010-06-05
  • 打赏
  • 举报
回复
背景与文字颜色反差太大时,是会闪烁的,双缓存应该也避免不了,调节一下背景与文本颜色看看
muzizongheng 2010-06-04
  • 打赏
  • 举报
回复
本质都是SetFocus()的原因, 要具体分析.
muzizongheng 2010-06-04
  • 打赏
  • 举报
回复
一种原因是 你这个窗体一种得到focus了 , 和别的窗体得来的去就有抖动.

第二种是你用了updatewindow, 这样它会每次默认从0行滚到现在, 还是有闪烁的问题.
FrankSun80 2010-06-01
  • 打赏
  • 举报
回复
坐等高手~~~
nommm 2010-06-01
  • 打赏
  • 举报
回复
好像这种滚动的东西总会闪的。我写过一个也是,双缓冲不擦除也不好使,应该就是移动的步长和频率调节的不好
llrock 2010-06-01
  • 打赏
  • 举报
回复
使用 Sin Cos这种周期性函数都可以达到闪烁的目的.

void MyOutPut( const TCHAR* OutString, FLOAT TickTime )
{
if( sin(TickTime)> 0.f )
{
printf( TEXT("%s\n"),OutString );
}
else
{
printf(TEXT(" "));
}
}

TickTime是你程序的时钟,你总是可以获得一跳间歇性的信号,你可以乘上一个系数来调节闪烁的速度。思路大概是这样
七十二寨寨主 2010-05-31
  • 打赏
  • 举报
回复
内容太长,我删了几个没用的成员函数
七十二寨寨主 2010-05-31
  • 打赏
  • 举报
回复


// .cpp
// CaptionScroll.cpp : implementation file
//

#include "stdafx.h"

#include <locale>
#include <math.h>

#include "CaptionScroll.h"

// CCaptionScroll

IMPLEMENT_DYNAMIC(CCaptionScroll, CWnd)

CCaptionScroll::CCaptionScroll()
: m_clrBk(255, 220, 220, 220)
, m_clrFont(255, 0,0,0)
, m_fontSize(18.0f)
, m_fontType(_T("宋体"))
, m_percent(0.0f)
, m_indTopLine(0)
#ifdef _USE_FLOAT__
, m_scrollStep(1.0f)
, m_lineOffset(0.0f)
, m_fontPixHeight(0.0f)
, m_txtHeight(0.0f)
, m_lineDis(2.0f)
#else
, m_scrollStep(1)
, m_lineOffset(0)
, m_fontPixHeight(0)
, m_txtHeight(0)
, m_lineDis(2)
#endif
, m_timeLen(0.0f)
, m_timeCur(0.0f)
, m_pOwnerWnd(NULL)
, m_bDragAble(false)
{
}
void
CCaptionScroll::SetDragAble(bool b)
{
m_bDragAble = b;
}

bool
CCaptionScroll::SetCaptionFile(const CString& fileName)
{
Clear();

bool bRes = true;
if (m_capFile.Open(fileName, CStdioFile::modeRead|CFile::typeText) != FALSE)
{
char* old_locale = _strdup( setlocale(LC_CTYPE,NULL) );
setlocale( LC_CTYPE, "chs" ); //设定

// TODO: if the file is biggish, not read all strings once.
// catch some of them, and catch more after free some old catch if be needed.
BOOL bRes = FALSE;
do
{
try
{
CString strLine;
bRes = m_capFile.ReadString(strLine);
if (bRes != FALSE)
{
m_arrlistStr.Add(strLine);
}

}
catch (CFileException* e)
{
e;
MessageBox(_T("文件读取失败!"));
bRes = false;
break;
}

} while (bRes);

setlocale( LC_CTYPE, old_locale ); //还原区域设定
free( old_locale );

m_capFile.Close(); // if use cache, do not close file here
}
else
{
bRes = false;
}

Invalidate();

return bRes;
}

void
CCaptionScroll::AutoScroll(int direction, UINT nElapse)
{
SetTimer(direction, nElapse, NULL);
}

void
CCaptionScroll::ScrollUp()
{
static int i = 0;

int numAllLines = m_arrlistStr.GetCount();
if (m_indTopLine < numAllLines)
{

#ifdef _USE_FLOAT__
REAL lineH = m_fontPixHeight + m_lineDis;
#else
int lineH = m_fontPixHeight + m_lineDis;
#endif
m_lineOffset -= m_scrollStep;
if (m_lineOffset < -lineH)
{
m_lineOffset = m_lineOffset + lineH;
++m_indTopLine;
}

Invalidate();
}
}

void
CCaptionScroll::GotoPercent(float percent)
{
#ifdef _USE_FLOAT__
float lineH = m_fontPixHeight + m_lineDis;
int numAllLines = m_arrlistStr.GetSize();

float txtHeight = lineH * numAllLines;

float pos = txtHeight * percent;


m_indTopLine = (int)(pos / lineH);
m_lineOffset = -fmod(pos, lineH);

Invalidate();
#else
int lineH = m_fontPixHeight + m_lineDis;
int numAllLines = m_arrlistStr.GetSize();

int txtHeight = lineH * numAllLines;

int pos = int(txtHeight * percent);


m_indTopLine = (int)(pos / lineH);
m_lineOffset = -pos % lineH;

Invalidate();
#endif
}

float
CCaptionScroll::CurrPercent()
{
return m_percent;
}

void
CCaptionScroll::Reset()
{
#ifdef _USE_FLOAT__
m_percent = 0.0f;

m_indTopLine = 0;
m_lineOffset = 0.0f;

m_timeCur = 0.0f;
Invalidate();
#else
m_percent = 0;

m_indTopLine = 0;
m_lineOffset = 0;

m_timeCur = 0;
Invalidate();
#endif
}

void
CCaptionScroll::Clear()
{
if (m_capFile.m_hFile != CStdioFile::hFileNull)
{
m_capFile.Close();
}

m_arrlistStr.RemoveAll();
Reset();
#ifdef _USE_FLOAT__
m_timeLen = 0.0f;
m_txtHeight = 0.0f;
#else
m_timeLen = 0;
m_txtHeight = 0;
#endif
Invalidate();
}

void
CCaptionScroll::UpdateCurTime()
{
if (m_timeLen > 0 && m_timeCur <= m_timeLen)
{
if (m_timeCur > 0)
{
float percent = float(m_timeCur / m_timeLen);
GotoPercent(percent);
}
else if (m_timeCur == 0)
{
Reset();
}
}
}

//////////////////////////////////////////////////////////////////////////

void
CCaptionScroll::OnDraw(CDC* pDC)
{
Gdiplus::Graphics graphics(pDC->m_hDC);
graphics.Clear(m_clrBk);

int numLines = m_arrlistStr.GetCount();
if (numLines > 0)
{
Gdiplus::Font font(m_fontType, m_fontSize);
Gdiplus::SolidBrush brush(m_clrFont);
Gdiplus::StringFormat stringFormat;
stringFormat.SetAlignment(StringAlignmentNear);
stringFormat.SetLineAlignment(StringAlignmentNear);

#ifdef _USE_FLOAT__
REAL drewdHeight = 0;
REAL lineH = m_fontPixHeight + m_lineDis;
#else
int drewdHeight = 0;
int lineH = m_fontPixHeight + m_lineDis;
#endif
//Gdiplus::RectF rcLine((REAL)(m_rcClnt.left), (REAL)(m_rcClnt.top + m_lineOffset), (REAL)(m_rcClnt.Width()), m_fontPixHeight);
PointF ptOrg(0, (REAL)(m_rcClnt.top + m_lineOffset));

int numAllLines = m_arrlistStr.GetCount();
for (int ind = m_indTopLine; (ind < numAllLines) && (drewdHeight < m_rcClnt.bottom + lineH); ++ind)
{
const CString& str = m_arrlistStr.GetAt(ind);
if (!str.IsEmpty())
{
//graphics.DrawString(str, str.GetLength(), &font, rcLine, &stringFormat, &brush);
graphics.DrawString(str, str.GetLength(), &font, ptOrg, &brush);
// Gdiplus::GraphicsPath path;
// FontFamily fontFamily(m_fontType);
// path.AddString(str, str.GetLength(), &fontFamily, 0, m_fontSize, ptOrg, &stringFormat);
// graphics.FillPath(&brush, &path);
}

drewdHeight += lineH;
// rcLine.Y += lineH;
ptOrg.Y += lineH;
}
}


//int r = m_clrBk.GetR();
//int g = m_clrBk.GetG();
//int b = m_clrBk.GetB();
//COLORREF clrBk( RGB( r,g,b));
//CBrush brushBk( clrBk);
//pDC->SetBkMode(TRANSPARENT); //设置背景为透明!
//pDC->FillRect(m_rcClnt, &brushBk);


// int numLines = m_arrlistStr.GetCount();
// if (numLines > 0)
// {
// int y = m_lineOffset;
// int drewHeight = 0;
// int lineH = 18 + m_lineDis;

// for (int ind = m_indTopLine; (ind < numLines) && (drewHeight < m_rcClnt.bottom + lineH); ++ind)
// {
// const CString& str = m_arrlistStr.GetAt(ind);
// pDC->TextOut(0,y, str, str.GetLength());

// drewHeight += lineH;
// y += lineH;
// }
//}

}


BEGIN_MESSAGE_MAP(CCaptionScroll, CWnd)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_PAINT()
ON_WM_ERASEBKGND()
ON_WM_SIZE()
ON_WM_MOVE()
ON_WM_TIMER()

ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_WM_MOUSEWHEEL()

ON_WM_KEYUP()
END_MESSAGE_MAP()



// CCaptionScroll message handlers


int
CCaptionScroll::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
{
return -1;
}

CDC* pDC = GetDC();
Gdiplus::Graphics graphics(pDC->m_hDC);
Gdiplus::Font font(m_fontType, m_fontSize);
#ifdef _USE_FLOAT__
m_fontPixHeight = font.GetHeight(&graphics);
#else
m_fontPixHeight = (int)(font.GetHeight(&graphics) + 1);
#endif
ReleaseDC(pDC);

return 0;
}

void
CCaptionScroll::OnDestroy()
{
Clear();
CWnd::OnDestroy();
}

void
CCaptionScroll::OnPaint()
{
CWnd::OnPaint();

m_pDC = GetDC();

m_memDC.CreateCompatibleDC(m_pDC);

// 创建与m_pDC相兼容的内存位图
m_memBitmap.CreateCompatibleBitmap( m_pDC, m_rcSelf.Width(), m_rcSelf.Height());
// 内存绘图设备选择内存位图为绘制区
m_pOldBmp = m_memDC.SelectObject( &m_memBitmap);
// 创建内存绘图区
m_memDC.BitBlt( 0, 0, m_rcSelf.Width(), m_rcSelf.Height(), m_pDC, 0, 0, SRCCOPY);

// 使用内存设备,在内存位图中画图
OnDraw(&m_memDC);

// 使用屏幕设备,把内存设备中的图像画到屏幕上
m_pDC->BitBlt( 0, 0, m_rcSelf.Width(), m_rcSelf.Height(), &m_memDC, 0, 0, SRCCOPY);

m_memDC.SelectObject(m_pOldBmp);
m_memBitmap.DeleteObject();
m_memDC.DeleteDC();

ReleaseDC(m_pDC);
}

BOOL
CCaptionScroll::OnEraseBkgnd(CDC* pDC)
{
//return CWnd::OnEraseBkgnd(pDC);
return TRUE;
}

void
CCaptionScroll::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
GetWindowRect(&m_rcSelf);
GetClientRect(&m_rcClnt);
}

void
CCaptionScroll::OnMove(int x, int y)
{
CWnd::OnMove(x,y);
}

void
CCaptionScroll::OnTimer(UINT_PTR nIDEvent)
{
CWnd::OnTimer(nIDEvent);

if (nIDEvent == 0)
{
ScrollUp();
}
else if (nIDEvent == 1)
{
ScrollDown();
}
}


void
CCaptionScroll::OnLButtonDown(UINT nFlags, CPoint point)
{
CWnd::OnLButtonDown(nFlags, point);
m_oldMousePt = point;
ClientToScreen(&m_oldMousePt);
}

void
CCaptionScroll::OnMouseMove(UINT nFlags, CPoint point)
{
CWnd::OnMouseMove(nFlags, point);
SetFocus();

if ( m_bDragAble &&
((nFlags & MK_LBUTTON) == MK_LBUTTON)
)
{
ClientToScreen(&point);
if (m_oldMousePt != point)
{
int offsetW = point.x - m_oldMousePt.x;
int offsetH = point.y - m_oldMousePt.y;

m_rcSelf.left += offsetW;
m_rcSelf.right += offsetW;
m_rcSelf.top += offsetH;
m_rcSelf.bottom += offsetH;

MoveWindow(m_rcSelf);
m_oldMousePt = point;
}
//Invalidate();
UpdateWindow();
}
}


七十二寨寨主 2010-05-31
  • 打赏
  • 举报
回复

// .h
#pragma once

// CCaptionScroll
#define _USE_FLOAT__

class CCaptionScroll : public CWnd
{
DECLARE_DYNAMIC(CCaptionScroll)

public:
enum ViewMode
{
ModeFixedSize,
ModeAutoSize
};

CCaptionScroll();
virtual ~CCaptionScroll();

void SetMyOwner(CWnd* pWnd);
void SetDragAble(bool b);

bool SetCaptionFile(const CString& fileName);

void SetFontType(const CString& type);(/*Font, FontColor, FontSize*/);
const CString& GetFontType();
DWORD SetFontColor(DWORD dwARGB);
DWORD GetFontColor();
DWORD SetBkColor(DWORD dwARGB);
DWORD GetBkColor();

#ifdef _USE_FLOAT__
float SetStep(float step); // each time, the string scroll`s length.
float GetStep();
float SetLineDis(float dis);
float GetLineDis();
#else
int SetStep(int step);
int GetStep();
int SetLineDis(int dis);
int GetLineDis();
#endif

// ViewMode SetMode(ViewMode mode);

void AutoScroll(int direction, UINT nElapse);

void ScrollUp();
void ScrollDown();
void SetTimeLen(double dSecLen);
double GetTimeLen();
void SetTimeCur(double dSecCur);
double GetTimeCur();

void GotoPercent(float percent);
float CurrPercent();

void Reset();
void Clear();
protected:
virtual void OnDraw(CDC* pDC);

void UpdateCurTime();
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDestroy();
afx_msg void OnPaint();
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg void OnMove(int x, int y);
afx_msg void OnTimer(UINT_PTR nIDEvent);

afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);

afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags);
DECLARE_MESSAGE_MAP()

private:
// GDI+程序启动的标识
ULONG_PTR m_gdiplusToken;

//Gdiplus::Graphics* m_pGraphics;
CDC* m_pDC; // 用于画图的DC
CDC m_memDC; // 内存DC
CBitmap m_memBitmap; // 内存位图
CBitmap* m_pOldBmp; // 旧的位图指针
CRect m_rcSelf;
CRect m_rcClnt;
CWnd* m_pOwnerWnd;
bool m_bDragAble;

CStdioFile m_capFile;
CStringArray m_arrlistStr;

float m_percent;
int m_indTopLine; // 第一行显示字符串缓存中的第几行

#ifdef _USE_FLOAT__
REAL m_lineDis; // 行间距
REAL m_scrollStep; // 滚动的单元长度
float m_lineOffset;
REAL m_fontPixHeight; // 文字的像素高
REAL m_txtHeight;
#else
int m_lineDis;
int m_scrollStep;
int m_lineOffset;
int m_fontPixHeight;
int m_txtHeight;
#endif

double m_timeLen;
double m_timeCur;

CString m_fontType;
Gdiplus::REAL m_fontSize;

Gdiplus::Color m_clrBk;
Gdiplus::Color m_clrFont;

CPoint m_oldMousePt;
};


zhou1xp 2010-05-31
  • 打赏
  • 举报
回复
直接贴代码
七十二寨寨主 2010-05-31
  • 打赏
  • 举报
回复
没明白楼上的意思
我想我的是连续的,无论是在空间还是时间上

每次向上滚动1.0个像素,0.003秒滚动一次,如果时间再短,的确肉眼不会明显感觉到闪,但速度太快了,那不是我想要的效果
ljc0895 2010-05-31
  • 打赏
  • 举报
回复
显示不连续就会闪的

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧