Win32 SDK 编写截图小工具
开发环境为windows xp,vc6
主要方案为,创建一个主窗口,不进行截图的时候将其隐藏,并在托盘区创建小图标,截图时使窗口全屏透明,捕捉鼠标行为截图保存,再使窗口隐藏。
以下根据主要步骤将核心内容点出:
(1)注册窗口类时,将背景色定为黑色,以使截图时有灰暗的效果
ATOM MyRegisterClass(PWNDCLASSEX wcex,HINSTANCE hInstance)
{...wcex->hCursor = LoadCursor(NULL, IDC_CROSS);wcex->hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);...return RegisterClassEx(wcex);
}
(2)创建窗口时,用到两个扩展风格,WS_EX_LAYERED,WS_EX_TOOLWINDOW
前者是将窗口透明化必须设置的窗口风格,后者使窗口成为一个工具窗口,不显示在任务栏中。
HWND hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOOLWINDOW, "MYSCREENSHOT", 0, WS_POPUP,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
(3)注册两套热键,用RegisterHotKey
函数原型为:
BOOL RegisterHotKey(HWND hWnd, // handle to windowint id, // hot key identifierUINT fsModifiers, // key-modifier optionsUINT vk // virtual-key code
);
RegisterHotKey(hWnd, 1346, MOD_ALT | MOD_CONTROL, 65);RegisterHotKey(hWnd, 1347, MOD_CONTROL, 222);
65为A的虚键码,222为' or " 的虚键码,适用于左手与右手。
这样当按下这两个组合键时,窗口会受到一个 WM_HOTKEY 消息,其中,lParam的低位字显示了alt或是control键是否被按下,高位字为虚键码,那么我们只需要在窗口函数中处理该消息,发送一个命令消息开始截图:
case WM_HOTKEY:{if(HIWORD(lParam) == 65 || HIWORD(lParam) == 222)SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDM_RUN, 0), 0);}break;
IDM_RUN 是一个开始截图的命令消息
注意窗口销毁时注销热键,在WM_DESTROY中
UnregisterHotKey(hWnd, 1346);UnregisterHotKey(hWnd, 1347);
(4)在不进行截图时,将窗口最小化到托盘,这里要用到 API函数Shell_NotifyIcon和结构体NOTIFYICONDATA,先来看下NOTIFYICONDATA:
typedef struct _NOTIFYICONDATA {
DWORD cbSize;
HWND hWnd;
UINT uID;
UINT uFlags;
UINT uCallbackMessage;
HICON hIcon;
char szTip[64];
} NOTIFYICONDATA, *PNOTIFYICONDATA;
其中,
cbSize : 结构的长度,用“位”来做单位。一般在程序中,我们用(DWORD)sizeof(NOTIFYICONDATA) 给它赋值。
HWnd : 一个句柄,如果对托盘中的图标进行操作,相应的消息就传给这个句柄所代表的窗口。自然了,大多数情况下是this->m_hWnd喽。
uID : 在工程中定义的图标ID
uFlags : 这个成员标志着其他哪些成员的数据是有效的,分别为NIF_ICON, NIF_MESSAGE, NIF_TIP,分别代表着数据有效的成员是hIcon, uCallbackMessage, szTip。当然,三个值可以用“|”联系到一起。下面分别对涉及到的成员进行阐述
hIcon : 要增加,删除或修改的图标句柄。如果只知道个uID, 一般可能会用函数LoadIcon来得到句柄。例如LoadIcon ( AfxGetInstanceHandle() ,MAKEINTRESOURCE (IDR_MAINFRAME) )。
uCallbackMessage : 这在对托盘区的操作中,是比较重要的数据成员。这是个消息标志,当用鼠标对托盘区相应图标进行操作的时候,就会传递消息给Hwnd所代表的窗口。所以说,在uFlags中,一般都得标志它有效。这里一般都是自定义的消息。
szTip : 鼠标移动到托盘图标上时的提示文字。
我们这里用一个自定义消息来接收托盘图标的消息:
#define MY_ICON_MESSAGE (WM_USER+1)
...
NOTIFYICONDATA g_nid;
...
g_nid.uCallbackMessage = MY_ICON_MESSAGE;
那么此时,第三个参数可以随便填。接下来处理这个消息,其中,wParam接收的是图标的ID,而lParam接收的是鼠标的行为
case MY_ICON_MESSAGE:{switch(lParam){case WM_RBUTTONDOWN:{HMENU hMenu = CreateMenu();HMENU hPopupMenu = CreateMenu();AppendMenu(hMenu, MF_POPUP, (UINT_PTR)hPopupMenu, 0);AppendMenu(hPopupMenu, MF_STRING, IDM_RUN, "&Run");AppendMenu(hPopupMenu, MF_SEPARATOR, 0, 0);AppendMenu(hPopupMenu, MF_STRING, IDM_QUIT, "&Quit");POINT point;GetCursorPos(&point);SetForegroundWindow(hWnd);TrackPopupMenu(hPopupMenu, TPM_LEFTALIGN, point.x, point.y, 0, hWnd, 0);}break;case WM_LBUTTONDBLCLK:SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDM_RUN, 0), 0);break;}}break;
右键单击时,弹出一个菜单,有两个选项,运行和退出,当左键双击时,与运行截图有相同的作用,发送一个IDM_RUN 的命令消息。注意,TrackPopupMenu之前的SetForegroundWindow是必要的,没有这一句,则弹出的菜单不会自动消失。
(5)接下去来处理IDM_RUN消息:
case IDM_RUN:{g_nid.hIcon = LoadIcon(g_hInstance, (LPCTSTR)IDI_ON); Shell_NotifyIcon(NIM_MODIFY, &g_nid);hSrcDC = GetDC(GetDesktopWindow());HMODULE hModule = LoadLibrary("User32.dll");lpfnSetLayeredWindowAttributes myfunc = (lpfnSetLayeredWindowAttributes)GetProcAddress(hModule, "SetLayeredWindowAttributes"); FreeLibrary(hModule);ShowWindow(hWnd, SW_MAXIMIZE);myfunc(hWnd, 0, 100, LWA_ALPHA);g_State = TRUE;}break;
首先是一个替换托盘区图标的操作,显示截图正在进行中。
然后先取得桌面DC,(先把全屏给截了,然后再跟踪鼠标的操作来对这张全屏图“剪裁”)hSrcDC是一个窗口消息处理函数的静态局部DC句柄。
接着利用API函数SetLayeredWindowAttributes来设置窗口为透明,其函数原型为:
BOOL SetLayeredWindowAttributes(HWND hwnd, // handle to the layered windowCOLORREF crKey, // specifies the color keyBYTE bAlpha, // value for the blend functionDWORD dwFlags // action
);
详细的解答请参照MSDN
这里需要申明对该函数的指针,注意,LWA_ALPHA需要自行定义
typedef BOOL (WINAPI *lpfnSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
...
#define LWA_ALPHA 0x00000002
g_State 是一个全局变量,用以记录是否在截图状态,在鼠标的消息处理函数中会对此变量进行判断,是的话再进行相应的操作。
(6)接下去跟踪鼠标的行为“剪裁”刚才的桌面DC,先找到需要的矩形块坐标。
主要过程为:
1.在WM_LBUTTONDOWN中记录第一个点,将它保存在静态POINT变量中;
2.在WM_MOUSEMOVE中在透明窗口上实时刷新并画线以显示截图的区域;
3.在WM_LBUTTONUP中记录第二个点,从而取得需要剪裁的区域矩形,用BitBlt复制DC内容,并保存位图文件。最后使窗口隐藏起来,更换托盘区图标等初始化工作。
具体代码在此不再罗嗦了,详见源码。
成品exe及源代码:点击打开链接
转载于:https://www.cnblogs.com/silyvin/archive/2012/05/07/9106906.html
Win32 SDK 编写截图小工具相关推荐
- SQL Server编写存储过程小工具(三)
SQL Server编写存储过程小工具 功能:为给定表创建Update存储过程 语法: sp_GenUpdate <Table Name>,<Primary Key>,&l ...
- 截图小工具,用c#语言开发
一.开发环境及工具 Windows 7 系统,开发软件为Microsoft Visual Studio Ultimate 2012 二.实现的功能 屏幕截屏,保存到图片或者保存到剪切板.截屏范围可以随 ...
- 手把手VC截图小工具,附源码
话说大四陪MM在图书管写论文的时候,图书馆没网,也没登陆QQ之类IM.都晓得论文要图文并茂....于是乎就需要截图.么法之好printscreen然后画图,麻烦到死...就想写个截图小工具还是很好玩的 ...
- python 编写实用小工具-toy: python平时积累的笔记以及编写的小工具
所有人都告诉你怎么活,只有自己没有搞清楚该如何活.相信自己,我们每个人都是主角?? toy Python ?? 献给我亲爱的女朋友--如 ? 介绍 学习 python.matlab 时积累的笔记以及编 ...
- python 编写实用小工具-使用Python制作一个打字训练小工具
一.写在前面 说道程序员,你会想到什么呢?有人认为程序员象征着高薪,有人认为程序员都是死肥宅,还有人想到的则是996和 ICU. 别人眼中的程序员:飞快的敲击键盘.酷炫的切换屏幕.各种看不懂的字符代码 ...
- 分享一个自己做的截图小工具(基于Windows平台的批处理文件实现)
最近项目中要有截图的工作要做,对于我等使用AS的开发人员来说,视频或者截图借用工具也是分分钟的事情,但是公司的业务同事和测试人员不懂怎么使用AS软件,而且犯不着为了截个图就去装AS吧,所以发挥我等程序 ...
- FSCapture截图小工具和注册码
今天给大家推荐一个小的截图截屏工具FSCapture,可在360软件库中下载安装,功能上的介绍网上好多在这就不多言.但是启动时需要注册码,于是乎就在网上找了一些供大家使用 企业版序列号: nam ...
- 非常简单的截图小工具
用QQ截图太麻烦. 我只是想要截个图,然后图片保持在窗口最前端即可. 2020.5.17 解决从下往上拉动鼠标造成错误的情况 增加右击取消截图 import Num.AddNum; import ja ...
- Win7系统截图小工具
第一步:按window键,可以看到 第二步:启动"截图工具"也很简单,单击"开始"菜单,打开"所有程序""附件"&quo ...
最新文章
- 将Nodelist快速转换为Array数组
- 团队-象棋游戏-模块测试过程
- 【NLP】simhash判断文档相似度
- 重磅!2021年考研国家线正式公布,部分学科分数线比去年更低!
- 20170910校内训练
- cycle函数python_Python执行函数的周期实现
- MySQL查看数据库相关信息
- SQL Server代理(11/12):维护计划作业
- Atitit.java swing打印功能 api attilax总结
- linux curl命令验证服务器断点续传支持
- 谁在告谁?移动专利混战图
- 程序观点下的线性代数
- @所有技术人,快来翻开属于你的2021定制日历!
- 度假村酒店官方网站模板里面包含7个子页面,适合酒店住宿网站模板下载
- R语言中的Factor到底是什么?
- Fiddler抓包工具报:The system ptoxy changed. Click to reenable capturing
- Using 1.7 requires compiling with Android 4.4 (KitKat); currently using API 10
- 用Python实现手机抓包,获取当当图书差评数据!
- Python爬虫——Urllib
- 小猿圈Java学习分享2019Java面试题