在win32下缺少cvwaitkey时会造成显示视频或图片时不正常,通常是显示全灰色的窗口,而在MFC中显示图片则不用cvwaitkey,因为MFC有自己的消息循环机制。
问题: 1、cvWaitKey中影响显示的关键步骤是?
cvwaitkey源码:
CV_IMPL int
cvWaitKey( int delay)
{
int time0=GetTickCount();
for(;;)
{
CvWindow* window;
MSG message;
intis_processed= 0;
if((delay> 0 && abs((int)(GetTickCount()- time0)) >= delay) || hg_windows== 0 )
return-1;
if(delay<= 0 )
GetMessage(&message, 0, 0, 0);//GetMessage从消息队列中取出一条消息
else if(PeekMessage(&message, 0, 0, 0, PM_REMOVE) ==FALSE )//获取当前调用的线程的所有消息
// PeekMesssge只得到那些与参数hWnd标识的窗口相联系的消息或被lsChild确定为其子窗口相联系的消息,并且该消息要在由参数wMsgFiterMin和wMsgFiherMax确定的范围内。如果hWnd为NULL,则PeekMessage接收属于当前调用线程的窗口的消息(PeekMessage不接收属于其他线程的窗口的消息)。如果hWnd为-1,PeekMessage只返回hWnd值为NULL的消息,该消息由函数PostThreadMessage寄送。如果wMsgFilterMin和wMsgFilterMax都为零,PeekMessage返回所有可得的消息(即,无范围过滤)。
{
Sleep(1);
continue;
}
for(window= hg_windows; window != 0 && is_processed == 0; window =window->next)
{
if(window->hwnd== message.hwnd || window->frame == message.hwnd )
{
is_processed = 1;
switch(message.message)
{
case WM_DESTROY:
case WM_CHAR:
DispatchMessage(&message);
return(int)message.wParam;
case WM_SYSKEYDOWN:
if(message.wParam== VK_F10 )
{
is_processed = 1;
return (int)(message.wParam<<16);
}
break;
case WM_KEYDOWN:
TranslateMessage(&message);
if((message.wParam>= VK_F1 && message.wParam <= VK_F24) ||
message.wParam == VK_HOME||message.wParam == VK_END ||
message.wParam == VK_UP|| message.wParam == VK_DOWN ||
message.wParam == VK_LEFT || message.wParam== VK_RIGHT ||
message.wParam ==VK_INSERT || message.wParam == VK_DELETE ||
message.wParam ==VK_PRIOR || message.wParam == VK_NEXT )
{
DispatchMessage(&message);//DispatchMessage(&msg)把你的message传给wndproc这个函数并且运行这个函数
is_processed = 1;
return (int)(message.wParam<<16);
}
default:
DispatchMessage(&message);
is_processed = 1;
break;
}
}
}
if(!is_processed)
{
TranslateMessage(&message);
DispatchMessage(&message);
}
}
}
分析源码可知:
1:当 cvwaitkey参数为0时,有WM_KEYDOWN、WM_SYSKEYDOWN、WM_DESTROY、WM_CHAR消息时结束等待,否则持续循环
2:当 cvwaitkey参数大于0时,有WM_KEYDOWN、WM_SYSKEYDOWN、WM_DESTROY、WM_CHAR消息或等到时间大于delay时 结束等待,否则持续循环
3:
调用opencvc显示图片或一帧视频需三步:
1)cvNameWindow
2)cvShowImage
3)cvwaitkey
创建的窗口的指针保存在hg_windowsz中
4:cvWaitKey中影响显示的关键步骤是DispatchMessage函数,
用以下代码代替cvWaitKey时,在win32中能正确显示图片
MSGmessage;
while(1)
{
GetMessage(&message,0,0,0);
DispatchMessage(&message); }
cvWaitKey与多线程
cvwaitkey会调用DispatchMessage函数,所以在多线程时,尽量不要把cvWaitKey放到临界区里。
因为如果界面线程进入临界区后,收到了某消息(比如退出消息),那么会在DispatchMessage这里转去响应收到的消息,直到处理完毕才返回。
而此时还并没有退出临界区,因此有可能造成另一线程无法进入临界区从而被阻塞,
万一界面线程(在响应退出消息时)又需要等待被阻塞的线程(等它先退出然后再做些收尾工作),这样就形成死锁了
不清楚的问题:
1:MFC中关于opencv窗口的DispatchMessage函数在哪里调用?
2:循环过程中刷新窗口的过程是怎样的?