您的位置:首页 > 其它

屏幕截图小软件的编写——WINDOWS API

2016-12-03 22:36 399 查看
近期在学习windows api编程,完全模仿的学习了,熟悉windows api和纯windows api编程

屏幕截图步骤:

1.如何捕获屏幕

2.捕获屏幕后怎么做到选定区域

3.选定区域后将图片写入剪贴板

具体还有很多细节需要考虑,如选定区域需要用不同颜色的画笔,如何知道区域被选择了......

主要代码如下,核心都在窗口回调函数中,不详细解释,几个重要的API函数在后面说明

//函数前置声明
void CaptureScreen();
void WriteDateToClipBoard();
// 全局变量:
HINSTANCE hInst; // 当前实例
WCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本
WCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名

int screenW, screenH;
HDC g_memDC; //全局内存DC,存储位图
RECT rect; //截图矩形区域
bool isSelect=FALSE, isDrawing=FALSE;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;

//画刷
LOGBRUSH brush;
brush.lbStyle = BS_NULL;
HBRUSH hBrush = CreateBrushIndirect(&brush);
//画笔
LOGPEN pen;
POINT penWidth;
penWidth.x = 2;
penWidth.y = 2;
pen.lopnColor = 0x0000FFFF;
pen.lopnStyle = BS_SOLID;
pen.lopnWidth = penWidth;
HPEN hPen = CreatePenIndirect(&pen);

//窗口信息
WINDOWINFO windowInfo;
windowInfo.cbSize = sizeof(WINDOWINFO);

switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// 分析菜单选择:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;

case WM_CREATE:
CaptureScreen();
break;

case WM_PAINT:
{

hdc = BeginPaint(hWnd, &ps);

// TODO: 在此处添加使用 hdc 的任何绘图代码...
HDC memDC = CreateCompatibleDC(hdc);
HBITMAP hbmp = CreateCompatibleBitmap(hdc, screenW, screenH);
SelectObject(memDC, hbmp);

BitBlt(memDC, 0, 0, screenW, screenH, g_memDC, 0, 0, SRCCOPY);
SelectObject(memDC, hPen);
SelectObject(memDC, hBrush);

if (isDrawing || isSelect)
{
BitBlt(memDC, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, g_memDC, rect.left, rect.top, SRCCOPY);
Rectangle(memDC, rect.left, rect.top, rect.right, rect.bottom);
}

BitBlt(hdc, 0, 0, screenW, screenH, memDC, 0, 0, SRCCOPY);

DeleteObject(hbmp);
DeleteObject(memDC);

EndPaint(hWnd, &ps);
}
break;

case WM_LBUTTONDOWN:
if (!isSelect)
{
POINT point;
GetCursorPos(&point);
//获取矩形区域起点
rect.top = point.y;
rect.left = point.x;
rect.right = point.x;
rect.bottom = point.y;

isDrawing = TRUE;
InvalidateRgn(hWnd, NULL, FALSE);
}

break;

case WM_LBUTTONUP:
if (isDrawing&&!isSelect)
{
isDrawing = FALSE;
POINT point;
GetCursorPos(&point);
//获取矩形区域终点
rect.right = point.x;
rect.bottom = point.y;

isSelect = TRUE;

InvalidateRgn(hWnd, NULL, FALSE);
}
break;

case WM_LBUTTONDBLCLK:
if (isSelect)
{
WriteDateToClipBoard();
InvalidateRgn(hWnd, NULL, FALSE);
ShowWindow(hWnd, SW_MINIMIZE);
}

isSelect = FALSE;
isDrawing = FALSE;

break;

case WM_MOUSEMOVE:
//鼠标移动实时捕获鼠标位置
if (isDrawing&&!isSelect)
{
POINT pt;
GetCursorPos(&pt);
rect.right = pt.x;
rect.bottom = pt.y;
InvalidateRgn(hWnd, 0, false);
}

break;

case WM_DESTROY:
PostQuitMessage(0);
break;

default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}

void CaptureScreen()
{
HDC disDC = ::CreateDC(L"DISPLAY", 0, 0, 0);//截取整个屏幕
screenW = GetDeviceCaps(disDC, HORZRES);
screenH = GetDeviceCaps(disDC, VERTRES);

//创建与DC相兼容的内存DC和位图
g_memDC = CreateCompatibleDC(disDC);
HBITMAP hbmp = CreateCompatibleBitmap(disDC, screenW, screenH);
SelectObject(g_memDC, hbmp);
BitBlt(g_memDC, 0, 0, screenW, screenH, disDC, 0, 0, SRCCOPY);

DeleteDC(disDC);
DeleteObject(hbmp);
}

void WriteDateToClipBoard()
{
HDC hMemDC, hdc;
HBITMAP hMemBmp, hbmp;
//计算矩形区域的长和宽
int width, height;
width = rect.right - rect.left;
height = rect.bottom - rect.top;

//创建相兼容的内存DC和位图
hdc = CreateDC(L"DISPLAY", 0, 0, 0);
hMemDC = CreateCompatibleDC(hdc);
hbmp = CreateCompatibleBitmap(hdc, width, height);

hMemBmp = (HBITMAP)SelectObject(hMemDC, hbmp);
BitBlt(hMemDC, 0, 0, width, height, g_memDC, rect.left, rect.bottom, SRCCOPY);
hbmp = (HBITMAP)SelectObject(hMemDC, hMemBmp);

DeleteDC(hdc);
DeleteDC(hMemDC);

//清空,写入,关闭剪贴板
if (OpenClipboard(0))
{
EmptyClipboard();
SetClipboardData(CF_BITMAP, hbmp);
CloseClipboard();
}

DeleteObject(hbmp);
DeleteObject(hMemBmp);
}窗口风格要是POPUP的,这样才能覆盖整个屏幕

DC,即device context,学会使用DC和内存DC传送位图,虽然还不是很理解,先抄,模仿别人的......
按我现在的理解,DC相当于一个容器,可以将画刷画笔等工具放入其中.....

SelectObject函数说明,摘录自MSDN

HGDIOBJ SelectObject(
_In_ HDC     hdc,
_In_ HGDIOBJ hgdiobj
);




Parameters

hdc [in]
A handle to the DC.
hgdiobj [in]
A handle to the object to be selected.

参数只能是这几个GDI对象Bitmap ,Brush ,Font,Pen,Region

初次接触windows api编程,所有API 都不熟悉,完全copy加模仿,此程序运行后只能截图一次

以后接触多了后再来写,改进思想如下:

1.能够对屏幕进行实时截图,即软件运行时可以在任意时刻对屏幕截图

2.能够撤销之前截图
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