📄 bmpform.prg
字号:
*!* 谢谢大家捧场。
*!* 保存任意一个窗口到一个bmp文件
*!* 你可以在command 窗口执行 bmpform.prg
*!* 不过最好在要保存的form调用这个子程序.
*!* bmpform.prg
********
DO decl
PRIVATE hMemDC, hMemBmp, lnWidth, lnHeight, lnBitsPerPixel,;
lnBytesPerScan, lcBFileHdr, lcBIHdr, lpBitsArray, lnBitsSize,;
lcRgbQuad, lnRgbQuadSize, lcBInfo, lnFileSize
STORE "" TO lcBIHdr, lcBInfo, lcRgbQuad
STORE 0 TO hMemDC, hMemBmp, lnWidth, lnHeight, lnFileSize,;
lnBitsPerPixel, lnBytesPerScan, lnRgbQuadSize, lpBitsArray, lnBitsSize
= MakeSnapshot()
= InitBitmapInfo()
= InitBitsArray()
#DEFINE DIB_RGB_COLORS 0
= GetDIBits (hMemDC, hMemBmp, 0, lnHeight, lpBitsArray,;
@lcBInfo, DIB_RGB_COLORS)
LOCAL lcFilename
**保存的文件名
lcFilename = "c:\myfile.bmp"
IF bmp2file (lcFilename)
ACTI SCREEN
? "file: ", lcFilename
? "Size: ", LTRIM(TRANS(lnFileSize, "999,999,999,999"))
? "Width: ", LTRIM(STR(lnWidth)) + " pixels"
? "Height: ", LTRIM(STR(lnHeight)) + " pixels"
? "Bits per pixel:", LTRIM(STR(lnBitsPerPixel))
ENDIF
= GlobalFree (lpBitsArray)
= DeleteObject (hMemBmp)
= DeleteDC (hMemDC)
RETURN && main
PROCEDURE InitBitmapInfo()
#DEFINE BI_RGB 0
#DEFINE RGBQUAD_SIZE 4 && RGBQUAD
#DEFINE BHDR_SIZE 40 && BITMAPINFOHEADER
* forcing 24-bit format
lnBitsPerPixel = 24
lnBytesPerScan = lnWidth * 3
* line width should be DWORD-aligned (4 bytes)
* important for 16- and 24-bit color palettes
IF Mod(lnBytesPerScan, 4) <> 0
lnBytesPerScan = lnBytesPerScan + 4 - Mod(lnBytesPerScan, 4)
ENDIF
* initializing BitmapInfoHeader structure
lcBIHdr = num2dword(BHDR_SIZE) + num2dword(lnWidth) +;
num2dword(lnHeight) + num2word(1) + num2word(lnBitsPerPixel) +;
num2dword(BI_RGB) + num2dword(0) + num2dword(0) + num2dword(0) +;
num2dword(0) + num2dword(0)
* creating a buffer for the color table
IF lnBitsPerPixel <= 8
lnRgbQuadSize = (2^lnBitsPerPixel) * RGBQUAD_SIZE
lcRgbQuad = Repli(Chr(0), lnRgbQuadSize)
ELSE
lnRgbQuadSize = 0
lcRgbQuad = ""
ENDIF
* merging two pieces together
lcBInfo = lcBIHdr + lcRgbQuad
RETURN
PROCEDURE InitBitsArray()
#DEFINE GMEM_FIXED 0
lnBitsSize = lnHeight * lnBytesPerScan
lpBitsArray = GlobalAlloc (GMEM_FIXED, lnBitsSize)
= ZeroMemory (lpBitsArray, lnBitsSize)
FUNCTION bmp2file (lcTargetFile)
* store all gathered pieces to a disk file
#DEFINE GENERIC_WRITE 1073741824 && 0x40000000
#DEFINE FILE_SHARE_WRITE 2
#DEFINE CREATE_ALWAYS 2
#DEFINE FILE_ATTRIBUTE_NORMAL 128
#DEFINE INVALID_HANDLE_value -1
#DEFINE BFHDR_SIZE 14 && BITMAPFILEHEADER
LOCAL hFile, lnOffBits
* resulting BMP file size
lnFileSize = BFHDR_SIZE + BHDR_SIZE + lnRgbQuadSize + lnBitsSize
* offset to the bitmap bits
lnOffBits = BFHDR_SIZE + BHDR_SIZE + lnRgbQuadSize
* BMP file header
lcBFileHdr = "BM" + num2dword(lnFileSize) +;
num2dword(0) + num2dword(lnOffBits)
* target file handle
hFile = CreateFile (lcTargetFile,;
GENERIC_WRITE,;
FILE_SHARE_WRITE, 0,;
CREATE_ALWAYS,;
FILE_ATTRIBUTE_NORMAL, 0)
IF hFile <> INVALID_HANDLE_value
* a straightforward process of storing block after block:
= String2File (hFile, @lcBFileHdr) && BitmapFileHeader
= String2File (hFile, @lcBInfo) && BitmapInfo
= Ptr2File (hFile, lpBitsArray, lnBitsSize) && bitmap data
= CloseHandle (hFile)
RETURN .T.
ELSE
= MessageB ("Unable to create file: " + lcTargetFile)
RETURN .F.
ENDIF
PROCEDURE String2File (hFile, lcBuffer)
* appends string buffer to a file
DECLARE INTEGER WriteFile IN kernel32;
INTEGER hFile, STRING @lpBuffer, INTEGER nBt2Write,;
INTEGER @lpBtWritten, INTEGER lpOverlapped
= WriteFile (hFile, @lcBuffer, Len(lcBuffer), 0, 0)
RETURN
PROCEDURE Ptr2File (hFile, lnPointer, lnBt2Write)
* appends memory block to a file
DECLARE INTEGER WriteFile IN kernel32;
INTEGER hFile, INTEGER lpBuffer, INTEGER nBt2Write,;
INTEGER @lpBtWritten, INTEGER lpOverlapped
= WriteFile (hFile, lnPointer, lnBt2Write, 0, 0)
RETURN
PROCEDURE MakeSnapshot()
#DEFINE SRCCOPY 13369376
LOCAL hwnd, hdc, hSavedBitmap
hwnd = GetFocus()
hdc = GetWindowDC(hwnd)
= GetWinRect(hwnd, @lnWidth, @lnHeight)
hMemDC = CreateCompatibleDC (hdc)
hMemBmp = CreateCompatibleBitmap (hdc, lnWidth, lnHeight)
hSavedBitmap = SelectObject (hMemDC, hMemBmp)
= BitBlt (hMemDC, 0,0, lnWidth,lnHeight, hdc, 0,0, SRCCOPY)
= SelectObject (hMemDC, hSavedBitmap)
= ReleaseDC (hwnd, hdc)
RETURN
PROCEDURE GetWinRect(hwnd, lnWidth, lnHeight)
#DEFINE MAX_DWORD 4294967295 && 0xffffffff
LOCAL lpRect, lnLeft, lnTop, lnRight, lnBottom
lpRect = Repli(Chr(0), 16)
= GetWindowRect (hwnd, @lpRect)
lnLeft = buf2dword(SUBSTR(lpRect, 1,4))
lnTop = buf2dword(SUBSTR(lpRect, 5,4))
lnRight = buf2dword(SUBSTR(lpRect, 9,4))
lnBottom = buf2dword(SUBSTR(lpRect, 13,4))
IF lnLeft > lnRight
lnLeft = lnLeft - MAX_DWORD
ENDIF
IF lnTop > lnBottom
lnTop = lnTop - MAX_DWORD
ENDIF
lnWidth = lnRight - lnLeft
lnHeight = lnBottom - lnTop
RETURN
FUNCTION num2dword (lnvalue)
#DEFINE m0 256
#DEFINE m1 65536
#DEFINE m2 16777216
LOCAL b0, b1, b2, b3
b3 = Int(lnvalue/m2)
b2 = Int((lnvalue - b3*m2)/m1)
b1 = Int((lnvalue - b3*m2 - b2*m1)/m0)
b0 = Mod(lnvalue, m0)
RETURN Chr(b0)+Chr(b1)+Chr(b2)+Chr(b3)
FUNCTION num2word (lnvalue)
RETURN Chr(MOD(m.lnvalue,256)) + CHR(INT(m.lnvalue/256))
FUNCTION buf2dword (lcBuffer)
RETURN Asc(SUBSTR(lcBuffer, 1,1)) + ;
Asc(SUBSTR(lcBuffer, 2,1)) * 256 +;
Asc(SUBSTR(lcBuffer, 3,1)) * 65536 +;
Asc(SUBSTR(lcBuffer, 4,1)) * 16777216
FUNCTION buf2word (lcBuffer)
RETURN Asc(SUBSTR(lcBuffer, 1,1)) + ;
Asc(SUBSTR(lcBuffer, 2,1)) * 256
PROCEDURE decl
DECLARE INTEGER GetDIBits IN gdi32;
INTEGER hdc, INTEGER hbmp, INTEGER uStartScan,;
INTEGER cScanLines, INTEGER lpvBits, STRING @lpbi,;
INTEGER uUsage
DECLARE INTEGER GlobalAlloc IN kernel32 INTEGER wFlags, INTEGER dwBytes
DECLARE INTEGER GetWindowRect IN user32 INTEGER hwnd, STRING @lpRect
DECLARE INTEGER SelectObject IN gdi32 INTEGER hdc, INTEGER hObject
DECLARE INTEGER ReleaseDC IN user32 INTEGER hwnd, INTEGER hdc
DECLARE INTEGER DeleteDC IN gdi32 INTEGER hdc
DECLARE INTEGER GetFocus IN user32
DECLARE INTEGER GetWindowDC IN user32 INTEGER hwnd
DECLARE INTEGER GlobalFree IN kernel32 INTEGER hMem
DECLARE INTEGER DeleteObject IN gdi32 INTEGER hObject
DECLARE INTEGER CreateCompatibleDC IN gdi32 INTEGER hdc
DECLARE INTEGER CloseHandle IN kernel32 INTEGER hObject
DECLARE RtlZeroMemory IN kernel32 As ZeroMemory;
INTEGER dest, INTEGER numBytes
DECLARE INTEGER CreateCompatibleBitmap IN gdi32;
INTEGER hdc, INTEGER nWidth, INTEGER nHeight
DECLARE INTEGER BitBlt IN gdi32;
INTEGER hDestDC, INTEGER x, INTEGER y,;
INTEGER nWidth, INTEGER nHeight, INTEGER hSrcDC,;
INTEGER xSrc, INTEGER ySrc, INTEGER dwRop
DECLARE INTEGER CreateFile IN kernel32;
STRING lpFileName, INTEGER dwDesiredAccess,;
INTEGER dwShareMode, INTEGER lpSecurityAttr,;
INTEGER dwCreationDisp, INTEGER dwFlagsAndAttrs,;
INTEGER hTemplateFile
*** The structures used in this code:
*| typedef struct tagBITMAPINFOHEADER{
*| DWORD biSize; 0:4
*| LONG biWidth; 4:4
*| LONG biHeight; 8:4
*| WORD biPlanes; 12:2
*| WORD biBitCount; 14:2
*| DWORD biCompression; 16:4
*| DWORD biSizeImage; 20:4
*| LONG biXPelsPerMeter; 24:4
*| LONG biYPelsPerMeter; 28:4
*| DWORD biClrUsed; 32:4
*| DWORD biClrImportant; 36:4 = 40 bytes
*| } BITMAPINFOHEADER, *PBITMAPINFOHEADER
*| typedef struct tagRGBQUAD {
*| BYTE rgbBlue;
*| BYTE rgbGreen;
*| BYTE rgbRed;
*| BYTE rgbReserved;
*| } RGBQUAD; total 4 bytes
*| typedef struct tagBITMAPINFO {
*| BITMAPINFOHEADER bmiHeader;
*| RGBQUAD bmiColors[1];
*|} BITMAPINFO, *PBITMAPINFO;
*| typedef struct tagBITMAPFILEHEADER {
*| WORD bfType; 0:2
*| DWORD bfSize; 2:4
*| WORD bfReserved1; 6:2
*| WORD bfReserved2; 8:2
*| DWORD bfOffBits; 10:4 = 14 bytes
*| } BITMAPFILEHEADER, *PBITMAPFILEHEADER;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -