windows屏幕捕捉BitBlt函数鼠标闪烁问题

转自:http://liufan5005.blog.163.com/blog/static/26710173200911291739569/

我们在用BitBlt函数进行屏幕捕捉时,若传递了CAPTUREBLT(捕捉alpha blending,即半透

明窗口)标志,鼠标就会闪烁,这是为什么呢?
 
下文是本人阅读英文解释后的个人理解:
 
在windows2000及以后的系统上,鼠标及半透明窗口这两种图形对象是浮于桌面其他图形对象之上的,这里我们称它们为层叠窗口。层叠窗口并不存在于通常的显示场景(具体是在显示的哪一层,我也不清楚,姑且称它为场景M)中,只有在显示到屏幕的最后一刻,Windows才把层叠窗口绘制到屏幕上。
 
仅使用SRCCOPY标志时,Windows只需要从M中拷贝屏幕图像就行了。而若使用了CAPTUREBLT标志,导致的结果是鼠标及半透明窗口均被捕捉下来。但在设计上,BitBlt函数是不允许捕捉鼠标的。于是,系统只好先隐藏鼠标,然后捕捉图像,再恢复鼠标,结果就导致了鼠标的闪烁。

 

另附 捕捉鼠标代码:

//包含鼠标 CAPTUREBLT 会闪烁

// 将屏幕数据画如内存上下文
        BitBlt(hDCMem,0,0,xScrn,yScrn,hDCSource,0,0,SRCCOPY|CAPTUREBLT);
        // 因为获取的屏幕上不包含鼠标信息,可以手动添加到内存上下文
POINT ptCursor;
        GetCursorPos(&ptCursor);   
        DrawIconEx(hDCMem, ptCursor.x, ptCursor.y, hCursor, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE);  

 
附上英文原文:
You may have noticed that when you press the PrtSc key to take a screenshot, the cursor blinks briefly. Believe it or not, it actually does this for the same reason that the Windows XP fade-out shutdown screen does not include translucent windows.
These translucent windows, known as layered windows, are not normally included by the BitBlt function when reading pixels from the screen. In order to get them, you have to pass the CAPTUREBLT flag. When you do, you may also notice that the mouse cursor blinks. So why is that?
Once upon a time, the only graphical object that floated "above" the rest of the objects on your screen was the mouse cursor. Originally, the system supported only monochrome mouse cursors. These cursors were supported either in software or, if you happened to have an awesome video card, in hardware.
When you use a video card-supported cursor, the Graphics Device Interface (GDI) gives the video card a bitmap and a mask and says, "OK, this is the mouse cursor. Overlay this on the screen at the coordinates I specify." When the user moves the mouse, the GDI sends the video card updated coordinates, and the video card does the hard work of moving the pixels around the screen.
On the other hand, when you use a software-supported cursor, then the GDI is responsible for saving the pixels under the cursor before drawing it into the frame buffer. The procedure works in the following way: when the user moves the mouse, the GDI manually restores the original pixels, saves all of the pixels under the cursor's new position, and then it draws the cursor at that new position.
When a hardware cursor is employed, the pixels of the mouse cursor do not actually exist in the frame buffer because the hardware is responsible for performing the overlay. Consequently, the BitBlt function is able to just copy pixels from the frame buffer without fear of picking up pixels from the mouse cursor by mistake since those pixels don't exist in the frame buffer to begin with.
Conversely, if a software cursor is being used, then the GDI must remove the mouse cursor from the screen before performing a BitBlt from the screen if the region being copied overlaps the mouse cursor.
When animated cursors are employed, hardware cursors just don't quite cut the mustard, since hardware cursors don't animate. Therefore, animated cursors are implemented in software.
OK, great. But what does this have to do with CAPTUREBLT? Hang on, I'm getting there.
In Windows 2000, the composition mechanism that was used for software cursors was generalized so applications could also take advantage of it. These pseudo-cursors ultimately became known as layered windows. Like software cursors, layered windows don't show up when you do a BitBlt from the screen since they do not really exist in the usual sense. The pixels from the cursor and layered windows are composited onto the screen at the last moment.
But what if you want to capture the pixels of a layered window via BitBlt? That's where the new CAPTUREBLT flag comes into play. This captures the pixels after the composition engine has had its say. Since the code that generates the Windows XP dimmed shutdown screen doesn't pass the CAPTUREBLT, layered windows don't appear.
That still doesn't seem to explain why the cursor flickers, though. Actually, it does. The mouse cursor is just another composition object and therefore would be captured by the CAPTUREBLT flag. To prevent this from happening during a screen capture, the composition engine has to hide the cursor, do the CAPTUREBLT, and then re-show the cursor.
By exposing the Windows 2000 composition engine to applications, cursors have lost their special status. We've come full circle. It's now just like the good old days, back when all you had was a frame buffer and a software cursor.

你可能感兴趣的:(MFC编程)