按照网上的代码,我继承了CStatic,实现了一个可以使背景色透明的子类CTransStatic。我现在用一个timer,每0.1秒让CTransStatic换一张图片,但是我发现可以明显地看到图片刷新。请问有什么办法能让换图的过程看上去比较流畅么?PS:
显示的是bitmap图片。
没有用LoadImage来取得HBITMAP,因为发现使用LoadImage刷新的更严重,而是使用的网上一段显示jpg图片的代码。如下:
HBITMAP LoadJPG(const char *FileName)
{
IPicture* p=NULL;
IStream* s=NULL;
HGLOBAL hG;
void* pp;
FILE* fp;
// Read file in memory
fp = fopen(FileName,"rb");
if (!fp)
return NULL;
fseek(fp,0,SEEK_END);
int fs = ftell(fp);
fseek(fp,0,SEEK_SET);
hG = GlobalAlloc(GPTR,fs);
if (!hG)
{
fclose(fp);
return NULL;
}
pp = (void*)hG;
fread(pp,1,fs,fp);
fclose(fp);
CreateStreamOnHGlobal(hG,false,&s);
if (!s)
{
GlobalFree(hG);
return NULL;
}
OleLoadPicture(s,0,false,IID_IPicture,(void**)&p);
if (!p)
{
s->Release();
GlobalFree(hG);
return NULL;
}
s->Release();
GlobalFree(hG);
HBITMAP hB = 0;
p->get_Handle((unsigned int*)&hB);
// Copy the image. Necessary, because upon p's release,
// the handle is destroyed.
HBITMAP hBB = (HBITMAP)CopyImage( hB,IMAGE_BITMAP,0,0,LR_COPYRETURNORG );
p->Release();
return hBB;
}
显示的是bitmap图片。
没有用LoadImage来取得HBITMAP,因为发现使用LoadImage刷新的更严重,而是使用的网上一段显示jpg图片的代码。如下:
HBITMAP LoadJPG(const char *FileName)
{
IPicture* p=NULL;
IStream* s=NULL;
HGLOBAL hG;
void* pp;
FILE* fp;
// Read file in memory
fp = fopen(FileName,"rb");
if (!fp)
return NULL;
fseek(fp,0,SEEK_END);
int fs = ftell(fp);
fseek(fp,0,SEEK_SET);
hG = GlobalAlloc(GPTR,fs);
if (!hG)
{
fclose(fp);
return NULL;
}
pp = (void*)hG;
fread(pp,1,fs,fp);
fclose(fp);
CreateStreamOnHGlobal(hG,false,&s);
if (!s)
{
GlobalFree(hG);
return NULL;
}
OleLoadPicture(s,0,false,IID_IPicture,(void**)&p);
if (!p)
{
s->Release();
GlobalFree(hG);
return NULL;
}
s->Release();
GlobalFree(hG);
HBITMAP hB = 0;
p->get_Handle((unsigned int*)&hB);
// Copy the image. Necessary, because upon p's release,
// the handle is destroyed.
HBITMAP hBB = (HBITMAP)CopyImage( hB,IMAGE_BITMAP,0,0,LR_COPYRETURNORG );
p->Release();
return hBB;
}
是否应该使用多个图片,还是应该将多个图片拼接成一张大图
是否应该用 CStatic控件实现这一个功能
等等。
{
static int i=0; //用于控制切换位图 CPaintDC dc(this);
CDC memoDC;
memoDC.CreateCompatibleDC(&dc);
CBitmap bitmap,*oldBitmap;
oldBitmap=NULL;
BITMAP bmp;
bitmap.LoadBitmap(IDB_BITMAP_BKGROUND+i); /////////////////////加载位图
bitmap.GetObject(sizeof(BITMAP),&bmp);
oldBitmap=memoDC.SelectObject(&bitmap);
CRect rectClient;
GetClientRect(&rectClient); dc.StretchBlt(0,0,rectClient.Width(),rectClient.Height(),&memoDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY); memoDC.SelectObject(oldBitmap); memoDC.DeleteDC();
bitmap.DeleteObject();
i++;
}上面的方法是先把位图绘制到内存DC中,然后再放缩到控件上。核心代码就是这样的。你只需设置在OnTimer中调用Invalidate刷新屏幕即可。bitmap.LoadBitmap(IDB_BITMAP_BKGROUND+i);每次刷新时都会加载下一副位图。
我使用了网上的代码,CTransStatic,他重写了OnPaint函数,但是这个函数有问题,无法将上一次的bitmap清除掉,导致我必须每次换图后要手动Invalidate窗口,导致刷新问题。代码如下:
void CTransStatic::OnPaint(){
HBITMAP l_hbmpBitmap = GetBitmap() ;
if( l_hbmpBitmap == NULL )
{
Default() ;
return ;
}
CPaintDC l_PaintDC( this ) ;
CRect l_rcClient ;
GetClientRect( &l_rcClient ) ;
CDC l_MaskDC ;
l_MaskDC.CreateCompatibleDC( &l_PaintDC ) ;
CBitmap l_MaskBitmap ;
l_MaskBitmap.CreateBitmap( l_rcClient.Width(), l_rcClient.Height(),
1, 1, NULL ) ;
CBitmap* l_pOldMaskBitmap = l_MaskDC.SelectObject( &l_MaskBitmap ) ;
CDC l_MemoryDC ;
l_MemoryDC.CreateCompatibleDC( &l_PaintDC ) ;
CBitmap* l_pOldMemoryBitmap =
l_MemoryDC.SelectObject( CBitmap::FromHandle( l_hbmpBitmap ) ) ;
COLORREF l_crOldBack =l_MemoryDC.SetBkColor( RGB( 160, 160, 64 ) ) ;//这是我定义的要滤掉的背景色。
l_MaskDC.BitBlt( 0, 0, l_rcClient.Width(), l_rcClient.Height(), &l_MemoryDC,
0, 0, SRCCOPY ) ;
l_PaintDC.BitBlt( 0, 0, l_rcClient.Width(), l_rcClient.Height(), &l_MemoryDC,
0, 0, SRCINVERT ) ;
l_PaintDC.BitBlt( 0, 0, l_rcClient.Width(), l_rcClient.Height(), &l_MaskDC,
0, 0, SRCAND ) ;
l_PaintDC.BitBlt( 0, 0, l_rcClient.Width(), l_rcClient.Height(), &l_MemoryDC,
0, 0, SRCINVERT ) ;
l_MemoryDC.SelectObject( l_pOldMemoryBitmap ) ;
l_MaskDC.SelectObject( l_pOldMaskBitmap ) ;
}
我每次换图后都要:
// m_static是显示图片的控件。 m_static->SetBitmap(hbmp); CRect rect;
m_static->GetClientRect(&rect);
//InvalidateRect(&rect);从而产生了刷新问题。