hur.cn - 华软网

 热门搜索

InvalidateRect刷新的问题

  作者:未知    来源:网络    更新时间:2011/8/19

我定时调用这个函数刷新上面那个显示图像的picture控件,我是这样获取的
C++">
        hWnd=AfxGetApp()->m_pMainWnd->m_hWnd;
CWnd *pWnd = GetDlgItem(IDC_IMAGE);
pWnd->GetClientRect(&OnPaintRect);

然后在回调方法里这样写的
C++">
InvalidateRect(hWnd,OnPaintRect,FALSE);

这样就会出现上面那个很奇怪的问题,左上角那个影子也会一直刷新,而且大小和我下面的picture一样大,我拉大picture它也跟着变大,后来我改成::SendMessage(hWnd,WM_PAINT,0,0);它就不刷新了,画面要手动刷新才会变换了,请各位帮我想下
---华软 网友回答---
应该是背景和PICTURE刷新顺序搞错了
---华软网友回复---
刷新的区域不对
---华软网友回复---
引用 1 楼 xiaoc1026 的回复:
应该是背景和PICTURE刷新顺序搞错了

我只用的这一句话InvalidateRect(hWnd,OnPaintRect,FALSE);应该怎么改
---华软网友回复---
引用 2 楼 xiaojunjun1202 的回复:
刷新的区域不对

  hWnd=AfxGetApp()->m_pMainWnd->m_hWnd;
    CWnd *pWnd = GetDlgItem(IDC_IMAGE);
    pWnd->GetClientRect(&OnPaintRect);
这样获取区域应该没问题啊,而且下面那个也刷新到了,其他控件都不受影响
---华软网友回复---
   hWnd=AfxGetApp()->m_pMainWnd->m_hWnd;
    CWnd *pWnd = GetDlgItem(IDC_IMAGE);
    pWnd->GetClientRect(&OnPaintRect);
这里获得的Rect left和top都是0, 接着InvalidateRect(hWnd,OnPaintRect,FALSE);就刷新了左上角区域
应该InvalidateRect(pWnd.m_Hwnd,OnPaintRect,FALSE);

或pWnd->GetWindowsRect m_pMainWnd->ScreenToClient 再InvalidateRect(hWnd,OnPaintRect,FALSE)



---华软网友回复---
楼上正解
---华软网友回复---
引用 5 楼 linghu9990 的回复:
   hWnd=AfxGetApp()->m_pMainWnd->m_hWnd;
    CWnd *pWnd = GetDlgItem(IDC_IMAGE);
    pWnd->GetClientRect(&OnPaintRect);
这里获得的Rect left和top都是0, 接着InvalidateRect(hWnd,OnPaintRect,FALSE);就刷新了左上角区……
  恩,好的。我明天试下,程序在公司带不出,呵呵
---华软网友回复---
引用 5 楼 linghu9990 的回复:
   hWnd=AfxGetApp()->m_pMainWnd->m_hWnd;
    CWnd *pWnd = GetDlgItem(IDC_IMAGE);
    pWnd->GetClientRect(&OnPaintRect);
这里获得的Rect left和top都是0, 接着InvalidateRect(hWnd,OnPaintRect,FALSE);就刷新了左上角区域……

我这样做了,但是它就不刷新了,定在一个画面就不动了,大伙看看是不是这个问题,我重新将pWnd定义为一个全局变量了,程序就是这样,在一个界面的OnInitDialog方法中这样写
C++">
hWnd=AfxGetApp()->m_pMainWnd->m_hWnd;

pWnd = GetDlgItem(IDC_IMAGE);
pWnd->GetClientRect(&OnPaintRect);

里面pWnd和hWnd都是全局变量,OnPaintRect也是一个CRect的全局变量,然后我写了个全局的回调函数,
BOOL CALLBACK BeginCapture(HANDLE hBoard)
在这个方法下调用的InvalidateRect(pWnd.m_Hwnd,OnPaintRect,FALSE);这样调用这些全局变量行么,是不是导致它不刷新的原因是这个
---华软网友回复---
好奇怪,我单步OnPaintRect.top和OnPaintRect.left都是0,可是我通过pWnd->GetClientRect(&OnPaintRect);应该是获取到中间的那个picture的区域了呀,就是那个显示了动画的那个区域,为什么会是0呀
---华软网友回复---
 是不是:pWnd->GetWindowRect(&OnPaintRect);
