QQ 静态截图程序模拟实现

摘要:
QQ静态截图程序模拟看到这样的截图QQ真的忍不住想,怎么实现?思考了很久之后,我想出了一个实现方法。现在让我给你看一张QQ静态模拟的截图。我写的代码很乱。我认为有比这更简单的方法!!

QQ 静态截图程序模拟实现


看到QQ这样的截图实在忍心不住想,是怎以实现的?想了许久想到一个实现法子,下面就让我给大家展示一下,模拟QQ静态模拟截图,我写的代码比较乱,是想到哪写到哪,我想肯实还有比这更简单的办法!!程序实现思路,程序是基于对话框,无标题栏,系统菜单,最小化框,最大化框,无边框....,程序初始化时,把整个桌面屏幕截图,保存下来,然后把对话框设置全屏顶层窗口,然后把保存下来的位图,在OnEraseBkgnd中把整个位图贴到对话框上,然后用像皮筋类选择截取范围,看起来就像操作屏幕一样 。

QQ 静态截图程序模拟实现第1张

图一 示例

下面说说实现细节:
一、初始化程序,在CCatchScreenDlg构造函数中 初始化像皮筋类和保存全屏位图,

      //初始化像皮筋类
	m_rectTracker.m_nStyle=CRectTracker::resizeInside|CRectTracker::solidLine;  
	m_rectTracker.m_rect.SetRect(-1,-1,-1,-1);

    m_hCursor=AfxGetApp()->LoadCursor(IDC_CURSOR1);  
    
	
	m_bDraw=FALSE;
	m_bFirstDraw=FALSE;
	m_bQuit=FALSE;
	m_bShowMsg=FALSE;
    m_startPt=0;
    
	//获取屏幕分辩率
	m_xScreen = GetSystemMetrics(SM_CXSCREEN);
	m_yScreen = GetSystemMetrics(SM_CYSCREEN);

	//截取屏幕到位图中
	CRect rect(0, 0,m_xScreen,m_yScreen);
	m_pBitmap=CBitmap::FromHandle(CopyScreenToBitmap(&rect));
    
	//一定要初始化m_rgn,
    m_rgn.CreateRectRgn(0,0,50,50);

然后在CCatchScreenDlg::OnInitDialog()中设置对话框成顶层窗口。在 CCatchScreenDlg::OnEraseBkgnd中 用整个桌面位图填充全屏对话框背景

二、从 CRectTracker中派生了一个CTrack 类在类中重载了DrawTrackerRect函数,在函数中直接 更新窗口,消除拖动和改变大小时的虚线框可能还有更简单的方法,本人能力有限想不出更简的!

三、从Edit类中派生一个CMyEdit类,用该类的实例对像显示操作提示信息,在 CMyEdit::OnEraseBkgnd中,用一位图填充背景,类中响应了WM_MOUSEMOVE消息,在CMyEdit::OnMouseMove(UINT nFlags, CPoint point) 中移动窗口在左上角和右上角之间来回移动.

	CRect rect;
	GetWindowRect(&rect);

	int xScreen = GetSystemMetrics(SM_CXSCREEN);
	//int ySCreen = GetSystemMetrics(SM_CYSCREEN);

	if(m_bMove)
	{
		//移动到左上角
		MoveWindow(10,10,rect.Width(),rect.Height());
		m_bMove=FALSE;
	}
	else
	{
		//移动到右上角
		MoveWindow(xScreen-180,10,rect.Width(),rect.Height());
		m_bMove=TRUE;
	}

在主对话框上放置编缉框,然后关联一个CMyEdit的变量,在主对话显示时移动到左上角

	//把对化框设置成全屏顶层窗口
	SetWindowPos(&wndTopMost,0,0,m_xScreen,m_yScreen,SWP_SHOWWINDOW);
    
	//移动操作提示窗口
	CRect rect;
	m_tipEdit.GetWindowRect(&rect);
         m_tipEdit.MoveWindow(10,10,rect.Width(),rect.Height());
    
	//显示操作提示窗口文字
	DrawTip();
	
	//捕获按键消息窗口,将对话框的句柄传递到CCatchScreenApp中
	((CCatchScreenApp *)AfxGetApp())->m_hwndDlg=m_hWnd;

