屏幕截图小软件的编写——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
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.能够撤销之前截图
屏幕截图步骤:
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.能够撤销之前截图
相关文章推荐
- C#软件开发实例.私人订制自己的屏幕截图工具(十)在截图中包含鼠标指针形状
- 浅析如何用C#.NET做屏幕截图软件以及注册全局快捷键(下)
- C#软件开发实例.私人订制自己的屏幕截图工具(七)添加放大镜的功能
- C#软件开发实例.个人定制自己的屏幕抓图工具(八)加入了截图功能键盘
- C#软件开发实例.私人订制自己的屏幕截图工具(四)基本截图功能实现
- Greenshot绿色免费屏幕截图软件修改版
- C#软件开发实例.私人订制自己的屏幕截图工具(七)加入放大镜的功能
- Java制作屏幕截图软件(还可以保存到剪切板内)
- Java制作屏幕截图软件(还可以保存到剪切板内)
- C#软件开发实例.私人订制自己的屏幕截图工具(八)添加键盘操作截图的功能
- 屏幕截图软件说明
- C#软件开发实例.私人订制自己的屏幕截图工具(十)在截图中包含鼠标指针形状
- C#软件开发实例.私人订制自己的屏幕截图工具(三)托盘图标及菜单的实现
- 精品软件 推荐 Ashampoo Snap 7.0.10 - 精美、实用的屏幕截图软件
- C#软件开发实例.私人订制自己的屏幕截图工具(九)使用自定义光标,QQ截图时的光标
- C#软件开发实例.私人订制自己的屏幕截图工具——放大镜的功能代码优化
- C#软件开发实例.私人订制自己的屏幕截图工具(二)创建项目、注册热键、显示截图主窗口
- C#软件开发实例.私人订制自己的屏幕截图工具(一)功能概览
- C#软件开发实例.私人订制自己的屏幕截图工具(一)功能概览
- Ubuntu 14.04下安装功能强大的屏幕截图软件 Shutter