zoukankan      html  css  js  c++  java
  • QQ 静态截图完善实现之改造 CRectTracker 类


    QQ 静态截图完善实现之改造 CRectTracker 类

      

    由于前次写的代码过于仓促(相关文章参见:“QQ 静态截图程序模拟实现”),还没仔细修改就投稿了,在这里向大家表示道歉,可能你觉得这种程序不值的一看,但我本着精益求
    精的态度,还是把它完善了一下,更重要的是深入了解CRectTracer类的内部机制,以能更灵活和使用该类,在此我把MFC的CRectTracker类源码,提取出来做了小小的改造,有兴趣的朋友还可能更深入的增加更多的功能。

    本文主要讲述三个问题:
    1. 程序中操作提示窗口文本更新闪烁问题;
    2. 程序在调整截取矩形大小和位置时,主窗口收不到消息;
    3. CRectTracker类的简要说明和改造类CMyTracker;


     



    图一 示列

    一、操作提示窗口是一个编辑框控件,刷新时由于整个文本刷新,所以会有很难看的闪烁,而其实只有上面的RGB值在变化,那么就
    只要更新RGB值的文本就可以了,由于CEdit中没有更改指定文本内容的成员方法,在这里有一个巧妙的方法来实现,用CEdit的成员方法 SetSel选中要更改的RGB文本字符,然后用ReplaceSel就可以把选中的文本替换,从而达到不用更新整个文本,面造极度成闪烁。

    程序代码如下:

    void CCatchScreenDlg::ChangeRGB()
    {
    	//保存旧的RGB值字符串
            static CString strOld("");
    
    	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;
    	string.Format("(%d,%d,%d)",rValue,gValue,bValue);
    	//如果当前颜色没变则不刷新RGB值,以免窗口有更多闪烁
        if(strOld!=string)
    	{
    	    //得到RGB文本那一行的文本长度
    		int LineLength=m_tipEdit.LineLength(6);
    		//复选RGB值文本,也就是选中(255,255,255)样式
    	    m_tipEdit.SetSel(20,LineLength+6);
            
    		//替换RGB内容
    		m_tipEdit.ReplaceSel(string);
        }
    	//保存RGB值字符串
    	strOld=string;
    
    }
    
    程序中存在硬编码,但只要知道就行了!!

    二、程序在调整大小和位置时,主窗口收不到消息,这是由于CRectTracker内部处处理了消息,看一下CRectTracker::TrackHandle的MFC源码 :

    // get messages until capture lost or cancelled/accepted
    	for (;;)
    	{
    		MSG msg;
    		VERIFY(::GetMessage(&msg, NULL, 0, 0));
    		      
    		if (CWnd::GetCapture() != pWnd)
    			break;
    
                   //增加的,把消息派送给窗口
    		DispatchMessage(&msg);
    
    		switch (msg.message)
    		{
    		// handle movement/accept messages
    		case WM_LBUTTONUP:
    		case WM_MOUSEMOVE:
    			rectOld = m_rect;
    			// handle resize cases (and part of move)
    			if (px != NULL)
    				*px = (int)(short)LOWORD(msg.lParam) - xDiff;
    			if (py != NULL)
    				*py = (int)(short)HIWORD(msg.lParam) - yDiff;
    
    			// handle move case
    			if (nHandle == hitMiddle)
    			{
    				m_rect.right = m_rect.left + nWidth;
    				m_rect.bottom = m_rect.top + nHeight;
    			}
    			// allow caller to adjust the rectangle if necessary
    			AdjustRect(nHandle, &m_rect);
    
    			// only redraw and callback if the rect actually changed!
    			m_bFinalErase = (msg.message == WM_LBUTTONUP);
    			if (!rectOld.EqualRect(&m_rect) || m_bFinalErase)
    			{
    				if (bMoved)
    				{
    					m_bErase = TRUE;
    					DrawTrackerRect(&rectOld, pWndClipTo, pDrawDC, pWnd);
    				}
    				OnChangedRect(rectOld);
    				if (msg.message != WM_LBUTTONUP)
    				{
    					bMoved = TRUE;
    				}
    			}
    			if (m_bFinalErase)
    				goto ExitLoop;
    
    			if (!rectOld.EqualRect(&m_rect))
    			{
    				m_bErase = FALSE;
    			    DrawTrackerRect(&m_rect, pWndClipTo, pDrawDC, pWnd);
    			}
    			break;
    
    		// handle cancel messages
    		case WM_KEYDOWN:
    			if (msg.wParam != VK_ESCAPE)
    				break;
    		case WM_RBUTTONDOWN:
    			if (bMoved)
    			{
    				m_bErase = m_bFinalErase = TRUE;
    				//DrawTrackerRect(&m_rect, pWndClipTo, pDrawDC, pWnd);
    			}
    			m_rect = rectSave;
    			goto ExitLoop;
    
    		// just dispatch rest of the messages
    		default:
    			DispatchMessage(&msg);
    			break;
    		}
    	}
    
      我们只要在GetMessage(&msg, NULL, 0, 0)之后调用DispatchMessage(&msg),就可以把消息传递到主窗口,这样,内部处理和主窗口消息两不误,进而为程序为CRectTrakcer不能响应WM_LBUTTONUP和其消息而不用大改程序了...

    三、CRectTracker类的简要说明和改造类CMyTracker, CMyTracker类中增加了更改矩形颜色方法,增加StyleFlags的resizeMiddle设置中
    间位置,增加SetResizeCursor方法用开改变调整矩形大小和位置时鼠标光标,CRectTracker类中有几个重要的成员方法,一个是Draw方法
    负责画出当前矩形,在此方法中可能更改矩形颜色,看如下代码

    	// draw lines
    	if ((m_nStyle & (dottedLine|solidLine)) != 0)
    	{
    		if (m_nStyle & dottedLine)
    		{	
    			//改变当前矩形颜色 ,点线
    			pOldPen = pDC->SelectObject(CPen::FromHandle(_afxBlackDottedPen));
    		}
    		else
    		{
    			//改变当前矩形颜色 ,实线
    			//pOldPen = (CPen*)pDC->SelectStockObject(BLACK_PEN); 
    			pOldPen = pDC->SelectObject(CPen::FromHandle(_afxBlackSolidPen));
    		}
    
    		pOldBrush = (CBrush*)pDC->SelectStockObject(NULL_BRUSH);
    		nOldROP = pDC->SetROP2(R2_COPYPEN);
    		rect.InflateRect(+1, +1);   // borders are one pixel outside
    		pDC->Rectangle(rect.left, rect.top, rect.right, rect.bottom);
    		pDC->SetROP2(nOldROP);
    	}
    
      其中_afxBlackSolidPen是我增加的全局画笔句柄,在初始化时创建,通过增加的SetRectColor方法可以改变颜色, 修改了矩形颜色,当然还得修改调整矩形手柄了,也就是那八个点,修改代码处如下:
    if ((m_nStyle & (resizeInside|resizeOutside)) != 0)
    	{
    		UINT mask = GetHandleMask();
    		for (int i = 0; i < 8; ++i)
    		{
    			GetHandleRect((TrackerHit)i, &rect);			
    			//改变当前调整手柄矩形颜色,也就是那八个点				
    			pDC->FillSolidRect(rect, m_rectColor);
    		}
    	}
    
      其次是Track方法和TrackRubberBand方法,在其内部主要是调用TrackHandle方法,在Tracker方法中主要是消息捕获处理,动态调整当前 m_rect 矩形大小,和在调整大小和位置时画出虚线,当然画虚线功能是在DrawTrackerRect方法中实现,在此方法中主要是调用CDC类
    中的DrawDragRect方法,至使动态画虚线时不用刷新窗口.程序中由于不需要画虚线所以把DrawTrackerRect方法中代码注释了,直接更新
    主窗口,如果需要原来的功能,可能把注释去掉,在CRectTracker类中还有一些辅助方法,在这就不一一讲说。

    四、CMyTracker类从MFC源文件COPY过来,头文件在AFXEXT.H中,实现文件为TRCKRECT.CPP,COPY时去掉了一些调试信息,类的无参数构造
    函数定义为内联函数,是在AFXEXT.INL中实现,在构造函数中调用类中初始化函数Construct(),可以直接在实现文件中加入无参数构造函
    的实现,直接调用函数Construct(),其实这些简单的功能只要直接修改MFC源代码,程序调试完成后再改回来,但这样不能很好的通用,有些朋友认为微软的MFC源码神圣不可侵犯,但是为了程序的性能和功能,就要不择手段。

    软件名称: 改造 CRectTracker 类 
    软件语言: 简体中文 整理时间:  
    运行环境: windowsXP/2003/2000/98/95x 软件大小: 65KB
    软件等级: ★★★ 授权方式: 免费
    开 发 商:  
    软件简介:  
    下载地址: 本地下载一
     

  • 相关阅读:
    linux系统中给数据加上列号
    linux系统中统计指定类型文件大小的总和
    linux系统中awk命令求一列值的最大值、最小值、和及平均值
    R语言中找交集、并集、找不同、判断是否相同
    如何在字符串中加入回车换行,tab字符(关于字符串处理)
    BAPI几个有用的BAPI调用样例
    SAP 中国的咨询合作伙伴
    关于MRP的几个概念
    为什么有人不喜欢标准成本
    ERP系统中的存货计价过程
  • 原文地址:https://www.cnblogs.com/wqj1212/p/1429236.html
Copyright © 2011-2022 走看看