2016-11-01 8 views
3

私はWebを通じていくつかの調査を行い、役に立つコードを見つけました。 C++とGDIを使用してスクリーンキャプチャで画面全体をキャプチャできない

#include <iostream> 
#include <Windows.h> 
#include <fstream> 

void CapruteScreenAndSaveToFile() 
{ 
    uint16_t BitsPerPixel = 24; 
    uint32_t Width = GetSystemMetrics(SM_CXSCREEN); 
    uint32_t Height = GetSystemMetrics(SM_CYSCREEN); 

    // Create Header 
    BITMAPFILEHEADER Header; 
    memset(&Header, 0, sizeof(Header)); 
    Header.bfType = 0x4D42; 
    Header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); 

    // Create Info 
    BITMAPINFO Info; 
    memset(&Info, 0, sizeof(Info)); 
    Info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
    Info.bmiHeader.biWidth = Width; 
    Info.bmiHeader.biHeight = Height; 
    Info.bmiHeader.biPlanes = 1; 
    Info.bmiHeader.biBitCount = BitsPerPixel; 
    Info.bmiHeader.biCompression = BI_RGB; 
    Info.bmiHeader.biSizeImage = Width * Height * (BitsPerPixel > 24 ? 4 : 3); 

    // Capture screen and save to Pixels 
    char* Pixels = NULL; 
    HDC MemDC = CreateCompatibleDC(0);//Context); 
    HBITMAP Section = CreateDIBSection(MemDC, &Info, DIB_RGB_COLORS, (void**)&Pixels, 0, 0); 
    DeleteObject(SelectObject(MemDC, Section)); 
    BitBlt(MemDC, 0, 0, Width, Height, GetDC(0), 0, 0, SRCCOPY); 
    DeleteDC(MemDC); 

    // Concatenate everything 
    char * buffer = (char*)malloc(sizeof(Header) + sizeof(Info.bmiHeader) + (((BitsPerPixel * Width + 31) & ~31)/8) * Height); 

    memcpy(buffer, (char*)&Header, sizeof(Header)); 
    memcpy(buffer + sizeof(Header), (char*)&Info.bmiHeader, sizeof(Info.bmiHeader)); 
    memcpy(buffer + sizeof(Header) + sizeof(Info.bmiHeader), Pixels, (((BitsPerPixel * Width + 31) & ~31)/8) * Height); 

    // Save to file 
    std::fstream hFile("Foo.bmp", std::ios::out | std::ios::binary); 

    hFile.write(buffer, sizeof(Header) + sizeof(Info.bmiHeader) + (((BitsPerPixel * Width + 31) & ~31)/8) * Height); 

    // Clean up 
    hFile.close(); 
    DeleteObject(Section); 
    free(buffer); 
} 


int main() 
{ 
    CapruteScreenAndSaveToFile(); 

    return 0; 
} 

しかし、私のデスクトップのこの部分をキャプチャするようだ:私は、画面全体をキャプチャし、私はUDPパケットを通じて送信できるバッファを生成するための試みで、それを少し変更し

enter image description here

私はCreateCompatibleDC(0)を使用しています。

+0

を再構築します。それは正常に動作しています。生成された "bmp"はフルスクリーンキャプチャを持っています。 – Naidu

+0

[SetWindowDisplayAffinity](https://msdn.microsoft.com/en-us/library/windows/desktop/dd375340.aspx)とOpenGLがあることを忘れないでください。両方ともあなたのコードに障害をもたらし、失敗させる可能性があります。あなたがここで解決しようとしている問題ではありませんが、必然的に逃げ出すことはありません。 – IInspectable

答えて

4

コンピュータのDPI設定が高く、アプリケーションがDPI対応でない場合、システムはアプリケーションに重なり、間違った画面サイズを与えます。

次のコードは、実際の画面サイズよりも小さい幅と高さを示しています:ソリューションは、アプリケーションにDPI awarenessを追加することです

uint32_t Width = GetSystemMetrics(SM_CXSCREEN); 
uint32_t Height = GetSystemMetrics(SM_CYSCREEN); 
std::cout << Width << " x " << Height << "\n"; 

を。あなたの場合に、 "パーモニターの高DPIが認識" または "高DPIを意識" DPI意識を設定し、>マニフェストツール

を - プロジェクトのプロパティに移動し、Visual Studioの2015年

:DPIとの互換性を追加するには

いくつかの古いコンパイラを使用している...

1)ファイルを作成し、この内容で "myapp.manifest":

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
    <application xmlns="urn:schemas-microsoft-com:asm.v3"> 
    <windowsSettings> 
     <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware> 
    </windowsSettings> 
    </application> 
</assembly> 

2)THIとのプロジェクトに* .RCファイルを追加します。 sのコンテンツ:

1 24 "myapp.manifest" 

3)私は自分のコンピュータ上でコードをテストしたプロジェクト

+0

これはおそらく正しい答えですが、それは私のWindows 8.1では明らかにVistaより新しいです。私はまだそれ以上の助けが必要です。それはSetProcessDPIAwareがWindows.hとリンクされたUser32.libを含んでいても、このスコープで宣言されていないと言います。 –

+0

'_WIN32_WINNT'を定義していないか、互換性のないMinGW-32を使用しているため、' SetProcessDPIAware'が動作しません。とにかく、DPI認識を追加する正しい方法は、マニフェストファイルです。これを私がすべてを推測しなければならないパズルには入れないでください。あなたが得ているエラーが再現可能なように最小限の情報を提供してください。 –

+0

ええ、私はMinGW-32を使用しています。それでは私は何を使うべきですか?そして多くの感謝! –

関連する問題