C#截图程序类似腾讯QQ截图实现代码
程序员文章站
2023-12-10 22:36:40
最近把以前制作的截图程序重新写了一下动了一个大手术 高质量仿照的tx的截图程序
先看几个效果图
拖动过程中显示当前鼠标下一小块的图像信息 尺寸、颜色信息的 &nbs...
最近把以前制作的截图程序重新写了一下动了一个大手术 高质量仿照的tx的截图程序
先看几个效果图
拖动过程中显示当前鼠标下一小块的图像信息 尺寸、颜色信息的 注意 这里颜色是用的argb 本来截图的话rgb就够了 可是我把那个做成了控件 不仅截图可用 其他地方也可用作图像的选取 具体看代码就知道了
并且我还加了一个可以截图的同时把鼠标也捕获下来 现在看到的是我自己的截图程序 那个工具条啥的 是从tx的截图程序上面拔下来的
上面是几个工具条上的工具的三种粗细型号的展示 看到的蓝色的粗的刷笔 本来想的不应该是这个效果的 应该是颜色填充均匀的那种 但是仔细一想代码中用的是drawline(p,pointlast,pointcurrent);这种方式来画的*线条 如果是一个像素的没什么问题 粗点的就是上面看到的那种效果 也就是由许多小线段拼接出来的*线条而每个线段两端都是方的所以线段与线段之间的接缝处 可能就有问题 反正就那个意思 你懂得 不过再仔细一想虽然不是想要的效果但却意外的出现了 蜡笔的效果 果断也就不改了这样也不错
同样的具有自动捕获窗体边框的功能
使用也非常简单 这个截图的功能写到了一个dll中 引用名称空间 然后frmcapture 就是截图的了给了他几个属性 也就是上面看到的
同时在拖动过程中可以通过键盘 wasd 四个键来控制鼠标精确移动
操作方式也和tx的一样
右键鼠标 如果有选择的区域则取消选择的区域 没有则退出截图
双击将选择的区域复制到剪切板
整个思路也和前面几篇文章中提到的一样 只是在代码层面上动了一个大手术 因为原来写的主要是凸显那个自动捕获窗体的功能
复制代码 代码如下:
//根据鼠标位置找寻窗体平绘制边框
private void foundanddrawwindowrect() {
win32.lppoint pt = new win32.lppoint();
pt.x = mouseposition.x; pt.y = mouseposition.y;
intptr hwnd = win32.childwindowfrompointex(win32.getdesktopwindow(), pt,
win32.cwp_skipinvisibl | win32.cwp_skipdisabled);
if (hwnd != intptr.zero) {
intptr htemp = hwnd;
while (true) { //循环的根据坐标向内部找寻子窗体 直到无法找到位置
win32.screentoclient(htemp, out pt);
htemp = win32.childwindowfrompointex(htemp, pt, win32.cwp_all);
if (htemp == intptr.zero || htemp == hwnd)
break;
hwnd = htemp;
pt.x = mouseposition.x; pt.y = mouseposition.y; //坐标还原为屏幕坐标
}
win32.lprect rect = new win32.lprect();
win32.getwindowrect(hwnd, out rect);
imageprocessbox1.setselectrect(
new rectangle(rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top));
}
}
同前几篇文章一样是通过禁用自身窗体然后通过childwindowfrompointex函数来根据鼠标位置 获得鼠标下面的窗体 因为在获取的时候 鼠标下面是截图程序的一个窗体 所以在找寻窗体的时候得把自己忽略掉 而childwindowfrompointex在查找过程中可以忽略禁用的窗体 所以讲自己禁用就到到目的了 然后通过hook来监视鼠标的行为 来恢复禁用的窗体
复制代码 代码如下:
private void m_mhook_mhookevent(object sender, mhookeventargs e) {
........
//鼠标点下恢复窗体禁用
if (e.mbutton == buttonstatus.leftdown || e.mbutton == buttonstatus.rightdown) {
this.enabled = true;
imageprocessbox1.isdrawoperationdot = true;
}
........
}
还有一点 就只捕获鼠标的时候
复制代码 代码如下:
//获取桌面图像
private bitmap getscreen() {
bitmap bmp = new bitmap(screen.primaryscreen.bounds.width,
screen.primaryscreen.bounds.height);
if (this.iscapturecursor) { //是否捕获鼠标
//如果直接将捕获当的鼠标画在bmp上 光标不会反色 指针边框也很浓 也就是说
//尽管bmp上绘制了图像 绘制鼠标的时候还是以黑色作为鼠标的背景 然后在将混合好的鼠标绘制到图像 会很别扭
//所以 干脆直接在桌面把鼠标绘制出来再截取桌面
using (graphics g = graphics.fromhwnd(intptr.zero)) { //传入0默认就是桌面 win32.getdesktopwindow()也可以
win32.pcursorinfo pci;
pci.cbsize = system.runtime.interopservices.marshal.sizeof(typeof(win32.pcursorinfo));
win32.getcursorinfo(out pci);
if (pci.hcursor != intptr.zero) {
cursor cur = new cursor(pci.hcursor);
g.copyfromscreen(0, 0, 0, 0, bmp.size); //在桌面绘制鼠标前 先在桌面绘制一下当前的桌面图像
//如果不绘制当前桌面 那么cur.draw的时候会是用历史桌面的快照 进行鼠标的混合 那么到时候混出现底色(测试中就是这样的)
cur.draw(g, new rectangle((point)((size)mouseposition - (size)cur.hotspot), cur.size));
}
}
}
//做完以上操作 才开始捕获桌面图像
using (graphics g = graphics.fromimage(bmp)) {
g.copyfromscreen(0, 0, 0, 0, bmp.size);
}
return bmp;
}
我总感觉上面的方式很别扭 可是目前我也就只能通过这种方式去捕获鼠标了
有兴趣的就自己改造吧 导入那个dll自己想咋改造就咋改造