WEB开发网
开发学院软件开发VC VC实现卡拉OK字幕叠加 阅读

VC实现卡拉OK字幕叠加

 2010-05-25 20:36:36 来源:WEB开发网   
核心提示:四. 性能优化我们在演示中发现,频繁地直接在窗口DC中画图会带来一定的闪烁感,VC实现卡拉OK字幕叠加(4),对此,我们可以进行一下优化,我们可以参考CSubtitleController类的DrawSubtitle2函数的实现:BOOL CSubtitleController::DrawSubtitle2(DWORD

四. 性能优化

我们在演示中发现,频繁地直接在窗口DC中画图会带来一定的闪烁感。对此,我们可以进行一下优化,即首先创建一个与目标窗口DC兼容的内存DC,在这个内存DC中画好字幕后,再将字幕位图从内存DC拷贝到目标窗口DC中去。

我们可以参考CSubtitleController类的DrawSubtitle2函数的实现:

BOOL CSubtitleController::DrawSubtitle2(DWORD inStreamTime)
{
ASSERT(mClientDC);
RECT bounds;
mTargetWnd->GetClientRect(&bounds);
int wndWidth = bounds.right - bounds.left;
int wndHeight = bounds.bottom - bounds.top;
CDC memDC;
// 创建与目标窗口DC兼容的内存DC
memDC.CreateCompatibleDC(mClientDC);
// 创建与目标窗口DC兼容的位图
HBITMAP membmp = CreateCompatibleBitmap(mClientDC->GetSafeHdc(),wndWidth,wndHeight);
// 将位图选入内存DC
HBITMAP oldbmp = (HBITMAP) memDC.SelectObject(membmp);
FillRect(memDC.GetSafeHdc(), &bounds, (HBRUSH)GetStockObject(LTGRAY_BRUSH));
/*----------------- 以下字幕操作都在内存DC中进行 ----------------*/
DWORD timeInChar = 0;
LONG sungLength = 0;
int currentChar = LocateChar(inStreamTime, timeInChar);
if (currentChar != -1)
{
sungLength = mFromToArray[currentChar].size.cx * timeInChar;
sungLength = sungLength / mFromToArray[currentChar].duration;
for (int i = 0; i < currentChar; i++)
{
sungLength += mFromToArray[i].size.cx;
}
}
else
{
sungLength = mTotalWidth;
}
CFont * pOldFont = (CFont *) memDC.SelectObject(&mTextFont);
memDC.SetBkMode(TRANSPARENT);
mSungRegion.CreateRectRgn(mStartPoint.x, mStartPoint.y,
mStartPoint.x + sungLength, mStartPoint.y + mFromToArray[0].size.cy);
mSingingRegion.CreateRectRgn(mStartPoint.x + sungLength, mStartPoint.y,
mStartPoint.x + mTotalWidth, mStartPoint.y + mFromToArray[0].size.cy);
// Draw the first part which has been sung
int ret = memDC.SelectClipRgn(&mSungRegion, RGN_COPY);
memDC.SetPolyFillMode(WINDING);
HPEN pOldPen = (HPEN) memDC.SelectObject(mSungBoundaryPen);
HBRUSH pOldBrush = (HBRUSH) memDC.SelectObject(mSungTextBrush);
memDC.BeginPath();
memDC.TextOut(mStartPoint.x, mStartPoint.y, mSubtitleLine);
memDC.EndPath();
memDC.StrokeAndFillPath();
memDC.SelectClipPath(RGN_AND);
memDC.SelectObject(pOldPen);
memDC.SelectObject(pOldBrush);
// Draw the second part which is waiting for being sung
pOldPen = (HPEN) memDC.SelectObject(mSingingBoundaryPen);
pOldBrush = (HBRUSH) memDC.SelectObject(mSingingTextBrush);
memDC.SelectClipRgn(&mSingingRegion, RGN_COPY);
memDC.BeginPath();
memDC.TextOut(mStartPoint.x, mStartPoint.y, mSubtitleLine);
memDC.EndPath();
memDC.StrokePath();
memDC.SelectClipPath(RGN_AND);
memDC.SelectObject(pOldBrush);
memDC.SelectObject(pOldPen);
mSungRegion.DeleteObject();
mSingingRegion.DeleteObject();
memDC.SelectObject(pOldFont);
// 将内存DC中的位图拷贝到目标窗口DC中
mClientDC->BitBlt(0, 0, wndWidth, wndHeight, &memDC, 0, 0, SRCCOPY);
// 删除内存DC及使用的资源
memDC.SelectObject(oldbmp);
DeleteObject(membmp);
memDC.DeleteDC();
return (currentChar != -1);
}

五. 结束语

本文介绍了卡拉OK字幕叠加的一般原理以及VC上使用GDI的一种简单实现,并且提供了完整的示例源代码,希望能够对读者朋友们有所启示。

上一页  1 2 3 4 

Tags:VC 实现 卡拉OK

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接