分享

一个不错的 trace.h 文件

 quasiceo 2014-01-18
分类: VC++ 2012-06-04 15:56 227人阅读 评论(0) 收藏 举报

/*==================trace 输出调试字符串====================
(一)功能:
 输出调试变量(类似于TRACE)

(二)特点:
 1.自动适应参数的类型(char、char*、string、CString、HWND、POINT、RECT....)
 2.自动适应输入参数的个数。(关闭了编译提醒 #pragma warning(disable: 4003) )
 3.会在输出的变量值前面自动添加变量的名称,方便查看
 4.程序自动创建Edit窗口用于输出转换后的字符串。
 5.程序退出时会将输出字符串保存到工程目录下的DebugData.txt。方便查看
 6.多种编译模式,比如可让DEBUG和Release版本都能输出调试变量或者两者都不输出
 7.支持UNICODE,WIN32,Dll,MFC

(三)使用说明:
 1.把trace.h复制到工程目录下(可以不添加到工程)。
 2.在文件"stdafx.h"里(文件的下方)添加 #include "trace.h"。之后就可以使用trace()宏了。
 3.所有输出的字符串会保存在工程目录下的"DebugData.txt"文件,以方便查看
 4.我把所有代码都放在一个头文件里,虽然不合符规范,但这样使用起来很方便。
 5.trace(x,y,z,w)宏原本有4个参数,当参数不如时,编译器会给出警告,
   所以使用 #pragma warning(disable: 4003) 把这个编译警告给关掉了。

(四)可以使用的宏:
 trace(X,Y,Z,W) //输出常用类型变量,如int、double、short、POINT、RECT、string
     //且自动适应变量的个数(变量数为1-4个)
 tracef()  //格式化字符串,类似sprintf
 traceLastError()//输出系统错误代码,调用了GetLastError()
 traceRel(X,Y)  //当X=true,输出"Y: successful" ; x=false,输出"Y: failed"
 CEasyTrace::clear();   //清空窗口
 

(五)关于trace宏使能设置:
 1.默认情况下 NO_TRACE_WINDOW 和 TRACE_WINDOW都没定义,则
   DEBUG版本会输出调试字符串,而Release版本不会
 2.如果开头定义了#define NO_TRACE_WINDOW
   DEBUG版本和Release版本都不会输出输出调试字符串
 3.如果开头定义了#define TRACE_WINDOW
   DEBUG版本和Release版本都会输出输出调试字符串
 4.每次修改上面2个宏后需要全部重新编译才会生效

(六)调用示例:
 void CDemoDlg::OnButton1()
 {
  int a=45; double b=67.45; double c=847.424;short d=324;
  RECT rect;
  ::GetWindowRect(m_hWnd,&rect);
  HWND hWnd=::GetForegroundWindow();
  POINT point;
  GetCursorPos(&point);
  bool ak=true;
  CPoint cpoint(88,421);
  CRect crect(19,423,56,522);
  CString mfcstr=_T("mfc CString");
  TCHAR buf[100]=_T("c style string");

 #ifdef _UNICODE
  wstring stlstr=_T("stl string");
 #else
  string stlstr=_T("stl string");
 #endif

  tracef(_T("tracef 类似于 %s"),_T("sprintf")); //格式化字符串,类似sprintf
  trace(_T("Impossible is nothing"));
  trace(stlstr);   //输出字符串
  trace(mfcstr);   //输出字符串
  trace(buf);   //输出字符串
  trace(a);  //输出int
  trace(a,b);  //输出int和double
  trace(a,b,c);
  trace(a,b,c,d);
  trace(point); 
  trace(point,cpoint); //输出POINT 和 CPoint 
  trace(rect);
  trace(rect,crect);  //输出RECT 和 CRect
  trace(hWnd);   //输出窗口信息
  traceLastError();  //输出系统错误代码  
  traceRel(ak==true,"func()");  //当X=true,输出"Y: successful" ; x=false,输出"Y: failed"
 }

(七)技巧:
 1.有时候我们只想观察某一个变量的变化,但程序里有很多trace,所以输出到窗口的
   数据影响了我们的观察。这是我们可以这样做,就能令其他trace都无效了。

   traceStart();  //接收数据
   trace(_T("只有 traceStart 和 traceStop 之间的trace才有效"));
   traceStop();  //禁止接收数据


版权声明:
 没有版权,许可任何单位,个人随意使用,拷贝,修改,但作者不承担由
 此代码带来的任何损失。由于作者水平有限,错误或不完善之处,在
 所难免,由此为你带来的不便,还望海涵。如果有任何BUG,请联系作者,
 大家一起完善它!以后有更新统一放在以下网址上,你可以浏览并获得
 更新以及详细的使用说明:
 当前更新日期:2011-10-21
 http://blog.csdn.net/jacky_qiu/archive/2010/11/04/5986089.aspx

最后:
 如果此份代码为你带来了帮助,并且使你心生感谢之意。那我可否请你
 诚心恭敬地念10遍“南(音:拿na)无(音:摩mo)阿弥陀佛”?
 愿得佛力加持,使你工作顺利,合家幸福!
 
           Jacky
           2011-5-25
           qiujiejia@gmail.com

========================================================================*/