---华软网友回复---
引用 10 楼 schlafenhamster 的回复:
 是不是:pWnd->GetWindowRect(&OnPaintRect);

不行,用了这个后还是会一闪一闪的
---华软网友回复---
我现在改成这样后,定义的全局变量有
HWND hWnd;
CWnd *pWnd;
CRect OnPaintRect;     //定义图像刷新区域
在OnInitDialog方法中是这样做的
hWnd=AfxGetApp()->m_pMainWnd->m_hWnd;
pWnd = GetDlgItem(IDC_IMAGE);
pWnd->GetWindowRect(&OnPaintRect);
在全局的回调函数中这样刷新
InvalidateRect(pWnd->m_hWnd,OnPaintRect,FALSE);
这样以后我一开软件,图像就定在那了,必须要我手动的切换页面才会刷新图像,等于不会实时的刷新,只能手动的了,为什么会这样啊,不过这样以后就没有左上角的阴影了
---华软网友回复---
为什么我将InvalidateRect(pWnd->m_hWnd,OnPaintRect,FALSE);中的hWnd改成pWnd->m_hWnd后它就像是要我更新一次OnPaint方法后它才会改变,感觉就像是页面有改变,它才会改变,但是原来我直接用hWnd的时候就可以实时刷新,就是左上角有个阴影,这是为什么啊??求教了
---华软网友回复---
回调方法用的什么消息?
---华软网友回复---
因为我用的是别人封装好了的回调方法,方法如下

