Pomelowu original, reprinted
It is easy to use the MFC to intercept the current screen and display it on the UI of your program. Take the dialog as an example, you can do the following functions in the execution of the plotted unit (such as onpaint):
Bool csrnshotdlg :: getMyscreen
CDC * PDC //
aims
DC
)
{
CDC DC;
Dc.created ("Display", NULL, NULL, NULL); //
screen
DC
CRECT ClientRect;
GetClientRect (ClientRect); //
Dialog rectangular area
PDC-> Bitblt (0, 0, //
starting point
ClientRect.Width (), clientRect.height (), //
Width Height
& DC, //
source
CDC
Object
0, 0,
//
Source location
Srcopy //
Replication method
);
Dc.deletedc (); return true;
}
Next, the screenshot of the screen is first converted to the grayscale map, and then display it. The formula of the conversion grayscale map is that the RGB value, R, G, and B are 3 color components, calculated:
Gray = r * 0.299 g * 0.587 b * 0.114
The gray then replaces the original 3 color component separately. To this place, I naturally think of using setpixel / getpixel. Because the DC is to be operated, of course, it cannot be directly operating directly on the DC inside above getMyScreen. For this purpose, the GetMyscreen is transformed, and for the ability to readability, add a CONVERTTOGRAY function to be responsible for conversion (different from the above code) The place is divided into red):
Void ConvertTograming (CDC * PDC)
{
For (int xx = 0; xx For (int yy = 0; yy { ColorRef crTemp = PDC-> GetPixel (XX, YY); Byte Pixelr = GtrValue (CRTEMP); BYTE PIXELG = GETGVALUE (CRTEMP); BYTE PIXELB = GetBValue (CRTEMP); Byte gray = (Byte) (Pixelr * 0.299 Pixelg * 0.587 Pixelb * 0.114); PDC-> SetPixelv (XX, YY, RGB (GRAY, GRAY, GRAY); } } Bool csrnshotdlg :: getMyscreen CDC * PDC // aims DC ) { CDC DC; Dc.created ("Display", NULL, NULL, NULL); // screen DC CRECT ClientRect; GetClientRect (ClientRect); // Dialog rectangular area CDC * Pmemdc = null; // compatible DC Pmemdc = New CDC; IF (! pmemdc) Return False; Pmemdc-> CreateCompatiPLEDC (& DC); ShowWindow (SW_HIDE); Pmemdc-> Bitblt (0, 0, ClientRect.Width (), clientRect.height (), & DC, 0, 0, SRCCOPY; Converttograming; PMEMDC); PDC-> Bitblt (0, 0, // starting point ClientRect.Width (), clientRect.height (), // Width Height Pmemdc // source CDC Object 0, 0, // Source location Srcopy // Replication method ); Pmemdc-> deletedc (); DELETE PMEMDC; dc.deletedc (); Return True; } The effect is out, but it is not perfect. In fact, I used SetPixelv to replace SetPixel, but the speed of display is still very slow, and the CPU usage is also very high. How to improve efficiency? Directly changed the bitmap data attached to the DC seems to be a good way. Below to the CBITMAP class object. Because it is a direct screen capture, you need to get the screen color depth with the cdc :: getDevicecaps with the Bitspixel parameter, because the storage mode of the bitmap of different color depths is different. Briefly illustrate: 16-bit color bitmap, each pixel for 2 bytes; 24-bit color, each pixel for 3 bytes; 32-bit color, each pixel for 4-byte storage space. We can use the cbitmap :: getBitmapBits function to get bitmap data, which is actually an array of BYTE. The structure of this array is the simplest of 24-bit color. As far as I have said 3 bytes per pixel, the subscript is b, g, r from low to high, and 32-bit color is similar, 4 bytes. There is only one alpha value. Below is the CONVERTTOGRAY24 for 24-bit color deep. #define bits24 (int) (1024 * 768 * 3) Void ConvertTograming24 (CBITMAP * PBMP) { LPBYTE LPBITS = NULL; LPBITS = new byte [bits24]; IF (! lpbits) Return; ZeromeMory (lpbits, bits24); PBMP-> GetBitmapBits (Bits24, LPBITS); For (int index = 0, j = 0, k = 0; index { Lpbits [index] = (byte) (0.114 * lpbits [index]); j = index 1; k = index 2; LPBITS [J] = (BYTE) (0.587 * lpbits [j]); LPBITS [K] = (Byte) (0.299 * lpbits [k]); LPBITS [INDEX] = LPBITS [J] LPBITS [K]; LPBITS [J] = LPBITS [INDEX]; LPBITS [K] = LPBITS [INDEX]; INDEX = K; } PBMP-> setBitmapbits (Bits24, LPBITS); DELETE [] lpbits; } When GetDeviceCaps (Bitspixel) returns 16, there are two cases: 16-bit color and 15 color. In the case of 16-bit color, the bitmap array uses 2 bytes to save data, where the low to the low position is B, G, R this 3 color component bits 5: 6: 5. Need to use the bit operation to get the color value of each component: #define getRvaluex (RGB) ((Byte) (RGB) & 0x1f) #define getgvaluex ((Byte) (((RGB) & 0x07E0 >> 5)) #define getBvaluex (RGB) ((BYTE) ((RGB) & 0xF800) >> 11)) #define RGBX (R, G, B) / ((Word) | ((Word) ((BYTE)) << 5)) | ((Word) (B)) << 11))) It is to be noted because the green component occupies 6bit, and its storage accuracy is twice the other two components, so the factor of the formula will change when performing successive calculations. (In addition, the use of 15-bit adapters is relatively small, and its storage rules are also occupied by 2 bytes, but the highest bit is meaningless, and the remaining 15 bits are assigned by 5: 5: 5, which is not discussed in detail.) #define bits16 (int) (1024 * 768 * 2) Void ConvertTogray16 (CBitmap * PBMP) { LPBYTE LPBITS = NULL; Word * wbits; LPBITS = New byte [bits16]; IF (! lpbits) Return; ZeromeMory (LPDIBITS, BITS16); PBMP-> GetBitmapBits (Bits16, LPBITS); For (int index = 0, j = 0, k = 0; index { WBITS = (Word *) (LPBITS INDEX); BYTE PIXELR = GETRVALUEX (* WBITS) * 2; BYTE PIXELG = GETGVALUEX (* WBITS); // Pay attention BYTE PIXELB = GetBValuex (* wbits) * 2; Byte gray = (Byte) (Pixelr * 0.299 Pixelg * 0.587 Pixelb * 0.114); * WBITS = RGBX (Gray / (Byte) 2, Gray, Gray / (Byte) 2); INDEX ; } PBMP-> setBitmapbits (BITS16, LPBITS); delete [] lpbits; } Finally, the third transformation getMyscreen: Bool csrnshotdlg :: getMyscreen CDC * PDC // aims DC ) { CDC DC; Dc.created ("Display", NULL, NULL, NULL); // screen DC CRECT ClientRect; GetClientRect (ClientRect); // Dialog rectangular area CDC * Pmemdc = null; // compatible DC CBitMap * pbmp = null; // Compatible bitmap Pmemdc = New CDC; IF (! pmemdc) Return False; Pmemdc-> CreateCompatiPLEDC (& DC); PBMP = New CBITMAP; IF (! PBMP) { Pmemdc-> deletedc (); DELETE PMEMDC; Return False; } PBMP-> CreateCompatibleBitmap (& DC, ClientRect.Width (), ClientRect.Height ()); PMEMDC-> SelectObject (PBMP); ShowWindow (SW_HIDE); Pmemdc-> Bitblt (0, 0, ClientRect.Width (), clientRect.height (), & DC, 0, 0, SRCCOPY; Switch (Pmemdc-> getDeviceCaps (Bitspixel)) { Case: 16 ConvertTograY16 (PBMP); Break; Case: 24 ConvertTograY24 (PBMP); Break; Case: 32 ConvertTograY32 (PBMP); // Not given Break; DEFAULT: PBMP-> deleteObject (); Pmemdc-> deletedc (); Delete PBMP; DELETE PMEMDC; dc.deletedc (); Return False; } PDC-> Bitblt (0, 0, // starting point ClientRect.Width (), clientRect.height (), // Width Height Pmemdc, // source CDC Object 0, 0, // Source location Srcopy // Replication method ); PBMP-> deleteObject (); Pmemdc-> deletedc (); Delete PBMP; DELETE PMEMDC; dc.deletedc (); Return True; } -------------------------------------------------- - Readable CONVERTBMP24TOBMP256 {file * fp = fopen ("test.bmp", "rb"); if (! Fp) return; BitmapFileHeader HDR; FREAD (& HDR, 1, SizeOf (HDR), FP); IF ((((((((((HDr.BFTYPE & 0xFF) == 'b') && ((hdr.bfType >> 8) == 'm'))) {fclose (fp); return;} BitmapInfoheader Bih; Fread (& BIH, 1, SIZEOF (BIH), FP); IF (BiH.BIBITCOUNT! = 24 || BiH.Bicompression! = 0) {fclose (fp); Return;} Unsigned char * pbuf = new unsigned char [bih.bisizeImage]; Fread (Pbuf, Bih.bisizeImage, Sizeof (unsigned char), fp); FILE * OUT = FOPEN ("Testout.BMP", "WB"); if (! Out) {delete [] PBUF; fclose (fp); Return;} unsigned char * pOutBuf = new unsigned char [bih.biWidth * bih.biHeight]; unsigned char * tmp = pBuf; unsigned char * tmp2 = pOutBuf; for (unsigned int i = 0; i Rgbquad q [256]; for (i = 0; i <256; i ) {q [i] .RGBRED = q [i] .RGBGreen = q [i] .RGBBBLUE = I; Q [i] .RGBRESERSERVED = 0 } Bih.biBitcount = 8; bih.bisizeImage = bih.biwidth * bih.biheight; Hdr.bfsize = sizeof (bitmapfileHeader) sizeof (bitmapinfoheader) sizeof (q) bih.bisizeImeimage; hdr.bfoffbits = sizeof (q); FWRITE (HDR, 1, SIZEOF (HDR), OUT); FWRITE (& BIH, 1, SIZEOF (BIH), OUT); FWRITE (q, 256, sizeof (rgbquad), OUT); FWRITE (Poutbuf, Bih.bisizeImage, SizeOf (unsigned char), out) DELETE [] Poutbuf; fclose (out); delete [] PBUF; fclose (fp);