• Re: Windows screenshot

    From CV@21:1/5 to All on Thu Feb 17 06:04:00 2022
    El lunes, 14 de mayo de 2012 a la(s) 14:06:43 UTC-3, Saulius escribió:
    Try this code:

    proc main()
    Win2Bmp(,, 'SCR_S.bmp') // Full Screen
    Win2Bmp(, .t., 'SCR_W.bmp') // Full window w/ border, title, ...
    Win2Bmp(, .f., 'SCR_C.bmp') // Windows' client area
    return

    #pragma BEGINDUMP
    #include <windows.h>
    #include "hbapi.h"

    /*
    * Win2Bmp( [nWnd], [lFullWindow] [,cBmFile] ) --> nBitMap
    *
    * hWnd : window handle - if NIL then GetForegroundWindow()
    * lFullWindow : .T. = Window, .F. = Client, Nil = Screen
    * cBmFile : FileName for .bmp file
    */
    HB_FUNC( WIN2BMP )
    {
    HWND hWnd = ISNUM( 1 ) ? (HWND) hb_parnl( 1 ) :
    ISPOINTER( 1 ) ? (HWND) hb_parptr( 1 ) : GetForegroundWindow();
    UINT iWhat = ISLOG( 2 ) ? ( hb_parl( 2 ) ? 1 : 2 ) : 0;
    const char *pszBmF = ISCHAR( 3 ) && hb_parclen( 3 ) ? hb_parc( 3 ) : NULL; HDC hdcWin, hdcMem;
    HBITMAP hbmWin;
    RECT rc;

    if( iWhat == 1 )
    {
    hdcWin = GetWindowDC( hWnd );
    GetWindowRect( hWnd, &rc );
    }
    else if( iWhat == 2 )
    {
    hdcWin = GetDC( hWnd );
    GetClientRect( hWnd, &rc );
    }
    else
    {
    hdcWin = GetDC( NULL );
    rc.left = rc.top = 0;
    rc.right = GetSystemMetrics( SM_CXSCREEN );
    rc.bottom = GetSystemMetrics( SM_CYSCREEN );
    }

    hdcMem = CreateCompatibleDC( hdcWin );
    hbmWin = CreateCompatibleBitmap( hdcWin, rc.right - rc.left, rc.bottom - rc.top );
    SelectObject( hdcMem, hbmWin );
    BitBlt( hdcMem, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hdcWin, 0, 0, SRCCOPY );

    if( pszBmF ) // Save bmp to .bmp file ?
    {
    BITMAP bmWin;
    BITMAPFILEHEADER bmfHdr;
    BITMAPINFOHEADER bmiHdr;
    LPBITMAPINFOHEADER lpbmi;
    DWORD dwBmSize, dwByWritten = 0;
    HANDLE hBmF;

    // Get the BITMAP from the HBITMAP
    GetObject( hbmWin, sizeof( BITMAP ), &bmWin );

    // Fill in BITMAPINFOHEADER structure
    memset( (void *) &bmiHdr, 0, sizeof( BITMAPINFOHEADER ) );
    bmiHdr.biSize = sizeof( BITMAPINFOHEADER );
    bmiHdr.biWidth = bmWin.bmWidth;
    bmiHdr.biHeight = bmWin.bmHeight;
    bmiHdr.biPlanes = 1; // Should always be 1
    bmiHdr.biBitCount = 32; // color resolution (in bits per pixel) bmiHdr.biCompression = BI_RGB;
    //bmiHdr.biSizeImage =
    //bmiHdr.biXPelsPerMeter =
    //bmiHdr.biYPelsPerMeter =
    //bmiHdr.biClrUsed =
    //bmiHdr.biClrImportant = 0;

    dwBmSize = ( ( bmiHdr.biWidth * bmiHdr.biBitCount + 31 ) / 32 ) * 4 * bmiHdr.biHeight;

    lpbmi = (LPBITMAPINFOHEADER) hb_xgrab( sizeof( BITMAPINFOHEADER ) + dwBmSize );
    *lpbmi = bmiHdr;

    GetDIBits( hdcWin, hbmWin, 0, (UINT) bmWin.bmHeight, lpbmi, (BITMAPINFO *) lpbmi, DIB_RGB_COLORS );

    // Fill in BITMAPFILEHEADER structure
    memset( (void *) &bmfHdr, 0, sizeof( BITMAPFILEHEADER ) );
    bmfHdr.bfType = 0x4D42; //= "BM"
    bmfHdr.bfSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + dwBmSize;
    bmfHdr.bfOffBits = (DWORD) sizeof( BITMAPFILEHEADER ) + (DWORD) sizeof( BITMAPINFOHEADER );

    // Create and Write .bmp file and Close it
    hBmF = CreateFile( pszBmF, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
    WriteFile( hBmF, (LPSTR) &bmfHdr, sizeof( BITMAPFILEHEADER ), &dwByWritten, NULL );
    WriteFile( hBmF, (LPSTR) &bmiHdr, sizeof( BITMAPINFOHEADER ), &dwByWritten, NULL );
    WriteFile( hBmF, (LPSTR) lpbmi, dwBmSize, &dwByWritten, NULL );
    CloseHandle( hBmF );

    hb_xfree( lpbmi );
    }
    DeleteDC( hdcMem );
    ReleaseDC( hWnd, hdcWin );

    hb_retnl( (LONG) hbmWin );
    }
    #pragma ENDDUMP

    Best regards,
    Saulius


    Hi! sorry for jumping over an old message.

    This routine works perfectly BUT has a drawback: generates memory leaks.
    If used repeatedly over a day (calling it every 5'), then the computer lost about 1.5 gb of ram. Closing the application and starting again solves the problem.

    My solution to avoid this involves modifying a couple of lines, as seen below.

    From:
    ...
    CloseHandle( hBmF );
    hb_xfree( lpbmi );
    }
    DeleteDC( hdcMem );
    ReleaseDC( hWnd, hdcWin );

    hb_retnl( (LONG) hbmWin );
    }
    #pragma ENDDUMP

    To:
    ...
    CloseHandle( hBmF );
    hb_xfree( lpbmi );
    }
    hb_retnl( (LONG) hbmWin ); // RELOCATED

    DeleteObject(hbmWin); // ADDED
    DeleteObject( hdcMem ); // MODIFIED
    ReleaseDC( hWnd, hdcWin );
    }
    #pragma ENDDUMP

    It solved the problem I was facing.

    Best regards!
    ---
    Claudio Voskian
    Buenos Aires - Argentina

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael Hagl@21:1/5 to All on Thu Feb 24 11:19:51 2022
    CV schrieb am Donnerstag, 17. Februar 2022 um 15:04:02 UTC+1:
    El lunes, 14 de mayo de 2012 a la(s) 14:06:43 UTC-3, Saulius escribió:
    Try this code:

    proc main()
    Win2Bmp(,, 'SCR_S.bmp') // Full Screen
    Win2Bmp(, .t., 'SCR_W.bmp') // Full window w/ border, title, ...
    Win2Bmp(, .f., 'SCR_C.bmp') // Windows' client area
    return

    #pragma BEGINDUMP
    #include <windows.h>
    #include "hbapi.h"

    /*
    * Win2Bmp( [nWnd], [lFullWindow] [,cBmFile] ) --> nBitMap
    *
    * hWnd : window handle - if NIL then GetForegroundWindow()
    * lFullWindow : .T. = Window, .F. = Client, Nil = Screen
    * cBmFile : FileName for .bmp file
    */
    HB_FUNC( WIN2BMP )
    {
    HWND hWnd = ISNUM( 1 ) ? (HWND) hb_parnl( 1 ) :
    ISPOINTER( 1 ) ? (HWND) hb_parptr( 1 ) : GetForegroundWindow();
    UINT iWhat = ISLOG( 2 ) ? ( hb_parl( 2 ) ? 1 : 2 ) : 0;
    const char *pszBmF = ISCHAR( 3 ) && hb_parclen( 3 ) ? hb_parc( 3 ) : NULL; HDC hdcWin, hdcMem;
    HBITMAP hbmWin;
    RECT rc;

    if( iWhat == 1 )
    {
    hdcWin = GetWindowDC( hWnd );
    GetWindowRect( hWnd, &rc );
    }
    else if( iWhat == 2 )
    {
    hdcWin = GetDC( hWnd );
    GetClientRect( hWnd, &rc );
    }
    else
    {
    hdcWin = GetDC( NULL );
    rc.left = rc.top = 0;
    rc.right = GetSystemMetrics( SM_CXSCREEN );
    rc.bottom = GetSystemMetrics( SM_CYSCREEN );
    }

    hdcMem = CreateCompatibleDC( hdcWin );
    hbmWin = CreateCompatibleBitmap( hdcWin, rc.right - rc.left, rc.bottom - rc.top );
    SelectObject( hdcMem, hbmWin );
    BitBlt( hdcMem, 0, 0, rc.right - rc.left, rc.bottom - rc.top, hdcWin, 0, 0, SRCCOPY );

    if( pszBmF ) // Save bmp to .bmp file ?
    {
    BITMAP bmWin;
    BITMAPFILEHEADER bmfHdr;
    BITMAPINFOHEADER bmiHdr;
    LPBITMAPINFOHEADER lpbmi;
    DWORD dwBmSize, dwByWritten = 0;
    HANDLE hBmF;

    // Get the BITMAP from the HBITMAP
    GetObject( hbmWin, sizeof( BITMAP ), &bmWin );

    // Fill in BITMAPINFOHEADER structure
    memset( (void *) &bmiHdr, 0, sizeof( BITMAPINFOHEADER ) );
    bmiHdr.biSize = sizeof( BITMAPINFOHEADER );
    bmiHdr.biWidth = bmWin.bmWidth;
    bmiHdr.biHeight = bmWin.bmHeight;
    bmiHdr.biPlanes = 1; // Should always be 1
    bmiHdr.biBitCount = 32; // color resolution (in bits per pixel) bmiHdr.biCompression = BI_RGB;
    //bmiHdr.biSizeImage =
    //bmiHdr.biXPelsPerMeter =
    //bmiHdr.biYPelsPerMeter =
    //bmiHdr.biClrUsed =
    //bmiHdr.biClrImportant = 0;

    dwBmSize = ( ( bmiHdr.biWidth * bmiHdr.biBitCount + 31 ) / 32 ) * 4 * bmiHdr.biHeight;

    lpbmi = (LPBITMAPINFOHEADER) hb_xgrab( sizeof( BITMAPINFOHEADER ) + dwBmSize );
    *lpbmi = bmiHdr;

    GetDIBits( hdcWin, hbmWin, 0, (UINT) bmWin.bmHeight, lpbmi, (BITMAPINFO *) lpbmi, DIB_RGB_COLORS );

    // Fill in BITMAPFILEHEADER structure
    memset( (void *) &bmfHdr, 0, sizeof( BITMAPFILEHEADER ) );
    bmfHdr.bfType = 0x4D42; //= "BM"
    bmfHdr.bfSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + dwBmSize;
    bmfHdr.bfOffBits = (DWORD) sizeof( BITMAPFILEHEADER ) + (DWORD) sizeof( BITMAPINFOHEADER );

    // Create and Write .bmp file and Close it
    hBmF = CreateFile( pszBmF, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
    WriteFile( hBmF, (LPSTR) &bmfHdr, sizeof( BITMAPFILEHEADER ), &dwByWritten, NULL );
    WriteFile( hBmF, (LPSTR) &bmiHdr, sizeof( BITMAPINFOHEADER ), &dwByWritten, NULL );
    WriteFile( hBmF, (LPSTR) lpbmi, dwBmSize, &dwByWritten, NULL ); CloseHandle( hBmF );

    hb_xfree( lpbmi );
    }
    DeleteDC( hdcMem );
    ReleaseDC( hWnd, hdcWin );

    hb_retnl( (LONG) hbmWin );
    }
    #pragma ENDDUMP

    Best regards,
    Saulius
    Hi! sorry for jumping over an old message.

    This routine works perfectly BUT has a drawback: generates memory leaks.
    If used repeatedly over a day (calling it every 5'), then the computer lost about 1.5 gb of ram. Closing the application and starting again solves the problem.

    My solution to avoid this involves modifying a couple of lines, as seen below.
    From:
    ...
    CloseHandle( hBmF );
    hb_xfree( lpbmi );
    }
    DeleteDC( hdcMem );
    ReleaseDC( hWnd, hdcWin );

    hb_retnl( (LONG) hbmWin );
    }
    #pragma ENDDUMP
    To:
    ...
    CloseHandle( hBmF );
    hb_xfree( lpbmi );
    }
    hb_retnl( (LONG) hbmWin ); // RELOCATED

    DeleteObject(hbmWin); // ADDED
    DeleteObject( hdcMem ); // MODIFIED
    ReleaseDC( hWnd, hdcWin );
    }
    #pragma ENDDUMP

    It solved the problem I was facing.

    Best regards!
    ---
    Claudio Voskian
    Buenos Aires - Argentina
    Thank you Claudio!
    Michael Hagl

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)