#ifndef _EASY_TRACE_H_
#define _EASY_TRACE_H_


//trace宏编译开关━━━━━━━━━
//  #define NO_TRACE_WINDOW  //DEBUG版本和Release版本都不会输出输出调试字符串
//  #define TRACE_WINDOW  //DEBUG版本和Release版本都会输出输出调试字符串 
#ifdef NO_TRACE_WINDOW
#else
#ifdef _DEBUG
#define TRACE_WINDOW
#else
#ifdef RELEASE_TRACE
#define TRACE_WINDOW
#endif
#endif
#endif

//trace宏的参数是4个,当参数少于4个,编译器会给出警告,我们手动关闭这个
//警告(disable warning C4003: not enough actual parameters for macro)
#pragma warning(disable: 4003)
#pragma warning(disable: 4002)


#define TRACE_WND_TEXT _T("TraceWnd") //窗口标题
#define WM_CREATE_WND WM_USER+888  //自定义消息
#define AUTO_HIDE_TIME 3000   //定义多少毫秒后自动窗口
#include <Windows.h> //需要的头文件
#include <tchar.h>
#include <sstream>


//Not #define TRACE_WINDOW
#ifndef TRACE_WINDOW
#define trace(X)
#define tracef __noop
#define traceLastError() 
#define traceRel(X)   
#define traceClear(X)    
#define traceStop(X)  
#define traceStart(X)  
#endif

//#define TRACE_WINDOW
#ifdef TRACE_WINDOW

