我一直在努力制作一个能够截取整个屏幕截图的SDL程序,在这种情况下,显示我整个显示器屏幕的实时信息。我已经成功到了能够使用GDI函数检索图像的程度,但我不知道如何在GetDIBits()函数返回后正确处理缓冲区中的数据输出。到目前为止,我的图像已远离预期的输出。我目前尝试的所有格式都混淆了颜色,这些格式是SDL纹理可用的大部分32位和24位像素格式。我的win32代码也可能有错误,我不完全确定,因为显示的图像不正确。
以下是我获取屏幕截图的方法:
void WINAPI get_screenshot( app_data * app )
{
HDC desktop = GetDC( NULL );
int width = GetDeviceCaps( desktop, HORZRES );
int height = GetDeviceCaps( desktop, VERTRES );
HDC desktop_copy = CreateCompatibleDC( 0 );
HGDIOBJ old = NULL;
HBITMAP screenshot = CreateCompatibleBitmap( desktop_copy, app->viewport.w, app->viewport.h );
BITMAPINFOHEADER screenshot_header = { 0 };
screenshot_header.biSize = sizeof( BITMAPINFOHEADER );
screenshot_header.biWidth = app->viewport.w;
screenshot_header.biHeight = -app->viewport.h;
screenshot_header.biPlanes = 1;
screenshot_header.biBitCount = 32;
screenshot_header.biCompression = BI_RGB;
if ( !screenshot )
{
ReleaseDC( NULL, desktop );
DeleteDC( desktop_copy );
DeleteObject( screenshot );
free_app_data( app );
win_error( "Creating Bitmap", true );
}
SetStretchBltMode( desktop_copy, HALFTONE );
SetBrushOrgEx( desktop_copy, 0, 0, NULL );
old = SelectObject( desktop_copy, screenshot );
if ( !StretchBlt( desktop_copy, 0, 0, app->viewport.w, app->viewport.h, desktop, 0, 0, width, height, SRCCOPY ) )
{
ReleaseDC( NULL, desktop );
DeleteDC( desktop_copy );
DeleteObject( screenshot );
free_app_data( app );
win_error( "Stretching Screenshot to Window Size", true );
}
if ( !GetDIBits( desktop_copy, screenshot, 0, app->viewport.h, app->pixels, ( BITMAPINFO * )&screenshot_header, DIB_RGB_COLORS ) )
{
ReleaseDC( NULL, desktop );
DeleteDC( desktop_copy );
DeleteObject( screenshot );
free_app_data( app );
win_error( "Getting Window RGB Values", true );
}
SelectObject( desktop_copy, old );
DeleteObject( screenshot );
ReleaseDC( NULL, desktop );
DeleteDC( desktop_copy );
return;
}
我觉得调用我的DLL函数的大部分代码都是自解释的,或者对于这篇文章并不重要,但我很乐意在必要时提供伪代码或纯win32 API代码。
创建SDL纹理和缓冲区的代码是:
app->frame = SDL_CreateTexture(
app->renderer,
SDL_PIXELFORMAT_ABGR8888,
SDL_TEXTUREACCESS_STREAMING,
app->viewport.w,
app->viewport.h
);
if ( !app->frame )
{
free_app_data( app );
SDL_errorexit( "Creating texture", 1, TRUE );
}
app->pixels = ( Uint32 * )create_array( NULL, ( app->viewport.w * app->viewport.h ), sizeof( Uint32 ), zero_array );
if ( !app->pixels )
{
free_app_data( app );
std_error( "Creating pixel buffer", TRUE );
}
同样,我在这种情况下使用我的DLL函数create_array(),但我认为你应该能够告诉它它的作用。
生成的图像是:
随意添加更好的方法或纯SDL方法。我尝试过GetPixel(),它返回正确的值。尽管如此,它的开销很高。
答案 0 :(得分:0)
捕获屏幕并将其绘制到表单的代码:
HDC hdcScreen, hdcForm;
hdcScreen = GetDC(NULL);
hdcForm = GetWindowDC(hwnd); //hwnd is form handle
StretchBlt(hdcForm, 0, 0, formW, formH, hdcScreen , 0, 0, screenW, screenH, SRCCOPY );
ReleaseDC(hwnd, hdcForm);
ReleaseDC(NULL, hdcScreen);
就这么简单。
瓦尔特