Hi All!
It is time to Implement Screen Shot for real hardware!
Who is up to it?
8^D
James
Oldies but Gold'ies
Filip Navara wrote: 03/08/04 20:44
> James Tabor wrote:
>
>> Filip Navara wrote:
>>
>>> I cheated, because I used virtual machine with emulated S3 card, but
>>> it looks same on real HW. If you need a screenshot feature, I'll try
>>> find on of my old patches that saves screenshots to files and adapt
>>> it for the current CVS.
>>>
>>> Regards,
>>> Filip
>>>
>> Ya! A good work around hack is good! If you can do so.
>> Thank,
>> James
>
>
> Here it is. Few notes:
> 1) Beware, it's hack!
> 2) It's a not little hack, it's a big hack!
> 3) Saves the screenshot to c:\reactos\screenshot.bmp.
> 4) Press ALT-PRINTSCREEN in any usual window (not console) to take the
> screenshot.
>
> - Filip
>
>
> ------------------------------------------------------------------------
>
> Index: drivers/video/videoprt/videoprt.c
> Index: lib/user32/windows/defwnd.c
> ===================================================================
> RCS file: /CVS/ReactOS/reactos/lib/user32/windows/defwnd.c,v
> retrieving revision 1.124
> diff -u -r1.124 defwnd.c
> --- lib/user32/windows/defwnd.c 22 Feb 2004 23:40:58 -0000 1.124
> +++ lib/user32/windows/defwnd.c 8 Mar 2004 20:26:40 -0000
> @@ -949,10 +949,205 @@
> return GetSysColorBrush(COLOR_WINDOW);
> }
>
> +/*
> + * CreateBitmapInfoStructure
> + *
> + * Creates a bitmap info structure for saving a bitmap into a file.
> + */
> +
> +PBITMAPINFO FASTCALL
> +CreateBitmapInfoStructure(HDC hDC, HBITMAP hBmp)
> +{
> + BITMAP bmp;
> + PBITMAPINFO pbmi;
> + WORD cClrBits;
> +
> + /* Get the width, height and the colordepth of the image. */
> + if (!GetObjectW(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
> + {
> + return NULL;
> + }
> +
> + /* Convert the color format to a count of bits. */
> + cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
> +
> + /*
> + * Allocate memory for the BITMAPINFO-structure. This structure
> + * contains a BITMAPINFOHEADER-structure and an array of RGBQUAD
> + * datastructures.
> + */
> + if (cClrBits <= 8)
> + pbmi = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << cClrBits));
> + else
> + pbmi = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER));
> +
> +
> + /* Initialize the fields in the BITMAPINFO-structure. */
> + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
> + pbmi->bmiHeader.biWidth = bmp.bmWidth;
> + pbmi->bmiHeader.biHeight = bmp.bmHeight;
> + pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
> + pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
> +
> + if (cClrBits <= 8)
> + pbmi->bmiHeader.biClrUsed = 1 << cClrBits;
> +
> + pbmi->bmiHeader.biCompression = BI_RGB;
> +
> + /*
> + * Compute the number of bytes in the array of color indices
> + * and store the result in biSizeImage.
> + */
> +
> + pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) / 8 * pbmi->bmiHeader.biHeight * cClrBits;
> +
> + /*
> + * Set biClrImportant to 0 to indicate that all of the device
> + * colors are important.
> + */
> +
> + pbmi->bmiHeader.biClrImportant = 0;
> +
> + /* And finally return the info-structure. */
> + return pbmi;
> +}
> +
> +/*
> + * SaveBitmap
> + *
> + * Saves a bitmap to a specified file.
> + */
> +
> +HRESULT FASTCALL
> +SaveBitmap(PWCHAR strFileName, HDC hDC, HBITMAP hBMP)
> +{
> + HANDLE hf;
> + BITMAPFILEHEADER hdr;
> + PBITMAPINFOHEADER pbih;
> + LPBYTE lpBits;
> + DWORD dwTotal;
> + DWORD cb;
> + BYTE *hp;
> + DWORD dwTmp;
> + PBITMAPINFO pbi;
> +
> + pbi = CreateBitmapInfoStructure(hDC, hBMP);
> + if (pbi == NULL)
> + {
> + return E_FAIL;
> + }
> +
> + pbih = (PBITMAPINFOHEADER)pbi;
> + lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
> +
> + if (!lpBits)
> + {
> + return E_FAIL;
> + }
> +
> + /*
> + * Retrieve the colortable (RGBQUAD-array) and the bits
> + * (array of palette indices) from the DIB.
> + */
> +
> + if (!GetDIBits(hDC, hBMP, 0, (WORD)pbih->biHeight, lpBits, pbi, DIB_RGB_COLORS))
> + {
> + return E_FAIL;
> + }
> +
> +
> + /* Create the .BMP file. */
> +
> + hf = CreateFileW(
> + strFileName,
> + GENERIC_READ | GENERIC_WRITE,
> + (DWORD)0,
> + NULL,
> + CREATE_ALWAYS,
> + FILE_ATTRIBUTE_NORMAL,
> + (HANDLE)NULL);
> +
> + if (hf == INVALID_HANDLE_VALUE)
> + {
> + return E_FAIL;
> + }
> +
> + hdr.bfType = 0x4D42; /* 0x42 = "B", 0x4D = "M" */
> +
> + /* Compute the size of the entire file. */
> + hdr.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD) + pbih->biSizeImage);
> + hdr.bfReserved1 = 0;
> + hdr.bfReserved2 = 0;
> +
> + /* Compute the offset to the array of color indices. */
> + hdr.bfOffBits = ( DWORD ) sizeof( BITMAPFILEHEADER ) + pbih->biSize + pbih->biClrUsed * sizeof( RGBQUAD );
> +
> + /* Copy the BITMAPFILEHEADER into the .BMP file. */
> + if (!WriteFile(hf, (LPVOID)&hdr, sizeof(BITMAPFILEHEADER), (LPDWORD)&dwTmp, NULL))
> + {
> + return E_FAIL;
> + }
> +
> +
> + /* Copy the BITMAPINFOHEADER and RGBQUAD array into the file. */
> + if (!WriteFile(hf,
> + (LPVOID)pbih,
> + sizeof(BITMAPINFOHEADER) + pbih->biClrUsed * sizeof(RGBQUAD),
> + (LPDWORD)&dwTmp, NULL))
> + {
> + return E_FAIL;
> + }
> +
> +
> + /* Copy the array of color indices into the .BMP file. */
> + dwTotal = cb = pbih->biSizeImage;
> + hp = lpBits;
> +
> + if (!WriteFile(hf, (LPSTR)hp, (int)cb, (LPDWORD)&dwTmp, NULL))
> + {
> + return E_FAIL;
> + }
> +
> +
> + /* Now close the .BMP file. */
> + if (!CloseHandle(hf))
> + {
> + return E_FAIL;
> + }
> +
> + /* Free the memory reserved. */
> + GlobalFree((HGLOBAL)lpBits);
> +
> + return S_OK;
> +}
> +
> VOID FASTCALL
> DefWndScreenshot(HWND hWnd)
> {
> -
> + HDC hScreenDC = GetDC(0), hDC;
> + HBITMAP hBmp, hSaveBmp;
> +
> + DbgPrint("Screenshot\n");
> + hBmp = CreateCompatibleBitmap(
> + hScreenDC,
> + GetSystemMetrics(SM_CXSCREEN),
> + GetSystemMetrics(SM_CYSCREEN));
> + hDC = CreateCompatibleDC(hScreenDC);
> + hSaveBmp = SelectObject(hDC, hBmp);
> + BitBlt(
> + hDC,
> + 0,
> + 0,
> + GetSystemMetrics(SM_CXSCREEN),
> + GetSystemMetrics(SM_CYSCREEN),
> + hScreenDC,
> + 0,
> + 0,
> + SRCCOPY);
> + SaveBitmap(L"c:\\reactos\\screenshot.bmp", hDC, hBmp);
> + SelectObject(hDC, hSaveBmp);
> + DeleteObject(hBmp);
> + DeleteDC(hDC);
> }
>
> LRESULT STDCALL
> Index: subsys/win32k/objects/dib.c
> ===================================================================
> RCS file: /CVS/ReactOS/reactos/subsys/win32k/objects/dib.c,v
> retrieving revision 1.42
> diff -u -r1.42 dib.c
> --- subsys/win32k/objects/dib.c 19 Feb 2004 21:12:10 -0000 1.42
> +++ subsys/win32k/objects/dib.c 8 Mar 2004 20:27:00 -0000
> @@ -23,6 +23,7 @@
> #include <windows.h>
> #include <stdlib.h>
> #include <win32k/bitmaps.h>
> +#include <win32k/color.h>
> #include <win32k/debug.h>
> #include "../eng/handle.h"
> #include <ntos/minmax.h>
> @@ -259,7 +260,7 @@
> }
>
> // Converts a device-dependent bitmap to a DIB
> -#if 0
> +#if 1
> INT STDCALL NtGdiGetDIBits(HDC hDC,
> HBITMAP hBitmap,
> UINT StartScan,
> @@ -278,7 +279,7 @@
> UINT coloruse) /* [in] RGB or palette index */
> #endif
> {
> -#if 0
> +#if 1
> BITMAPINFO Info;
> BITMAPCOREHEADER *Core;
> PBITMAPOBJ BitmapObj;
> @@ -377,8 +378,7 @@
> Info.bmiHeader.biWidth == BitmapObj->bitmap.bmWidth &&
> Info.bmiHeader.biHeight == BitmapObj->bitmap.bmHeight &&
> Info.bmiHeader.biPlanes == BitmapObj->bitmap.bmPlanes &&
> - Info.bmiHeader.biBitCount == BitmapObj->bitmap.bmBitsPixel &&
> - 8 < Info.bmiHeader.biBitCount)
> + Info.bmiHeader.biBitCount == BitmapObj->bitmap.bmBitsPixel)
> {
> Info.bmiHeader.biSizeImage = BitmapObj->bitmap.bmHeight * BitmapObj->bitmap.bmWidthBytes;
> Status = MmCopyToCaller(Bits, BitmapObj->bitmap.bmBits, Info.bmiHeader.biSizeImage);
> @@ -390,7 +390,7 @@
> }
> RtlZeroMemory(&InfoWithBitFields, sizeof(InfoWithBitFields));
> RtlCopyMemory(&(InfoWithBitFields.Info), &Info, sizeof(BITMAPINFO));
> - if (BI_BITFIELDS == Info.bmiHeader.biCompression)
> + if (Info.bmiHeader.biCompression == BI_BITFIELDS)
> {
> DCObj = DC_LockDc(hDC);
> if (NULL == DCObj)
> @@ -419,6 +419,22 @@
> BITMAPOBJ_UnlockBitmap(hBitmap);
> return 0;
> }
> + if (Info.bmiHeader.biBitCount <= 8)
> + {
> + DCObj = DC_LockDc(hDC);
> + if (NULL == DCObj)
> + {
> + SetLastWin32Error(ERROR_INVALID_HANDLE);
> + BITMAPOBJ_UnlockBitmap(hBitmap);
> + return 0;
> + }
> + NtGdiGetPaletteEntries(
> + DCObj->w.hPalette,
> + 0,
> + 1 << Info.bmiHeader.biBitCount,
> + (LPPALETTEENTRY)&UnsafeInfo->bmiColors);
> + DC_UnlockDc(hDC);
> + }
> }
> else
> {
> @@ -516,7 +532,7 @@
> if (bits && lines)
> {
> /* If the bitmap object already have a dib section that contains image data, get the bits from it */
> - if(bmp->dib && bmp->dib->dsBm.bmBitsPixel >= 15 && info->bmiHeader.biBitCount >= 15)
> + if(bmp->dib)
> {
> /*FIXME: Only RGB dibs supported for now */
> unsigned int srcwidth = bmp->dib->dsBm.bmWidth, srcwidthb = bmp->dib->dsBm.bmWidthBytes;
> @@ -702,6 +718,44 @@
> }
> break;
>
> + case 8: /* 8 bpp dstDIB */
> + {
> + switch(bmp->dib->dsBm.bmBitsPixel) {
> + case 8: /* 8 bpp srcDIB -> 8 bpp dstDIB */
> + {
> + /* FIXME: BI_BITFIELDS not supported yet */
> + for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
> + memcpy(dbits, sbits, srcwidthb);
> + }
> + break;
> +
> + default: /* ? bit bmp -> 8 bit DIB */
> + DPRINT1("FIXME: 8 bit DIB %d bit bitmap\n",
> + bmp->bitmap.bmBitsPixel);
> + break;
> + }
> + }
> + break;
> +
> + case 4: /* 4 bpp dstDIB */
> + {
> + switch(bmp->dib->dsBm.bmBitsPixel) {
> + case 4: /* 4 bpp srcDIB -> 4 bpp dstDIB */
> + {
> + /* FIXME: BI_BITFIELDS not supported yet */
> + for (y = 0; y < lines; y++, dbits+=dstwidthb, sbits+=srcwidthb)
> + memcpy(dbits, sbits, srcwidthb);
> + }
> + break;
> +
> + default: /* ? bit bmp -> 4 bit DIB */
> + DPRINT1("FIXME: 4 bit DIB %d bit bitmap\n",
> + bmp->bitmap.bmBitsPixel);
> + break;
> + }
> + }
> + break;
> +
> default: /* ? bit DIB */
> DPRINT1("FIXME: Unsupported DIB depth %d\n", info->bmiHeader.biBitCount);
> break;