BOOL CALLBACK Process(HANDLE hBoard,long no)
{
char  a[80];

if (avi==1)
{
sprintf(a,"image.avi,mjpg,con");
okSaveImageFile(hBoard,a,tnum,BUFFER,no,1);

/* else
{
sprintf(a,"t%03d.jpg",tnum);
okSaveImageFile(hBoard,a,0,BUFFER,no,1);
}*/


sprintf(string,"%5.2f",exCalcCaptureRatio(&num,&times));
AfxGetApp()->m_pMainWnd->SetDlgItemText(IDC_STATIC,string);
okConvertRect(hBoard,(TARGET)&blk,0,BUFFER,no,1);
  InvalidateRect(pWnd->m_hWnd,OnPaintRect,FALSE);
  UpdateWindow(hWnd);
// tnum++;

return 1;
}

然后在开始预览的时候调用okSetSeqCallback(hBoard,BeginCapture,Process,EndCapture);来调用回调方法,跟踪okSetSeqCallback进去后是

BOOL WINAPI okSetSeqCallback(HANDLE hBoard, 
BOOL CALLBACK BeginProc(HANDLE hBoard), 
BOOL CALLBACK SeqProc(HANDLE hBoard, long No), 
BOOL CALLBACK EndProc(HANDLE hBoard));
//set callback function for multi-frame capturing function 
//(which are okCaptureTo, okCaptureFrom,okCaptureToFile, okCaptureFromFile)
//see follow 

我在process这个回调这个加了个断点,发现程序开始后,它就进一次这里,然后就一直在OnPaint方法这里循环了,运行完一次OnPaint方法后马上又运行一遍,这样一直一直的
---华软网友回复---
就是说process这个回调只进入一次?
---华软网友回复---
是不是我OnPaint方法里的问题啊

void CTHIRD::OnPaint() 
{
CPaintDC dc(this); // device context for painting

     CDC *cdc;
// RECT rect;

cdc=m_image.GetDC();

m_image.GetClientRect(&OnPaintRect);
SetStretchBltMode(cdc->m_hDC,STRETCH_DELETESCANS);
StretchDIBits(cdc->m_hDC,
OnPaintRect.left,OnPaintRect.top,
OnPaintRect.right,OnPaintRect.bottom, 
0,0, //horzstart, vertstart, 
lpbi->biWidth,lpbi->biHeight,
lpdib,(LPBITMAPINFO)lpbi, 
DIB_RGB_COLORS,SRCCOPY);

  ReleaseDC(cdc);


}

---华软网友回复---
lpbi在哪里?
---华软网友回复---
这个定义的是一个LPBITMAPINFOHEADER的全局变量,赋值是在回调函数里面,以下是所有回调函数,开始采集,压缩,停止采集三个

BOOL CALLBACK BeginCapture(HANDLE hBoard)
{
short width,height;
long form;

exGetTargetSize(hBoard, BUFFER, &width, &height);
   form=okSetCaptureParam(hBoard,CAPTURE_SCRRGBFORMAT,GETCURRPARAM); //-1
exSetBitmapHeader(lpbi, width, height, HIWORD(form), LOWORD(form) );
blk.lpBits=lpdib;
blk.iBitCount=lpbi->biBitCount;
blk.iHeight =-(short)lpbi->biHeight;
blk.iWidth =(short)lpbi->biWidth;
if (avi==1)
okSaveImageFile(hBoard,"image.avi,mjpg,beg",0,BUFFER,0,1);

return 1;
}

BOOL CALLBACK Process(HANDLE hBoard,long no)
{
char  a[80];

if (avi==1)
{
sprintf(a,"image.avi,mjpg,con");
okSaveImageFile(hBoard,a,tnum,BUFFER,no,1);

/* else
{
sprintf(a,"t%03d.jpg",tnum);
okSaveImageFile(hBoard,a,0,BUFFER,no,1);
}*/


sprintf(string,"%5.2f",exCalcCaptureRatio(&num,&times));
AfxGetApp()->m_pMainWnd->SetDlgItemText(IDC_STATIC,string);
okConvertRect(hBoard,(TARGET)&blk,0,BUFFER,no,1);
  InvalidateRect(hWnd,OnPaintRect,FALSE);
  UpdateWindow(hWnd);
// tnum++;

return 1;
}

BOOL CALLBACK EndCapture(HANDLE hBoard)
{
okSetSeqCallback(hBoard,NULL,NULL,NULL);
okStopCapture(hBoard);
if (avi==1)
okSaveImageFile(hBoard,"image.avi,mjpg,end",0,BUFFER,0,1);

return 1;
}
//********************************************************************
float exCalcCaptureRatio(long *num,DWORD *times)
{
if( (*num>=12) || ((okGetTickCount()-(*times))>2000) ) 
{
*times=okGetTickCount()-(*times);
ratio=((float)(*num)*1000/(*times));
*num=0;
}

if(*num==0)
(*times)=okGetTickCount();
(*num)++;

return ratio;
}

long exGetTargetSize(HANDLE hBoard, TARGET tgt, short *width, short *height)
{
RECT rect;
long form;


if( (tgt==SCREEN ) ||(tgt==BUFFER) ) {
rect.right=-1;
okSetTargetRect(hBoard,tgt,&rect); //get current rect
if(width)
*width=(short)(rect.right-rect.left);
if(height)
*height=(short)(rect.bottom-rect.top);

if(tgt==SCREEN ) {
form=okSetCaptureParam(hBoard,CAPTURE_SCRRGBFORMAT,GETCURRPARAM); //-1
//limit to video rect
rect.right=-1; //max. captured rect
okSetTargetRect(hBoard,VIDEO,&rect); //get video rect
if(width)
*width=(short)min(*width,rect.right-rect.left);
if(height)
*height=(short)min(*height,rect.bottom-rect.top);
}
else if(tgt==BUFFER) 
form=okSetCaptureParam(hBoard,CAPTURE_BUFRGBFORMAT,GETCURRPARAM); //-1

} else if(tgt>BUFFER) { //from blkinfo
LPBLOCKINFO lpblk;
lpblk=(LPBLOCKINFO)tgt;

if(width)
*width=lpblk->iWidth;
if(height)
*height=abs(lpblk->iHeight);
form=MAKELONG(lpblk->iFormType,lpblk->iBitCount);
}


return form;
}

long exSetBitmapHeader(LPBITMAPINFOHEADER lpbi,short width,short height, short bits, short form)
{
long wbytes;

if(!lpbi)
return FALSE;


if(form==FORM_RGB555)
bits=16;
wbytes=((((width*bits)+31)&~31)>>3);//bmp need 4 byte align

lpbi->biWidth=width;
lpbi->biHeight=height;

lpbi->biSize=sizeof(BITMAPINFOHEADER);
lpbi->biPlanes=1;

lpbi->biBitCount=bits;
lpbi->biSizeImage=wbytes*height;


lpbi->biClrUsed=0;
//special format for 555,565 & 32 
if(form==FORM_RGB555 || form==FORM_RGB565 || form==FORM_RGB8888 ) 
lpbi->biCompression=BI_BITFIELDS;
else
lpbi->biCompression=0;
if(lpbi->biCompression==BI_BITFIELDS ) {//
DWORD *lpmask;
lpmask=(DWORD *)((LPSTR)lpbi+lpbi->biSize);

if(form==FORM_RGB555) {
lpmask[2]=0x001f; //blue
lpmask[1]=0x03e0;
lpmask[0]=0x7c00;
}
else if(form==FORM_RGB565) {
lpmask[2]=0x001f; //blue
lpmask[1]=0x07e0;
lpmask[0]=0xf800;
}
else if(bits==32 ) {
lpmask[2]=0x0000ff;
lpmask[1]=0x00ff00;
lpmask[0]=0xff0000;
}
}
else if(bits<=14) { // 8,10,12
int i,ratio;
RGBQUAD *lpRGB=(RGBQUAD *)((LPSTR)lpbi+lpbi->biSize);

lpbi->biClrUsed=(1<<bits);
ratio=lpbi->biClrUsed/256;

for(i=0; i<(short)lpbi->biClrUsed;i++) {
lpRGB[i].rgbBlue=i/ratio;
lpRGB[i].rgbGreen=i/ratio;
lpRGB[i].rgbRed=i/ratio;
lpRGB[i].rgbReserved=0;
}


lpbi->biClrImportant=lpbi->biClrUsed;

return lpbi->biClrUsed;
}

---华软网友回复---
从BOOL CALLBACK Process(HANDLE hBoard,long no)
看只要Process被调用InvalidateRect(hWnd,OnPaintRect,FALSE);
就会被调用。
插入:
AfxDump << "Process被调用\n";
看看。
好像Process只被调用了一次。
---华软网友回复---
引用 20 楼 schlafenhamster 的回复:
从BOOL CALLBACK Process(HANDLE hBoard,long no)
看只要Process被调用InvalidateRect(hWnd,OnPaintRect,FALSE);
就会被调用。
插入:
AfxDump << "Process被调用\n";
看看。
好像Process只被调用了一次。

我插入了,会一直弹出对话框,说明这个process一直被反复调用的
---华软网友回复---
AfxDump << "Process被调用\n";会弹出对话框?
这是在output中可以看到的。不会弹出对话框。
尤其在OnPaint() 中不能用MessageBox之类对话框。



---华软网友回复---
不是不是,我加的是AfxMessageBox,想看下它会调用process多少次,你那个我应该加在哪
---华软网友回复---
哪里用AfxMessageBox哪里就可以用AfxDump 他类似Trace在output中可以看到的。不会弹出对话框。

---华软网友回复---
你的意思是process被正常调用,图片不刷新?
看看那个lpbi里内容是不是变了
---华软网友回复---
引用 25 楼 schlafenhamster 的回复:
你的意思是process被正常调用,图片不刷新?
看看那个lpbi里内容是不是变了

这个的值没有变化,一直调用OnPaint都是下面这个样子

---华软网友回复---
我感觉问题还是出在InvalidateRect这个上面,我把OnPaint里的

m_image.GetClientRect(&rect);
SetStretchBltMode(cdc->m_hDC,STRETCH_DELETESCANS);
StretchDIBits(cdc->m_hDC,
rect.left,rect.top,
rect.right,rect.bottom, 
0,0, //horzstart, vertstart, 
lpbi->biWidth,lpbi->biHeight,
lpdib,(LPBITMAPINFO)lpbi, 
DIB_RGB_COLORS,SRCCOPY);

全都注释掉后,就只有一个阴影在刷,但是我把InvalidateRect这句话注释掉的话就不会有阴影,但是图像就不变化了
---华软网友回复---
吧lpbi放clipboard看看。
// move bmp to clipboard
OpenClipboard();
EmptyClipboard();
if(SetClipboardData(CF_BITMAP,IconInfo.hbmColor)) // not CF_DIB
m_ClipBroad.ShowWindow(SW_SHOW);
else
m_ClipBroad.ShowWindow(SW_HIDE);
//
CloseClipboard();
可以用paintbrush,粘贴的
---华软网友回复---
引用 28 楼 schlafenhamster 的回复:
吧lpbi放clipboard看看。
// move bmp to clipboard
OpenClipboard();
EmptyClipboard();
if(SetClipboardData(CF_BITMAP,IconInfo.hbmColor)) // not CF_DIB
m_ClipBroad.ShowWindow(SW_SHOW);
else
m_ClipBroad.……

应该b不是lpbi的问题吧,因为它的值都不会改变的呀
---华软网友回复---
你只看到大小,因为每个的大小都一样,问题是内容一样不一样,要不你在PAINT中用2个lpbi交换看显示对不对,我怀疑lpbi没有更新,所以PAINT同一个bmp
---华软网友回复---
引用 30 楼 schlafenhamster 的回复:
你只看到大小,因为每个的大小都一样,问题是内容一样不一样,要不你在PAINT中用2个lpbi交换看显示对不对,我怀疑lpbi没有更新,所以PAINT同一个bmp

我有点不太明白,应该怎么写让它交换,麻烦你了
---华软网友回复---
我不知道你的lpbi是怎么产生的。
---华软网友回复---
引用 27 楼 g6785654 的回复:
我感觉问题还是出在InvalidateRect这个上面,我把OnPaint里的
C/C++ code

    m_image.GetClientRect(&amp;rect);
        SetStretchBltMode(cdc->m_hDC,STRETCH_DELETESCANS);
        StretchDIBits(cdc->m_hDC,
           ……

我现在找出这样的原因来了,应该在InvalidateRect这里刷新有点问题吧,我把两句话注释掉的图贴出来
第一幅图是注释掉nvalidateRect后的,有图像,但是定在那不动,不刷新

第二幅图是注释掉OnPaint方法的,没有注释InvalidateRect,此时中间那个框一直在闪,波浪一样

---华软网友回复---
第一幅图是注释掉nvalidateRect后的,有图像,但是定在那不动,不刷新。当然
第二幅图是注释掉OnPaint方法的(m_image 画?),没有注释InvalidateRect,此时中间那个框一直在闪,波浪一样
是不是太快了?没秒有24帧就可以了。
---华软网友回复---
引用 34 楼 schlafenhamster 的回复:
第一幅图是注释掉nvalidateRect后的,有图像,但是定在那不动,不刷新。当然
第二幅图是注释掉OnPaint方法的(m_image 画?),没有注释InvalidateRect,此时中间那个框一直在闪,波浪一样
是不是太快了?没秒有24帧就可以了。

第二幅图我就是注释掉了这个

m_image.GetClientRect(&rect);
SetStretchBltMode(cdc->m_hDC,STRETCH_DELETESCANS);
StretchDIBits(cdc->m_hDC,
rect.left,rect.top,
rect.right,rect.bottom, 
0,0, //horzstart, vertstart, 
lpbi->biWidth,lpbi->biHeight,
lpdib,(LPBITMAPINFO)lpbi, 
DIB_RGB_COLORS,SRCCOPY);

是24帧,就是那个刷新的很明显,从上到下刷那个框框,就像很粗的一条白色的布慢慢刷下来。还有,如果我把InvalidateRect方法改成发送WM_PAINT命令让它重新运行OnPaint方法,它也和第一种情况一样,定在那,好像没有刷新一样
---华软网友回复---
要是可以,传工程上来(我用VC6),大家看看。
---华软网友回复---
引用 36 楼 schlafenhamster 的回复:
要是可以,传工程上来(我用VC6),大家看看。

可是我这个程序用到了采集卡,如果主机箱没有插入采集卡,程序运行不了的
---华软网友回复---
想法确定是不是是24帧,别的就帮不了你了,
---华软网友回复---
schlafenhamster
(schlafenhamster)
真的挺谢谢你的,虽然没有完全解决我的问题,不过我相信也快了,你那么有耐心的帮我,非常感谢你了      
华软声明:本内容来自网络,如有侵犯您版权请来信指出,本站立即删除。