窗口的屏幕截图

发布于 2024-08-15 18:59:30 字数 311 浏览 4 评论 0原文

我一直在编写一些代码来执行窗口的屏幕抓取(在 Windows 中)。该代码工作正常,但是在屏幕抓取之前,我必须将窗口带到我想要捕获并强制重绘的前面。

我使用 InvalidateRect 强制重绘,然后必须从消息循环中抽取一些消息,以便处理 WM_PAINT。这显然有点蹩脚,因为我不知道要发送多少消息。

我尝试将 RedrawWindow 与 RDW_ALLCHILDREN 一起使用,但是我从中抓取屏幕的应用程序是一个 MDI 应用程序,并且似乎不会重绘它的所有子项。

所以我的问题是,有没有更好的方法在屏幕抓取之前重绘窗口?

干杯 富有的

I've been writing some code to do a screen grab of a window (in Windows). The code works fine, however prior to the screen grab I have to bring the window to the front that I want to capture and force a redraw.

I force the redraw with InvalidateRect, I then have to pump some messages from the message loop in order for the WM_PAINT to get processed. This is obviously a bit lame, as i don't know how many messages to pump.

I tried using RedrawWindow with RDW_ALLCHILDREN, however the app I am grabbing a screen from is an MDI app and doesn't seem to redraw all of it's children.

So my question is, is there a better way to redraw the window prior to the screen grab?

Cheers
Rich

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

硬不硬你别怂 2024-08-22 18:59:30

由于您没有提到您使用的语言,我希望以下 C++ 代码对您有所帮助!

void getScreenShot( int texWidth, int texHeight, unsigned char* pBuffer, HWND handle )
{
    /* Local variables */
    HDC screenDC;
    RECT screenRect;
    int extraBytesPerRow;
    BITMAPINFO bitmapInfo;
    HDC bitmapDC;
    void* bitmapDataPtr;
    HBITMAP hBitmap;
    HBITMAP hPrevBitmap;
    unsigned char* pIn;
    unsigned char* pOut;
    int rowIndex;
    int colIndex;
    /* Get a DC from the desktop window */
    screenDC = GetDC(handle);
    GetClientRect(handle, &screenRect );
    /* Determine the extra bytes we need per row (each row of bitmap data must end on a 32bit boundary) */
    extraBytesPerRow = ( texWidth * 3 ) % 4;
    extraBytesPerRow = extraBytesPerRow ? 4 - extraBytesPerRow : 0;
    /* Setup the bitmap info structure */
    memset( &bitmapInfo, 0, sizeof( bitmapInfo ) );
    bitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
    bitmapInfo.bmiHeader.biWidth = texWidth;
    bitmapInfo.bmiHeader.biHeight = texHeight;
    bitmapInfo.bmiHeader.biPlanes = 1;
    bitmapInfo.bmiHeader.biBitCount = 24;
    bitmapInfo.bmiHeader.biCompression = BI_RGB;
    /* Create a bitmap device context (bitmapDataPtr will be a pointer to the bits in the bitmap) */
    bitmapDC = CreateCompatibleDC( NULL );
    hBitmap = CreateDIBSection( bitmapDC, ( BITMAPINFO* )&bitmapInfo.bmiHeader, DIB_RGB_COLORS, &bitmapDataPtr, NULL, 0 );
    hPrevBitmap = ( HBITMAP )SelectObject( bitmapDC, hBitmap );
    /* BitBlt or StretchBlt the image from the input DC into our bitmap DC */
    if ( ( texWidth != screenRect.right ) || ( texHeight != screenRect.bottom ) )
    {
        SetStretchBltMode( bitmapDC, HALFTONE );
        StretchBlt( bitmapDC, 0, 0, texWidth, texHeight, screenDC, 0, 0, screenRect.right, screenRect.bottom, SRCCOPY );
    }
    else
    {
        BitBlt( bitmapDC, 0, 0, texWidth, texHeight, screenDC, 0, 0, SRCCOPY);
    }
    /* Copy the data from the bitmap to the user's buffer (bitmap data is BGR and 4 byte aligned on each row, we want tightly-packed RGB) */
    pIn = ( unsigned char* )bitmapDataPtr;
    pOut = pBuffer;
    for ( rowIndex = 0; rowIndex < texHeight; rowIndex++ )
    {
        for ( colIndex = 0; colIndex < texWidth; colIndex++ )
        {
            pOut[ 0 ] = pIn[2];
            pOut[ 1 ] = pIn[1];
            pOut[ 2 ] = pIn[0];
            pOut += 3;
            pIn += 3;
        }
        pIn += extraBytesPerRow;
    }
    /* Free memory used by the bitmap */
    SelectObject( bitmapDC, hPrevBitmap );
    DeleteObject( hBitmap );
    DeleteDC( bitmapDC );
    /* Release the screen DC */
    ReleaseDC(handle, screenDC );
}