//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━trace宏━━━━
#define trace(X,Y,Z,W) {CEasyTrace obj; \
  obj.name(#X); obj.add(X); \
  obj.name(#Y); obj.add(Y); \
  obj.name(#Z); obj.add(Z); \
  obj.name(#W); obj.add(W); }

#define tracef      CEasyTrace::Tracef 
#define traceLastError() { CEasyTrace().TraceSysError();  }
#define traceRel(X)   { CEasyTrace().TraceResult(#X,X); }
#define traceClear(X)  { ::SendMessage(::FindWindow(NULL,TRACE_WND_TEXT),WM_COMMAND,3,NULL); }    
#define traceStop(X)  { CEasyTrace::IsReceive(FALSE);  }
#define traceStart(X)  { CEasyTrace::IsReceive(TRUE);  }
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 

 

class CTraceWnd
{
public:
 ~CTraceWnd(){ ::DestroyWindow(::FindWindow(NULL,TRACE_WND_TEXT)); }
 
 /****************************************************************************
 行首序列号
 -1 ---- 不输出索引
 1   --- 重置索引值为1
 0    ---获取索引
 ****************************************************************************/
 static TCHAR* GetIndex(int opt=0)
 {
#define INDDEX_NUM 4  //对齐的位数

  static int num=1;
  static TCHAR buf[11]={0};
  static TCHAR buf2[11]={0};
  static BOOL IsOutIndex=-10;
  if (IsOutIndex==-10) IsOutIndex=GetProfileInt(TRACE_WND_TEXT,_T("m_IsIndex"),TRUE);

  if (opt==-1) IsOutIndex=FALSE;
  if (opt== 1) {IsOutIndex=1; num=1;}
  if (!IsOutIndex) {  buf[0]=NULL; return buf;}

  
  _itot(num++,buf,10);//int 转文本
  int len=_tcslen(buf);
  int count=INDDEX_NUM-len;
  if (count>0)
  {
   for (int i=0; i< count;i++) {buf2[i]=' ';}
   _tcscpy(buf2+count,buf);
   return buf2;
  }
  else
   return buf;
 }


 static BOOL IsName(BOOL var=-1)
 {
  static int state=-10;
  if (state==-10)  state=GetProfileInt(TRACE_WND_TEXT,_T("m_IsName"),TRUE);
  if(var!=-1) state=var;
  return state;
 }
 
 /****************************************************************************
 输出的字符串到窗口
 ****************************************************************************/
 static void CTraceWnd::PrintString(const TCHAR* OutputStr)
 {
  //寻找已创建的输出窗口
  HWND hWnd=::FindWindow(NULL,TRACE_WND_TEXT);
  
  //如果不存在,则创建窗口并初始化设置
  if ( !hWnd )
  {
   //定义这个对象是为了程序退出是调用析构函数来
   //保存文件和关闭窗口,除此之外没有其他用处了
   static CTraceWnd ForGetCloseMessage;
   
   //创建窗口
   hWnd=(HWND)WindowProc(NULL,WM_CREATE_WND,NULL,NULL);
   if (!hWnd) return;
  }
  
  //将字符串输出到窗口
  ::SendMessage(hWnd,EM_REPLACESEL,FALSE,(LPARAM)OutputStr); 
 }

 /****************************************************************************
 //保存窗口配置
 ****************************************************************************/
 static void SaveConfig(BOOL m_IsAutoWidth,BOOL m_IsAutoHide,BOOL m_IsHide,BOOL m_IsContinue,BOOL m_IsName,BOOL m_IsIndex,HWND hWnd)
 {
  TCHAR buf[11];
  _itot(m_IsAutoWidth,buf,10); WriteProfileString(TRACE_WND_TEXT,_T("m_IsAutoWidth"),buf);
  _itot(m_IsAutoHide ,buf,10); WriteProfileString(TRACE_WND_TEXT,_T("m_IsAutoHide"), buf);
  _itot(m_IsHide    ,buf,10); WriteProfileString(TRACE_WND_TEXT,_T("m_IsHide"),   buf);
  _itot(m_IsContinue ,buf,10); WriteProfileString(TRACE_WND_TEXT,_T("m_IsContinue"), buf);
  _itot(m_IsName    ,buf,10); WriteProfileString(TRACE_WND_TEXT,_T("m_IsName"),     buf);
  _itot(m_IsIndex    ,buf,10); WriteProfileString(TRACE_WND_TEXT,_T("m_IsIndex"),    buf);
  if (!m_IsHide)
  {
   RECT rect;
   ::GetWindowRect(hWnd,&rect);
   _itot(rect.left,buf,10);   WriteProfileString(TRACE_WND_TEXT,_T("x"),buf);
   _itot(rect.top,buf,10);    WriteProfileString(TRACE_WND_TEXT,_T("y"),buf);
   _itot(rect.right-rect.left,buf,10); WriteProfileString(TRACE_WND_TEXT,_T("cx"),buf);
   _itot(rect.bottom-rect.top,buf,10); WriteProfileString(TRACE_WND_TEXT,_T("cy"),buf);
  }
 }
 
 static void ReShowWindow(HWND hWnd)
 {
  int x=GetProfileInt(TRACE_WND_TEXT,_T("x"),0);
  int y=GetProfileInt(TRACE_WND_TEXT,_T("y"),0);
  int cx=GetProfileInt(TRACE_WND_TEXT,_T("cx"),200);
  int cy=GetProfileInt(TRACE_WND_TEXT,_T("cy"),600);
  ::SetWindowPos(hWnd,HWND_TOPMOST,x,y,cx,cy,SWP_NOACTIVATE);
 }

 static void HideWindowToLeftScreen(HWND hWnd)
 {
  ::SetWindowPos(hWnd,HWND_TOPMOST,-100,0,104,GetSystemMetrics(SM_CYSCREEN),NULL);
 }


 /****************************************************************************
 Edit Window的窗口过程
 ****************************************************************************/
 static LRESULT CALLBACK CTraceWnd::WindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
 {
  static WNDPROC m_OldWndProc = NULL;
  static int  m_WindowWidth = 200; //窗口宽度
  static HWND  StaticWnd  = NULL; //
  static BOOL  m_IsReceive  = TRUE; //是否接受数据
  static BOOL  m_IsContinue = TRUE; //当输出字符串时是否清空之前的数据
  static BOOL  m_IsAutoWidth = TRUE; //是否根据字符串长度自动调整窗口宽度
  static BOOL  m_IsAutoHide = FALSE; //是否自动隐藏
  static BOOL  m_IsHide  = FALSE; //是否隐藏
  static BOOL  m_IsName  = TRUE; //是否自动补上变量名
  static BOOL  m_IsIndex  = TRUE; //添加行号索引
 
  switch(message)
  {
  case WM_CREATE_WND: //创建Edit窗口 ,这是自定义消息
   {
    //获取窗口配置
    int x=GetProfileInt(TRACE_WND_TEXT,_T("x"),0);
    int y=GetProfileInt(TRACE_WND_TEXT,_T("y"),0);
    int cx=GetProfileInt(TRACE_WND_TEXT,_T("cx"),200);
    int cy=GetProfileInt(TRACE_WND_TEXT,_T("cy"),600);
    m_IsAutoWidth =GetProfileInt(TRACE_WND_TEXT,_T("m_IsAutoWidth"),1);
    m_IsAutoHide =GetProfileInt(TRACE_WND_TEXT,_T("m_IsAutoHide"),0);
    m_IsHide  =GetProfileInt(TRACE_WND_TEXT,_T("m_IsHide"),FALSE);
    m_IsContinue =GetProfileInt(TRACE_WND_TEXT,_T("m_IsContinue"),TRUE);
    m_IsName  =GetProfileInt(TRACE_WND_TEXT,_T("m_IsName"),TRUE);
    IsName(m_IsName);
    m_IsIndex  =GetProfileInt(TRACE_WND_TEXT,_T("m_IsIndex"),TRUE);
    GetIndex( m_IsIndex ? 1 : -1);
    m_IsReceive  =TRUE; //不需要保存在配置文件

    //超出屏幕重新调整
    int SrcCx=GetSystemMetrics(SM_CXSCREEN);
    int SrcCy=GetSystemMetrics(SM_CYSCREEN);
    if (x<0 || x>=SrcCx) x=0;
    if (y<0 || y>=SrcCy) y=0;
    if (cx<100) cx=100;
    if (cy<40) cy=40;
    if (x+cx>SrcCx) x=SrcCx-cx;
    if (y+cy>SrcCy) y=SrcCy-cy;

    //如果窗口是隐藏状态,修改x的值
    if (m_IsHide)
    {
     x=-cx+4;
     y=0;
     cy=GetSystemMetrics(SM_CYSCREEN);
    }

    HWND hWnd=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW,TEXT("Edit"),TRACE_WND_TEXT ,
     WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL|
     ES_AUTOHSCROLL|ES_WANTRETURN|ES_MULTILINE ,
     x,y,cx,cy,
     NULL,NULL,NULL,NULL);
    
    if (hWnd==NULL) return NULL;
    
    //创建菜单,并添加到窗口
    HMENU hMenu = CreateMenu() ;
    AppendMenu(hMenu,MF_STRING, 5, _T("隐藏到屏幕左边") ) ;
    AppendMenu(hMenu,MF_STRING, 3, _T("清空窗口"));
    //-----------------sub menu
    HMENU hSubMenu=CreateMenu() ;
    AppendMenu(hSubMenu,MF_STRING, 6,  _T("自动隐藏") );
    AppendMenu(hSubMenu,MF_STRING, 7,  _T("接受数据") );
    AppendMenu(hSubMenu,MF_STRING, 4,  _T("根据字符串长度自动调整窗口宽度" ));
    AppendMenu(hSubMenu,MF_STRING, 9,  _T("连续输出数据"));
    AppendMenu(hSubMenu,MF_STRING, 10, _T("输出时自动添加变量名"));
    AppendMenu(hSubMenu,MF_STRING, 11, _T("输出时添加行号索引"));
    AppendMenu(hSubMenu,MF_STRING, 8,  _T("帮助"));
    //-----------------sub menu
    AppendMenu(hMenu, MF_POPUP,UINT(hSubMenu), _T("选项")) ;
    ::SetMenu(hWnd,hMenu);
   

    //修改edit框的限制字符个数
    ::SendMessage(hWnd,EM_SETLIMITTEXT,1000000, 0);
    
    //清空Edit
    ::SendMessage(hWnd,WM_SETTEXT,NULL,(LPARAM)_T("")); 
    
    // 设置字体参数
    LOGFONT LogFont;
    ::memset(&LogFont, 0, sizeof(LOGFONT));
    lstrcpy(LogFont.lfFaceName,_T("Fixedsys"));
    LogFont.lfHeight = -12; // 字体大小
    LogFont.lfCharSet = GB2312_CHARSET;
    // 创建字体
    HFONT hFont=CreateFontIndirect(&LogFont);
    // 设置字体
    ::SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, 0);
    
    //把hWnd的默认窗口过程替换为WindowProc,返回默认函数过程的函数指针
    m_OldWndProc=(WNDPROC)SetWindowLong(hWnd,GWL_WNDPROC, (LONG)WindowProc);
    if (!m_OldWndProc)
     return NULL;
    
    //显示时无焦点
    ::ShowWindow(hWnd,SW_SHOWNOACTIVATE);
    
    //如果没有开启自动隐藏并且又处于隐藏状态,则弹出提示窗口
    if (!m_IsAutoHide && m_IsHide)
    {
     StaticWnd=CreateWindowEx(WS_EX_TOPMOST,_T("Static"),
      _T("Trace窗口隐藏在屏幕左边\n点击屏幕左边可恢复窗口"),
      WS_POPUP|WS_VISIBLE|WS_BORDER
      |SS_CENTER ,
      0,y,200,40,NULL,NULL,NULL,NULL);

     SetTimer(hWnd,2,2000,NULL);
    }

    return (LRESULT)hWnd;
   }
   break;

  case WM_TIMER:
   {
    if (wParam==2) //关闭提示窗口
    {
     ::DestroyWindow(StaticWnd);
     break;
    }

    if ( !m_IsHide && ::GetForegroundWindow()!=hWnd)
    {
     //隐藏窗口
     m_IsHide=true;
     HideWindowToLeftScreen(hWnd);
    }
   }
   break;

  case WM_ACTIVATE:
   {
    if (LOWORD(wParam)==WA_INACTIVE ) //窗口失去焦点
    {
     if (m_IsAutoHide)
     {
      ::SetTimer(hWnd,1,200,NULL); //延长200ms后hide
     }
    }
   }
   break;

  case WM_NCLBUTTONDOWN:
   {
    if (m_IsHide)
    {
     m_IsHide=false;
     ReShowWindow(hWnd); //重新显示窗口
     // save m_IsHide
     SaveConfig(m_IsAutoWidth,m_IsAutoHide,m_IsHide,m_IsContinue,m_IsName,m_IsIndex,hWnd);
    }
    else
    {
     //传递默认操作另其改变窗口的位置大小
     int rel=::CallWindowProc(m_OldWndProc, hWnd, message, wParam, lParam);

     if (wParam==HTLEFT  ||wParam==HTTOP  ||wParam==HTRIGHT  ||wParam==HTBOTTOM || wParam==HTCAPTION ||
      wParam==HTTOPLEFT||wParam==HTTOPRIGHT ||wParam==HTBOTTOMLEFT ||wParam==HTBOTTOMRIGHT)
     {
      //保存窗口配置
      SaveConfig(m_IsAutoWidth,m_IsAutoHide,m_IsHide,m_IsContinue,m_IsName,m_IsIndex,hWnd);
     }

     return rel;
    }
   }
   break;

  case EM_REPLACESEL:
   {
    if(!m_IsReceive) return 0;

    if (m_IsContinue)
    {
     //光标指向最后
     ::SendMessage(hWnd,EM_SETSEL,4294967290, 4294967290); 

     //调用默认过程添加字符串到edit 窗口
     ::CallWindowProc(m_OldWndProc, hWnd, message, wParam, lParam);
    }
    else
    {
     ::SendMessage(hWnd,WM_SETTEXT,NULL,lParam);
    }
    
    
    //开启了自动隐藏功能
    if (m_IsAutoHide)
    {
     if (m_IsHide)
     {
      m_IsHide=false;
      ReShowWindow(hWnd);
     }

     //设置AUTO_HIDE_TIME后隐藏窗口
     ::SetTimer(hWnd,1,AUTO_HIDE_TIME,NULL);
    }

    //开启了自动调整窗口的宽度功能
    if (m_IsAutoWidth)
    {
     if (!m_IsHide)
     {
      int MinPos,MaxPos;
      GetScrollRange(hWnd,SB_HORZ, &MinPos,&MaxPos);
      if (m_WindowWidth<MaxPos+40)
      {
       m_WindowWidth=MaxPos+40;
       RECT rect;
       ::GetWindowRect(hWnd,&rect);
       ::SetWindowPos(hWnd,NULL,0,0,m_WindowWidth,rect.bottom-rect.top,SWP_NOMOVE|SWP_NOACTIVATE);
      }
     }
    }
   }
   break;

  case WM_DESTROY:
   {
    //删除字体
    DeleteObject( (HFONT)::SendMessage(hWnd,WM_GETFONT,0,0) );
    //删除菜单
    DestroyMenu(GetMenu(hWnd));

    //设置程序运行的目录跟程序文件所在目录相同
    //当我们的程序被其他程序打开时,它的工作目录和打开它的那。
    //个程序的目录是相同的。所以我们需要把目录改回来
    TCHAR AppPath[MAX_PATH];
    int nlen=GetModuleFileName(NULL,AppPath,MAX_PATH);
    while(AppPath[--nlen]!='\\'); 
    AppPath[nlen]='\0';
    SetCurrentDirectory(AppPath); 
    
    //获取窗口的字符串
    int len=::SendMessage(hWnd,WM_GETTEXTLENGTH,0,0);
    TCHAR* WindowText=new TCHAR[(len+1)*sizeof(TCHAR)];
    ::GetWindowText(hWnd,WindowText,len+1);  //GetWindowText会自动添加NULL结束符
    
    //打开由于保存数据文件DebugData.txt, 
    FILE* fp=fopen("DebugData.txt","wb"); 
    
#ifdef _UNICODE//如果定义了unicode,则先转为ansi再保存
    //len是源字符串的长度 len=_tcslen(WindowText)
    //(len+1)*2是源字符串占用的内存空间,包括NULL结束符
    //nChars返回转换的字符个数,不包括NULL,既nChars=_tcslen(buffer)
    //wcstombs会自动添加NULL结束符
    char* buffer = new char[(len+1)*2];
    setlocale(LC_ALL,".936");
    int nChars = wcstombs(buffer,WindowText,(len+1)*2);
    setlocale(LC_ALL,"C");
    fwrite(buffer,1,nChars,fp);
    delete buffer;
#else 
    fwrite(WindowText,1,len,fp);
#endif
    delete[] WindowText;
    fclose(fp);
   }
   break;

  case WM_CLOSE:
   if (m_IsIndex)
    GetIndex(TRUE);
   ::DestroyWindow(hWnd);
   break;

  case WM_KEYDOWN:
   {
    //select all
    if (wParam=='A' && GetKeyState(VK_CONTROL)<0)
     ::SendMessage(hWnd,EM_SETSEL,0,-1);
   }
   break;

  case WM_INITMENUPOPUP:
   {
    HMENU hSubMenu=(HMENU)wParam;
    CheckMenuItem(hSubMenu,6, MF_BYCOMMAND | m_IsAutoHide ? MF_CHECKED : MF_UNCHECKED );
    CheckMenuItem(hSubMenu,7, MF_BYCOMMAND | m_IsReceive  ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hSubMenu,4, MF_BYCOMMAND | m_IsAutoWidth? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hSubMenu,9, MF_BYCOMMAND | m_IsContinue ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hSubMenu,10,MF_BYCOMMAND | m_IsName     ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hSubMenu,11,MF_BYCOMMAND | m_IsIndex    ? MF_CHECKED : MF_UNCHECKED);
   }
   break;

  case WM_COMMAND:
   {
    switch(wParam)
    {
    case 3:  //清空内容
     {
      if (m_IsIndex)
       GetIndex(1);
      ::SendMessage(hWnd,WM_SETTEXT,NULL,(LPARAM)_T("")); 
     }
     break;
    case 5:  //hide window int the left of the screen
     {
      //隐藏窗口
      m_IsHide=true;
      HideWindowToLeftScreen(hWnd);

      //隐藏窗口后要禁止自动隐藏
      m_IsAutoHide=false;
      SaveConfig(m_IsAutoWidth,m_IsAutoHide,m_IsHide,m_IsContinue,m_IsName,m_IsIndex,hWnd);
     }
     break;
    case 4:  //modify the Auto Adjust window width option
     {
      m_IsAutoWidth=!m_IsAutoWidth;
      SaveConfig(m_IsAutoWidth,m_IsAutoHide,m_IsHide,m_IsContinue,m_IsName,m_IsIndex,hWnd);
     }
     break;
    case 6:  //modify the Auto hide window option
     {
      m_IsAutoHide=!m_IsAutoHide;
      if(!m_IsAutoHide) ::KillTimer(hWnd,1);
      SaveConfig(m_IsAutoWidth,m_IsAutoHide,m_IsHide,m_IsContinue,m_IsName,m_IsIndex,hWnd);
     }
     break;
    case 7:  //modify the receivd date option
     {
      if(m_IsReceive)
       ::SendMessage(hWnd,EM_REPLACESEL,FALSE,(LPARAM)_T("\r\n注意:当前处于禁止接收数据状态\r\n")); 

      m_IsReceive=!m_IsReceive;
      SaveConfig(m_IsAutoWidth,m_IsAutoHide,m_IsHide,m_IsContinue,m_IsName,m_IsIndex,hWnd);
     }
     break;
    case 8: 
     ::SendMessage(hWnd,WM_SETTEXT,NULL,(LPARAM)_T("帮助及更新:\r\nhttp://blog.csdn.net/jacky_qiu/article/details/5986089\r\nEmail: qiujiejia@gmail.com")); 
     break;
    case 9:  //modify the receivd date option
     {
      m_IsContinue=!m_IsContinue;
      SaveConfig(m_IsAutoWidth,m_IsAutoHide,m_IsHide,m_IsContinue,m_IsName,m_IsIndex,hWnd);
     }
     break;
    case 10: 
     {
      m_IsName=!m_IsName;
      IsName(m_IsName);
      SaveConfig(m_IsAutoWidth,m_IsAutoHide,m_IsHide,m_IsContinue,m_IsName,m_IsIndex,hWnd);
     }
     break;
    case 11: 
     {
      m_IsIndex=!m_IsIndex;
      GetIndex( m_IsIndex ? 1 : -1);
      SaveConfig(m_IsAutoWidth,m_IsAutoHide,m_IsHide,m_IsContinue,m_IsName,m_IsIndex,hWnd);
     }
     break;
    }
   }
   break;

  default:
   return ::CallWindowProc(m_OldWndProc, hWnd, message, wParam, lParam);
  }
  return 0;
 }
};

 

 

/****************************************************************************
CEasyTrace
****************************************************************************/
class CEasyTrace
{
private:

#ifdef _UNICODE 
 std::wostringstream m_str;
#else 
 std::ostringstream m_str;
#endif 

public:
 void add(){}  //当trace宏参数不足时会调用此函数
 void name(){}  //当trace宏参数不足时会调用此函数

 //初始化一个ostringstream对象并且添加序列号
 CEasyTrace() {  m_str<<CTraceWnd::GetIndex()<<_T("  ");    }

 //析构时将字符串输出到Edit窗口
 ~CEasyTrace()
 {
  if(!IsReceive()) return;

  m_str<<_T("\r\n");   //输出“换行”
#ifdef _UNICODE 
  CTraceWnd::PrintString(std::wstring(m_str.str()).c_str());
#else 
  CTraceWnd::PrintString(std::string(m_str.str()).c_str());
#endif 
 }

 //输出变量名
 void name(char* pStr)
 {
  if(!CTraceWnd::IsName()) return;

  if (strchr(pStr,'\"')!=NULL) return;
#ifdef _UNICODE 
  wchar_t* UnicodeStr=AnsiToUnicode(pStr);
  m_str<<UnicodeStr<<_T("=");
  delete[] UnicodeStr;
#else
  m_str<<pStr<<_T("=");
#endif
 }

 //输出一般类型的变量
 template <class T> void add(T t)  { m_str<<t<<_T("\t"); }

 //输出point
 void add(POINT point) { m_str<<(_T("("))<<point.x<<(_T(","))<<point.y<<(_T(")\t")); }

 //输出rect
 void add(RECT rect) { m_str<<(_T("("))<<rect.left<<(_T(","))<<rect.top<<(_T(","))<<rect.right<<(_T(","))<<rect.bottom<<(_T(")-("))<<(rect.right-rect.left)<<(_T(","))<<(rect.bottom-rect.top)<<(_T(")\t")); }

 //输出窗口信息
 void add(HWND hWnd)
 {
  if (!::IsWindow(hWnd)) { m_str<<_T("Invalid Window"); return; }
  
  TCHAR WindowText[40]; ::SendMessage(hWnd,WM_GETTEXT,(WPARAM)sizeof(WindowText)/sizeof(TCHAR),(LPARAM)WindowText); 
  TCHAR ClassName[40]; ::GetClassName(hWnd,ClassName,sizeof(ClassName)/sizeof(TCHAR));
  RECT  rect;    ::GetWindowRect(hWnd,&rect);

  m_str<<_T("━━━━━━━━━━━━━")
    <<_T("\r\n\tWindow Text:  \"")  <<WindowText
    <<_T("\"\r\n\tClass Name:  \"") <<ClassName
    <<_T("\"\r\n\tHandle:  0x")  <<HWND(hWnd)
    <<_T("\r\n\trect:\t");   
  add(rect);
  m_str<<_T("\r\n\t━━━━━━━━━━━━━━━━"); 
 }
 
 //输出系统错误代码
 void TraceSysError() { m_str<<_T("System Error Codes:")<<GetLastError(); }

 //输出函数执行的结果
 void TraceResult(char* pStr,BOOL IsOk) 
 {
#ifdef _UNICODE
  wchar_t* UnicodeStr=AnsiToUnicode(pStr);
  m_str<<UnicodeStr;
  delete[] UnicodeStr;
#else
  m_str<<pStr;
#endif
  m_str<<_T(" : ")<<( IsOk==TRUE ? _T(" Successful(true)") : _T("Failed(false)") );
 }

 //输出MFC的 CPoint CRect CString
#ifdef __AFXWIN_H__
 void add(CPoint point) { add((POINT)point);}
 void add(CRect rect) { add((RECT)rect);}
 void add(CString str) { add((LPTSTR)(LPCTSTR)str); }
#endif

 //ansi 转 unicode ,用完要删除指针
 wchar_t* AnsiToUnicode(char* AnsiStr)
 {
  UINT len=strlen(AnsiStr);
  wchar_t* UnicodeStr= new wchar_t[len+1];
  setlocale(LC_ALL,".936");
  int num=mbstowcs(UnicodeStr,AnsiStr,len+1);
  setlocale(LC_ALL,"C");
  if(-1==num) *UnicodeStr=NULL;
  return UnicodeStr;
 }

 //输出格式化字符串,类似sprintf
 static void Tracef(LPCTSTR lpszFormat, ...)
 {
  va_list args; va_start(args, lpszFormat); //begin
  TCHAR szBuffer[1024];
  int rel=_vsntprintf(szBuffer, sizeof(szBuffer)/sizeof(TCHAR)-1, lpszFormat, args);
  if (rel==-1) szBuffer[sizeof(szBuffer)/sizeof(TCHAR)-1]=NULL;
  va_end(args);  //end
  CEasyTrace().add(szBuffer); //输出字符串
 }

 /****************************************************************************
 设置和获取接收状态
 -1: 获取接收状态
 TRUE: 设置为接收状态
 FALSE: 禁止接收。
 ****************************************************************************/
 static BOOL IsReceive(BOOL var=-1)
 {
  static BOOL state=true;
  if(var!=-1) state=var;
  return state;
 }

};


#endif // #define TRACE_WINDOW
#endif // #define _EASY_TRACE_H_

更多 0

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多