/* ************************************
* PrtSrcn.c 截屏
//http://blog.csdn.net/fsjaky
**************************************/
/* 頭文件 */
#include <windows.h>
/* 常量定義 */
#define PALVERSION 0x300
#define CAP_SHOW_MODE_STRTCH 1
#define CAP_SHOW_MODE_NOSTRTCH 0
/* 全局變量 */
HBITMAP ghBitmap = NULL;
RECT rectShow;
char *filename,*filenametemp;
// 修改這裏截取不同的窗口,如果爲NULL,則截取屏幕
LPSTR szCaptureWindowName = "攝像頭錄像大師";
/* 函數申明 */
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);
HBITMAP ScreenCapture(LPSTR filename ,WORD BitCount,LPRECT lpRect);
VOID DoPaint(HWND hWnd, DWORD dwMode);
/*************************************
* DWORD WINAPI WinMain(HINSTANCE hinstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
* 功能 截屏,保存爲文件,並顯示在窗口上
*
**************************************/
INT WINAPI WinMain(HINSTANCE hinstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
WNDCLASSEX wcx;
HWND hwnd;
MSG msg;
WORD wport = 80;
BOOL fGotMessage;
HWND hwndCap = NULL;
// 截取全屏幕還是窗口
if(szCaptureWindowName != NULL)
{
hwndCap = FindWindow(NULL,"攝像頭錄像大師");
// 獲取窗口的RECT,可自行修改,獲取屏幕中的任意區域
if(!GetWindowRect(hwndCap,&rectShow))
{
MessageBox(NULL,"Can not find window to capture", "erroe",MB_OK);
return 0;
}
}
// 註冊窗口類,並創建窗口,用於顯示截取的位圖
wcx.cbSize = sizeof(wcx);
wcx.style = CS_HREDRAW | CS_VREDRAW;
wcx.lpfnWndProc = MainWndProc;
wcx.cbClsExtra = 0;
wcx.cbWndExtra = 0;
wcx.hInstance = hinstance;
wcx.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION));
wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
wcx.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcx.lpszMenuName = NULL;
wcx.lpszClassName = "MainWClass";
wcx.hIconSm = NULL;
if( !RegisterClassEx(&wcx))
return 1;
// 創建窗口
hwnd = CreateWindow(
"MainWClass",
"CAP",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
WS_MAXIMIZE | WS_POPUPWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
(HWND) NULL, (HMENU) NULL, hinstance, (LPVOID) NULL);
if (!hwnd)
return 1;
// 截取屏幕,可根據需要設置不同的參數,這裏只演示截取特定窗口。
ghBitmap = ScreenCapture("D:\\Screen\.jpg" ,32, &rectShow); //保存路徑
//ghBitmap = ScreenCapture(filename ,32, &rectShow); //保存路徑
// 顯示
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while ((fGotMessage = GetMessage(&msg, (HWND) NULL, 0, 0)) != 0 && fGotMessage != -1)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
UNREFERENCED_PARAMETER(lpCmdLine);
}
LRESULT CALLBACK MainWndProc(
HWND hwnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg)
{
case WM_PAINT:
// 顯示截取的屏幕
DoPaint(hwnd,CAP_SHOW_MODE_STRTCH);
break;
case WM_DESTROY:
// 創建的BITMAP對象需要刪除,以釋放資源
DeleteObject(ghBitmap);
ExitProcess(0);
break;
default:
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
/*************************************
* VOID DoPaint(HWND hWnd, DWORD dwMode)
* 功能 將位圖(全局變量ghBitmap)顯示在界面上
*
* 參數 HWND hWnd,用於顯示位圖的窗口
* DWORD dwMode,模式,是否拉申
*
* 無返回值
**************************************/
VOID DoPaint(HWND hWnd, DWORD dwMode)
{
PAINTSTRUCT ps;
RECT rect;
HDC hdcMem;
BITMAP bm;
// BeginPaint
HDC hDC = BeginPaint(hWnd, &ps);
// 獲取窗口的Client區域,用於顯示位圖
GetClientRect(hWnd, &rect);
// 設置拉申模式
SetStretchBltMode(hDC, HALFTONE);
// 將BITMAP對象選擇入內存DC
hdcMem = CreateCompatibleDC(hDC);
SelectObject(hdcMem, ghBitmap);
if (ghBitmap)
{
// 獲取DIB屬性
if (GetObject(ghBitmap, sizeof(BITMAP), &bm))
{
// 判斷參數示:是否根據顯示窗口大小拉申位圖
// 採用不同的方面將內存DC StretchBl t至窗口Client區域DC
if(dwMode == CAP_SHOW_MODE_STRTCH)
{
StretchBlt(hDC, 0, 0, rect.right, rect.bottom,
hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
}
else
{
// 不拉伸,計算顯示的位置,將其顯示在Client的中央
INT ixStart = (rect.right - rect.left - bm.bmWidth)/2;
INT iyStart = (rect.bottom - rect.top - bm.bmHeight)/2;
ixStart = ixStart < 0 ? 0 : ixStart;
iyStart = iyStart < 0 ? 0 : iyStart;
BitBlt(hDC, 0, 0, rect.right, rect.bottom,
hdcMem,-ixStart,-iyStart, SRCCOPY);
}
DeleteDC(hdcMem);
}
}
// 如果沒有位圖,則使用Brush填充
else
{
PatBlt(hDC, 0, 0, rect.right, rect.bottom, BLACKNESS);
}
// EndPaint
EndPaint(hWnd, &ps);
}
/*************************************
* HBITMAP ScreenCapture(LPSTR filename ,WORD BitCount,LPRECT lpRect);
* 功能 截取指定區域的屏幕,並保存爲文件
*
* 參數 LPSTR filename 保存位圖文件的文件路徑,如果爲NULL,則不保存
* WORD BitCount Bit深度,用於表示一個像素點所使用的數據長度
* LPRECT lpRect 所需截取的屏幕區域,如果爲NULL,則獲取全屏幕
*
* 返回 HBITMAP 所截取的位圖對象
**************************************/
HBITMAP ScreenCapture(LPSTR filename ,WORD BitCount,LPRECT lpRect)
{
HBITMAP hBitmap;
// 顯示器屏幕DC
HDC hScreenDC = CreateDC("DISPLAY", NULL, NULL, NULL);
HDC hmemDC = CreateCompatibleDC(hScreenDC);
// 顯示器屏幕的寬和高
int ScreenWidth = GetDeviceCaps(hScreenDC, HORZRES);
int ScreenHeight = GetDeviceCaps(hScreenDC, VERTRES);
// 舊的BITMAP,用於與所需截取的位置交換
HBITMAP hOldBM;
// 保存位圖數據
PVOID lpvpxldata;
// 截屏獲取的長寬及起點
INT ixStart;
INT iyStart;
INT iX;
INT iY;
// 位圖數據大小
DWORD dwBitmapArraySize;
// 幾個大小
DWORD nBitsOffset;
DWORD lImageSize ;
DWORD lFileSize ;
// 位圖信息頭
BITMAPINFO bmInfo;
// 位圖文件頭
BITMAPFILEHEADER bmFileHeader;
// 寫文件用
HANDLE hbmfile;
DWORD dwWritten;
// 如果LPRECT 爲NULL 截取整個屏幕
if(lpRect == NULL)
{
ixStart = iyStart = 0;
iX = ScreenWidth;
iY =ScreenHeight;
}
else
{
ixStart = lpRect->left;
iyStart = lpRect->top;
iX = lpRect->right - lpRect->left;
iY = lpRect->bottom - lpRect->top;
}
// 創建BTIMAP
hBitmap = CreateCompatibleBitmap(hScreenDC, iX, iY);
// 將BITMAP選擇入內存DC。
hOldBM = (HBITMAP)SelectObject(hmemDC, hBitmap);
// BitBlt屏幕DC到內存DC,根據所需截取的獲取設置參數
BitBlt(hmemDC, 0, 0, iX, iY, hScreenDC, ixStart, iyStart, SRCCOPY);
// 將舊的BITMAP對象選擇回內存DC,返回值爲被替換的對象,既所截取的位圖
hBitmap = (HBITMAP)SelectObject(hmemDC, hOldBM);
if(filename == NULL)
{
DeleteDC( hScreenDC);
DeleteDC(hmemDC);
return hBitmap;
}
// 爲位圖數據申請內存空間
dwBitmapArraySize = ((((iX*32) + 31) & ~31)>> 3)* iY;
lpvpxldata = HeapAlloc(GetProcessHeap(),HEAP_NO_SERIALIZE,dwBitmapArraySize);
ZeroMemory(lpvpxldata,dwBitmapArraySize);
// 添充 BITMAPINFO 結構
ZeroMemory(&bmInfo,sizeof(BITMAPINFO));
bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmInfo.bmiHeader.biWidth = iX;
bmInfo.bmiHeader.biHeight = iY;
bmInfo.bmiHeader.biPlanes = 1;
bmInfo.bmiHeader.biBitCount = BitCount;
bmInfo.bmiHeader.biCompression = BI_RGB;
// 添充 BITMAPFILEHEADER 結構
ZeroMemory(&bmFileHeader,sizeof(BITMAPFILEHEADER));
nBitsOffset = sizeof(BITMAPFILEHEADER) + bmInfo.bmiHeader.biSize;
lImageSize =
((((bmInfo.bmiHeader.biWidth * bmInfo.bmiHeader.biBitCount) + 31) & ~31)>> 3)
* bmInfo.bmiHeader.biHeight;
lFileSize = nBitsOffset + lImageSize;
bmFileHeader.bfType = 'B'+('M'<<8);
bmFileHeader.bfSize = lFileSize;
bmFileHeader.bfOffBits = nBitsOffset;
// 獲取DIB用於寫入到文件
GetDIBits(hmemDC, hBitmap, 0, bmInfo.bmiHeader.biHeight,
lpvpxldata, &bmInfo, DIB_RGB_COLORS);
// 寫文件
hbmfile = CreateFile(filename,
GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hbmfile == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,"create file error","error",MB_OK);
}
WriteFile(hbmfile,&bmFileHeader,sizeof(BITMAPFILEHEADER),&dwWritten,NULL);
WriteFile(hbmfile,&bmInfo,sizeof(BITMAPINFO),&dwWritten,NULL);
WriteFile(hbmfile,lpvpxldata,lImageSize,&dwWritten,NULL);
CloseHandle(hbmfile);
// 釋放內存,清除不同的DC。
// 這裏沒有刪除BITMAP對象,需在顯示完成後刪除
HeapFree(GetProcessHeap(),HEAP_NO_SERIALIZE,lpvpxldata);
ReleaseDC(0, hScreenDC);
DeleteDC(hmemDC);
return hBitmap;
}