您实际上不需要强制重绘..但是如果窗口最小化,您可能需要在使用窗口句柄调用函数之前将其调出..! texWidth 和 texHeight 是您要捕获的窗口的尺寸;要获得此信息,您可以使用 GetWindowRect(..) 或查看此处的链接: 链接

Since you have not mentioned the language you are using, I hope the following code in C++ helps you!

void getScreenShot( int texWidth, int texHeight, unsigned char* pBuffer, HWND handle )
{
    /* Local variables */
    HDC screenDC;
    RECT screenRect;
    int extraBytesPerRow;
    BITMAPINFO bitmapInfo;
    HDC bitmapDC;
    void* bitmapDataPtr;
    HBITMAP hBitmap;
    HBITMAP hPrevBitmap;
    unsigned char* pIn;
    unsigned char* pOut;
    int rowIndex;
    int colIndex;
    /* Get a DC from the desktop window */
    screenDC = GetDC(handle);
    GetClientRect(handle, &screenRect );
    /* Determine the extra bytes we need per row (each row of bitmap data must end on a 32bit boundary) */
    extraBytesPerRow = ( texWidth * 3 ) % 4;
    extraBytesPerRow = extraBytesPerRow ? 4 - extraBytesPerRow : 0;
    /* Setup the bitmap info structure */
    memset( &bitmapInfo, 0, sizeof( bitmapInfo ) );
    bitmapInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
    bitmapInfo.bmiHeader.biWidth = texWidth;
    bitmapInfo.bmiHeader.biHeight = texHeight;
    bitmapInfo.bmiHeader.biPlanes = 1;
    bitmapInfo.bmiHeader.biBitCount = 24;
    bitmapInfo.bmiHeader.biCompression = BI_RGB;
    /* Create a bitmap device context (bitmapDataPtr will be a pointer to the bits in the bitmap) */
    bitmapDC = CreateCompatibleDC( NULL );
    hBitmap = CreateDIBSection( bitmapDC, ( BITMAPINFO* )&bitmapInfo.bmiHeader, DIB_RGB_COLORS, &bitmapDataPtr, NULL, 0 );
    hPrevBitmap = ( HBITMAP )SelectObject( bitmapDC, hBitmap );
    /* BitBlt or StretchBlt the image from the input DC into our bitmap DC */
    if ( ( texWidth != screenRect.right ) || ( texHeight != screenRect.bottom ) )
    {
        SetStretchBltMode( bitmapDC, HALFTONE );
        StretchBlt( bitmapDC, 0, 0, texWidth, texHeight, screenDC, 0, 0, screenRect.right, screenRect.bottom, SRCCOPY );
    }
    else
    {
        BitBlt( bitmapDC, 0, 0, texWidth, texHeight, screenDC, 0, 0, SRCCOPY);
    }
    /* Copy the data from the bitmap to the user's buffer (bitmap data is BGR and 4 byte aligned on each row, we want tightly-packed RGB) */
    pIn = ( unsigned char* )bitmapDataPtr;
    pOut = pBuffer;
    for ( rowIndex = 0; rowIndex < texHeight; rowIndex++ )
    {
        for ( colIndex = 0; colIndex < texWidth; colIndex++ )
        {
            pOut[ 0 ] = pIn[2];
            pOut[ 1 ] = pIn[1];
            pOut[ 2 ] = pIn[0];
            pOut += 3;
            pIn += 3;
        }
        pIn += extraBytesPerRow;
    }
    /* Free memory used by the bitmap */
    SelectObject( bitmapDC, hPrevBitmap );
    DeleteObject( hBitmap );
    DeleteDC( bitmapDC );
    /* Release the screen DC */
    ReleaseDC(handle, screenDC );
}

You dont actually need to force a redraw.. But in case the window is minimised, you might need to bring it up, before you call the function with the window handle..! texWidth and texHeight are dimension of the window you are about to capture; to get this you can use, GetWindowRect(..) or check out the link here: link

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文