2015-05-07 27 views
28

Używam GDI do przechwytywania ekranu i zauważyłem, że "Porady na temat narzędzi" nie są zawarte na zrzucie ekranu. To jest mój podstawowy kod:Jak przechwycić ekran za pomocą "Poradnika narzędzia"?

HDC hdcDesk = GetDC(0); 

HDC hdcMem = CreateCompatibleDC(hdcDesk); 
HBITMAP hbmMem = CreateCompatibleBitmap(hdcDesk, 1920, 1080); 
SelectObject(hdcMem, hbmMem); 

StretchBlt(hdcMem, 0, 0, 1920, 1080, hdcDesk, 0, 0, 1920, 1080, SRCCOPY); 

// Now save the bitmap... 

Można to naprawić, czy powinienem użyć innego podejścia do przechwytywania ekranu (innego niż GDI)?


Edit:

To jest zrzut ekranu, który wziąłem, że nie wyświetla podpowiedzi.

enter image description here

+4

Wypróbuj SRCCOPY | CAPTUREBLT? –

+1

Twój program jest prawdopodobnie aktywowany za pomocą myszy lub klawiatury, która zamyka podpowiedź w innym miejscu. –

+0

@Barmak Shemirani Nie, końcówka narzędzia nie jest zamknięta. – paul

Odpowiedz

10

Aktualizacja: dodano CAPTUREBLT sugerowane przez Alex K., Adrian McCarthy et al.

Nie mogę odtworzyć tego samego problemu. Jeśli uda ci się zrobić zrzut ekranu z pulpitu, wszystko powinno tam być! Zamiast tego wypróbuj ten kod. Uwaga 3-sekundowe oczekiwanie ma dać czas na ręczne aktywowanie końcówki narzędzia.

int main() 
{ 
    Sleep(3000); 
    TCHAR* filename = TEXT("c:\\test\\_bmp.bmp"); 
    int width = GetSystemMetrics(SM_CXFULLSCREEN); 
    int height = GetSystemMetrics(SM_CYFULLSCREEN); 

    HDC hdc = GetDC(HWND_DESKTOP); 
    HBITMAP hbitmap = CreateCompatibleBitmap(hdc, width, height); 
    HDC memdc = CreateCompatibleDC(hdc); 
    HGDIOBJ oldbmp = SelectObject(memdc, hbitmap); 
    BitBlt(memdc, 0, 0, width, height, hdc, 0, 0, CAPTUREBLT | SRCCOPY); 

    WORD bpp = 24; //24-bit bitmap 
    DWORD size = ((width * bpp + 31)/32) * 4 * height; 
    BITMAPFILEHEADER filehdr = { 'MB', 54 + size, 0, 0, 54 }; 
    BITMAPINFOHEADER infohdr = { 40, width, height, 1, bpp }; 

    std::vector<BYTE> bits(size); 
    GetDIBits(hdc, hbitmap, 0, height, &bits[0], (BITMAPINFO*)&infohdr, DIB_RGB_COLORS); 

    std::ofstream f(filename, std::ios::binary); 
    f.write((char*)&filehdr, sizeof(filehdr)); 
    f.write((char*)&infohdr, sizeof(infohdr)); 
    f.write((char*)bits.data(), size); 

    SelectObject(memdc, oldbmp); 
    DeleteObject(memdc); 
    DeleteObject(hbitmap); 
    ReleaseDC(HWND_DESKTOP, hdc); 
    ShellExecute(0, 0, filename, 0, 0, SW_SHOW); 

    return 0; 
} 
+2

Niestety, to nie zadziałało. Zmieniłem moje pytanie. – paul

+3

Wypróbuj 'SRCCOPY | CAPTUREBLT' na komentarz Alexa K.To zawsze działało dla mnie. –

+0

Mimo że współczesne wersje Windows są bardziej tolerancyjne, dobrą praktyką jest wybranie bmp z memdc przed zniszczeniem bmp. W rzeczywistości powinien zostać wybrany z memdc zanim zadzwonisz do GetDIBits. W przypadku MSDN "Bitmapy identyfikowane przez parametr hbmp nie mogą być wybierane w kontekście urządzenia, gdy aplikacja wywołuje tę funkcję." –

6

Miałem problem dokładnie kilka lat temu z systemem Windows XP. Kod w odpowiedzi na moje pytanie rozwiązało problem:

Capture screenshot Including Semitransparent windows in .NET

dla ciebie, powinieneś być w stanie po prostu zmienić linię StretchBlt do bitblt i dodać captureblt:

HDC hdcDesk = GetDC(0); 

HDC hdcMem = CreateCompatibleDC(hdcDesk); 
HBITMAP hbmMem = CreateCompatibleBitmap(hdcDesk, 1920, 1080); 
SelectObject(hdcMem, hbmMem); 

BitBlt(hdcMem, 0, 0, 1920, 1080, hdcDesk, 0, 0, SRCCOPY | CAPTUREBLT); 

// Now save the bitmap... 

podpowiedzi, jak przezroczyste okna, są pomijane przez specyfikację bitblt. Poza tym nie zmieniasz rozmiaru, więc używaj bitblt. Jeśli to nie zadziała, może być coś jeszcze nie tak z tym, co robisz, jak podpowiedź innych komentatorów, więc możesz przekonwertować odpowiedź na moje pytanie z C# na C, które działało dla mnie na XP. (Oczywiście nie mam już XP do testowania, ale to był zdecydowanie problem).

Powiązane problemy