2015-05-07 77 views
28

Sto utilizzando GDI per acquisire lo schermo e ho notato che i "Tool Tips" non sono inclusi nello screenshot. Questo è il mio codice di base:Come catturare lo schermo con "Tool Tips"?

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

questo può essere fissato, o dovrei utilizzare un altro approccio per catturare lo schermo (diverso da GDI)?


Edit:

Questo è uno screenshot che ho preso che non visualizza la punta dello strumento.

enter image description here

+4

Prova SRCCOPY | CAPTUREBLT? –

+1

Il tuo programma è probabilmente attivato da un mouse o da una tastiera che chiude il tooltip altrove. –

+0

@Barmak Shemirani No, la punta dello strumento non è chiusa. – paul

risposta

10

Aggiornamento: aggiunto CAPTUREBLT come suggerito da Alex K., Adrian McCarthy et al.

Non riesco a riprodurre lo stesso problema. Se riesci a scattare una schermata del desktop, tutto dovrebbe essere lì! Prova questo codice invece. Nota che l'attesa di 3 secondi dovrebbe dare il tempo di attivare manualmente un suggerimento.

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

Sfortunatamente, non ha funzionato. Ho modificato la mia domanda. – paul

+3

Prova 'SRCCOPY | CAPTUREBLT' per commento di Alex K.Questo ha sempre funzionato per me –

+0

Sebbene le versioni moderne di Windows siano più tolleranti, è comunque buona norma selezionare bmp out di memdc prima di distruggere bmp. Infatti, dovrebbe essere selezionato da memdc prima di chiamare GetDIBits. Per MSDN, "La bitmap identificata dal parametro hbmp non deve essere selezionata in un contesto di dispositivo quando l'applicazione chiama questa funzione." –

6

ho avuto il problema esatto a pochi anni fa, con un sistema Windows XP. Il codice in risposta alla mia domanda ha risolto il problema:

Capture screenshot Including Semitransparent windows in .NET

Per voi, si dovrebbe essere in grado di cambiare solo la tua linea di StretchBlt per bitblt e aggiungere 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... 

Tooltips, come finestre trasparenti, vengono saltate dalle specifiche di bitblt. Inoltre, non stai ridimensionando, quindi usa bitblt. Se ciò non funziona, potrebbe esserci qualcos'altro di sbagliato in quello che stai facendo come suggeriscono gli altri commentatori, quindi puoi convertire la risposta alla mia domanda da C# a C, che ha funzionato per me su XP. (Ovviamente non ho più XP da testare ma quello era sicuramente il problema).