2015-05-07 29 views
28

Ekranı yakalamak için GDI kullanıyorum ve "Araç İpuçları" ekran görüntüsünde bulunmadığını fark ettim. Bu benim temel kodudur: "Araç İpuçları" ile ekran nasıl kaydedilir?

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... 

bu sabit edilebilir veya I (GDI hariç) ekran yakalamak için başka bir yaklaşım kullanmalıyım?


Düzenleme:

Bu Bunun Aracı İpucu göstermez aldı bir görüntü var.

enter image description here

+4

SRCCOPY'i deneyin | CAPTUREBLT? –

+1

Programınız muhtemelen başka bir yerde araç ipucunu kapatan fare veya klavye ile etkinleştirilir. –

+0

@Barmak Shemirani Hayır, Araç İpucu kapalı değil. – paul

cevap

10

Güncelleme Alex K. Adrian McCarthy ve arkadaşları tarafından önerilen CAPTUREBLT ilave edildi.

Aynı sorunu yeniden oluşturamıyorum. Masaüstü ekran görüntüsünü almayı başarırsanız, o zaman her şey orada olmalı! Bunun yerine bu kodu deneyin. 3 saniye beklemenin, bir takım ucunu manuel olarak etkinleştirmek için zaman vermesi gerektiğini unutmayın.

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

hakkında yorum yapan insanlara ne yazık ki sormadım. Sorumu düzenledim. – paul

+3

SRCCOPY'yi deneyin | Alex K.'ın yorumu başına CAPTUREBLT.Bu her zaman benim için çalıştı –

+0

Windows'un modern sürümleri daha hoşgörülü olsa da, bmp yok etmeden önce memdc bmp seçmek için hala iyi bir uygulamadır. Aslında, GetDIBits çağırmadan önce memdc dışında seçilmelidir. MSDN başına, "Uygulama bu işlevi çağırdığında, hbmp parametresi tarafından tanımlanan bitmap bir aygıt bağlamında seçilmemelidir." –

6

Windows XP sistemiyle birkaç yıl önce tam olarak sorun yaşadım. gibi

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... 

İpuçlarını: Eğer bitblt ve captureblt eklemek için sadece StretchBlt hattını değiştirmek gerekir, sizin için

Capture screenshot Including Semitransparent windows in .NET

: my soruya yanıt olarak kod sorunu çözüldü Şeffaf pencereler, bitblt özelliği tarafından atlanır. Ayrıca, yeniden boyutlandırmıyorsunuz, bu yüzden bitblt kullanın. Bu işe yaramazsa, diğer yorumcular için ipucu olarak yaptığınız şeyle ilgili başka bir sorun olabilir, bu nedenle soruyu yanıtımı C# 'dan C'ye çevirebilirsin. (tabii ki test etmek için daha fazla XP'm yok ama bu kesinlikle sorun).

İlgili konular