四、程序中有两个重要成员函数,一个是画截取矩形时的信息显示在鼠标右上角。

//显示截取矩形信息
void CCatchScreenDlg::DrawMessage(CRect &inRect)
{
	//截取矩形大小信息离鼠标间隔
	const int space=3;
    
	//设置字体颜色大小
	CClientDC dc(this);
	CPoint pt;
	CPen pen(PS_SOLID,1,RGB(147,147,147));
	dc.SetTextColor(RGB(147,147,147));
	CFont font;
	font.CreatePointFont(90,"宋体");
	dc.SelectObject(&font);

	//得到字体宽度和高度
	GetCursorPos(&pt);
	dc.SetBkMode(TRANSPARENT);
	TEXTMETRIC tm;
	int charHeight;
	CSize size;
	int	lineLength;
	dc.GetTextMetrics(&tm);
	charHeight = tm.tmHeight+tm.tmExternalLeading;
	size=dc.GetTextExtent("顶点位置  ",strlen("顶点位置  "));
	lineLength=size.cx;
    
	//初始化矩形, 以保证写下六行文字
	CRect rect(pt.x+space,pt.y-charHeight*6-space,pt.x+lineLength+space,pt.y-space);

	int x = GetDeviceCaps(dc, HORZRES);
	int y = GetDeviceCaps(dc, VERTRES);

    //创建临时矩形
    CRect rectTemp;
	//当矩形到达桌面边缘时调整方向和大小
	if((pt.x+rect.Width())>=x)
	{
		//桌面上方显示不下矩形
		rectTemp=rect;
		rectTemp.left=rect.left-rect.Width()-space*2;
		rectTemp.right=rect.right-rect.Width()-space*2;;
		rect=rectTemp;
	}

	if((pt.y-rect.Height())<=0)
	{
		//桌面右方显示不下矩形
		rectTemp=rect;
		rectTemp.top=rect.top+rect.Height()+space*2;;
		rectTemp.bottom=rect.bottom+rect.Height()+space*2;;
		rect=rectTemp;
		
	}
    
	//创建空画刷画矩形
	dc.SelectObject((HBRUSH)GetStockObject(NULL_BRUSH));
	dc.Rectangle(rect);
   	
	//在矩形中显示文字
	CString string(" 顶点位置 ");
    dc.TextOut(rect.left,rect.top,string);

	string.Format(" (%d,%d)",inRect.left,inRect.top);
	dc.TextOut(rect.left,rect.top+charHeight,string);

	string=" 矩形大小 ";
	dc.TextOut(rect.left,rect.top+charHeight*2,string);

	string.Format(" (%d,%d)",inRect.Width(),inRect.Height());
	dc.TextOut(rect.left,rect.top+charHeight*3,string);

	string=" 光标坐标 ";
	dc.TextOut(rect.left,rect.top+charHeight*4,string);

	string.Format(" (%d,%d)",pt.x,pt.y);
	dc.TextOut(rect.left,rect.top+charHeight*5,string);
	
}

根据鼠标的位置和要显示的字的宽度各高度在鼠标左上角位置处构造一个CRect对像,在CRect中显示矩形信息,同时根据鼠标当前的位置,在左边和上边不能正常显示信息时动态度反转矩形,还有一个类是DrawTip()在鼠标按下、松下是显示相应的操作提示

//显示操作提示信息
void CCatchScreenDlg::DrawTip()
{
    
    //得当前坐标像素,
	CPoint pt;
	GetCursorPos(&pt);

	//当到当前R,G,B,各像素值
	COLORREF color;
	CClientDC dc(this);
	color=dc.GetPixel(pt);
	BYTE rValue,gValue,bValue;
	rValue=GetRValue(color);
	gValue=GetGValue(color);
	bValue=GetGValue(color);
	
	//按格式排放字符串
	CString string;
	CString strTemp;
	string.Format("\r\n\r\n\r\n ·当前像素RGB (%d,%d,%d)\r\n",rValue,gValue,bValue);
    
	if(!m_bDraw&&!m_bFirstDraw)
	{
		strTemp="\r\n ·按下鼠标左键不放选择截取\r\n 范围\r\n\r\n ·按ESC键或鼠标右键退出";
	}
	else
	if(m_bDraw&&m_bFirstDraw)
	{
		strTemp="\r\n ·松开鼠标左键确定截取范围\r\n\r\n ·按ESC键退出";
	}
	else
	if(m_bFirstDraw)
	{
		strTemp="\r\n ·用鼠标左键调整截取范围的\r\n 大小和位置\r\n\r\n·截取范围内双击鼠标左键保存\r\n 图像,

结束操作\r\n\r\n·点击鼠标右键重新选择"; } string+=strTemp; //显示到编缉框中,操作提示窗口 m_tipEdit.SetWindowText(string); }

程序有点乱,文字都是硬编码写上去的,整个字符串显示在一对话框的编辑出框中,用空格和回车换行来控制摆放格式。

五、由于对话框中有一个编辑框,并且背景是一张位图,由于程截图时要经常刷新窗口,如果刷新整个窗口的话,编辑框会有很大的闪烁,
所以只能更新编辑框以外的区域,函数PaintWindow()计算更新区域,并更新窗口

void CCatchScreenDlg::PaintWindow()
{
	//获取当全屏对话框窗口大小
	CRect rect1;
	GetWindowRect(rect1);

	//获取编辑框窗口大小
	CRect rect2;
	m_tipEdit.GetWindowRect(rect2);

	CRgn rgn1,rgn2;
	rgn1.CreateRectRgnIndirect(rect1);
	rgn2.CreateRectRgnIndirect(rect2);

	//获取更新区域,就是除了编辑框窗口不更新
	m_rgn.CombineRgn(&rgn1,&rgn2,RGN_DIFF);
	
	InvalidateRgn(&m_rgn);
}

六、当然不能忘了方向键来微调截取矩形大小和位置,由于是基于对话框的程序,按键消息,被Windows内部的对话框过程处理了(即在基类中完成了处理,读者可以查看MFC的源代码),或者被发送给子控件进行处理,所以在对话框类中可能利用
BOOLProcessMessageFilter(int code, LPMSG lpMsg)这个虚函数来过滤或响应菜单和对话框的特定Windows消息在头文件中增加一个类型为HWND,Public成员变量名m_hwndDlg,在构造函数中初始化为NULL;在 CCatchScreenDlg::OnInitDialog()中加入

((CWinSunApp*)AfxGetApp())->m_hwndDlg=m_hWnd; 

将对话框的句柄传递到CWinSunApp类中

//********************************************************************************
#define SHIFTED 0x8000 
//********************************************************************************

BOOL CCatchScreenApp::ProcessMessageFilter(int code, LPMSG lpMsg) 
{
	// TODO: Add your specialized code here and/or call the base class
	if(m_hwndDlg!=NULL)
	{   //判断消息,如果消息是从对话框发出的或者其子控件发出的,就进行处理
		if((lpMsg->hwnd==m_hwndDlg) || ::IsChild(m_hwndDlg,lpMsg->hwnd))
		{
			//如果消息是WM_KEYDOWN
			//用方向键调整位置
			if(lpMsg->message==WM_KEYDOWN)
			{
				CRect rect(0,0,0,0);
				CCatchScreenDlg * pDlg=(CCatchScreenDlg *)AfxGetMainWnd();
				
				rect=pDlg->m_rectTracker.m_rect;

				if(pDlg->m_bFirstDraw)
				{
					
					//如果Shift键按下则方向键调整大小
					BOOL isShifeDowm=FALSE;
					int nVirtKey;
					nVirtKey = GetKeyState(VK_SHIFT); 
					if (nVirtKey & SHIFTED) 
						isShifeDowm=TRUE;

					switch(lpMsg->wParam)
					{
					case VK_UP:
						//如果按下Shift,则只调整一边
						if(!isShifeDowm)
							rect.top-=1;
						rect.bottom-=1;
						pDlg->m_rectTracker.m_rect=rect;
						pDlg->PaintWindow();
						break;
					case VK_DOWN:
						rect.top+=1;
						if(!isShifeDowm)
							rect.bottom+=1;
						pDlg->m_rectTracker.m_rect=rect;
						pDlg->PaintWindow();
						break;
					case VK_LEFT:
						if(!isShifeDowm)
							rect.left-=1;
						rect.right-=1;
						pDlg->m_rectTracker.m_rect=rect;
						pDlg->PaintWindow();
						break;
					case VK_RIGHT:
						rect.left+=1;
						if(!isShifeDowm)
							rect.right+=1;
						pDlg->m_rectTracker.m_rect=rect;
						pDlg->PaintWindow();
						break;
					}
				}
			}
		}
	} 
	return CWinApp::ProcessMessageFilter(code, lpMsg);
}

程序中涉及到像皮筋类的使用,就不多说了,知识库中有许多文章,接着就双击选区保存图片到剪贴板中。就说到这。我嘴笨 , 详细的请参看源文件注释,,有什么问题或您有更好的建意请不要忘了和我联系哦,邮箱: jzlkcn@yahoo.com.cn

软件名称:QQ 静态截图程序模拟实现
软件语言:简体中文整理时间:
运行环境:windowsXP/2003/2000/98/95x软件大小:58KB
软件等级:★★★授权方式:免费
开 发 商:
软件简介:
下载地址:本地下载一

免责声明:文章转载自《QQ 静态截图程序模拟实现》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇adb 环境配置 常用命令 [MD]手把手教你Smarty缓存技术(转)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

【原创+亲测可用】JS如何区分微信浏览器、QQ浏览器和QQ内置浏览器

1、原理: 通过不同移动端的ua弹窗 获取user-agent 参数包含的信息,进行判断浏览器类型 在Android上 QQ内置环境的ua中有关键字 MQQBrowser, 并且后面包含一个【空白符+QQ】字符;QQ浏览器仅有【MQQBrowser】因此在Android上区分,需要用正则判断ua中包含MQQBrowser,并且剔除【MQQBrowser...

每日技术总结:jquery datetimepicker,微博QQ好友QQ空间微信等分享接口

前言: 1.jquery datetimepicker 今天遇到一个日期控件格式的问题,默认选中显示的并不是设定的值,而是当天的日期。于是去查了一遍文档。 参考文章:jquery datetimepicker 配置参数 官方文档:DateTimePicker jQuery plugin select date and time (找了很久) 耗时2小时,翻...

“仿QQ局域网聊天软件”项目-常用编程技巧总结

1 信号槽篇 qqLogin loginDialog; QQ mainDialog; loginDialog.show(); //连接登陆窗口和主窗口 QObject::connect(&loginDialog,SIGNAL(SignalShowMainDialog(QTcpSocket *,QStringList)),&mainDialo...

认证授权:一键登录的背后过程

前言   许多网站在登录时,都有第三方账号登录方式:如常见的QQ、微信、微博登录   如下图:博客园、简书登录界面             那么当我们点击三方账号登录时,发生了什么事情呢?涉及什么概念呢?接下来我们就以QQ登录为例一步步去查看整个过程。 三方登录过程  以QQ登录简书为例,来查看整个过程。  1、进入QQ登录页面:   可以通过F12查看源...

很有用的系统命令和一些技巧(只列出扩展名为msc和cpl的)

在开始--运行输入命令即可运行相关的命令 下面目前在windows server2003测试过,其它操作系统未测试 azman.msc    授权管理器certmgr.msc  证书ciadv.msc    索引服务compmgmt.msc 计算机管理dcpol.msc    默认域控制器安全设置devmgmt.msc  设备管理器dfrg.msc    ...

命令行方式实现QQ自动登录

      上一次写过一篇VB制作QQ自动登录器的日志,介绍用得是模拟键盘输入的方式实现QQ的自动登录。这种方式有一种缺陷,就是必须保持输入焦点的正确,否则很容易就打乱了程序的执行过程,造成无法登录。特别是一开机就运行该程序,然后该程序去调用QQ的时候,Win API Winexec执行特慢,导致程序跟不上QQ,输入焦点也错了。后来在网上又发现了一种用QQ...