VC 调试输出int,char......

(六)调用示例:
    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"
    }

trace.h 代码,复制后保存为“trace.h",之后#include "trace.h" 就可以使用了

<p>/*==================trace 输出调试字符串====================
(一)功能:
 输出调试变量(类似于TRACE)</p><p>(二)特点:
 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</p><p>(三)使用说明:
 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) 把这个编译警告给关掉了。</p><p>(四)可以使用的宏:
 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();   //清空窗口
 </p><p>(五)关于trace宏使能设置:
 1.默认情况下 NO_TRACE_WINDOW 和 TRACE_WINDOW都没定义,则
   DEBUG版本会输出调试字符串,而Release版本不会
 2.如果开头定义了#define NO_TRACE_WINDOW
   DEBUG版本和Release版本都不会输出输出调试字符串
 3.如果开头定义了#define TRACE_WINDOW
   DEBUG版本和Release版本都会输出输出调试字符串
 4.每次修改上面2个宏后需要全部重新编译才会生效</p><p>(六)调用示例:
 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"); </p><p> #ifdef _UNICODE
  wstring stlstr=_T("stl string");
 #else
  string stlstr=_T("stl string");
 #endif</p><p>  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"
 }</p><p>(七)技巧:
 1.有时候我们只想观察某一个变量的变化,但程序里有很多trace,所以输出到窗口的
   数据影响了我们的观察。这是我们可以这样做,就能令其他trace都无效了。</p><p>   BEGINTRACE;  //接收数据
   trace(_T("只有 BEGINTRACE 和 ENDTRACE 之间的trace才有效"));
   ENDTRACE;  //禁止接收数据</p><p>
版权声明:
 没有版权,许可任何单位,个人随意使用,拷贝,修改,但作者不承担由
 此代码带来的任何损失。由于作者水平有限,错误或不完善之处,在
 所难免,由此为你带来的不便,还望海涵。如果有任何BUG,请联系作者,
 大家一起完善它!以后有更新统一放在以下网址上,你可以浏览并获得
 更新以及详细的使用说明:
 当前更新日期:2011-10-21
 <a href="http://blog.csdn.net/jacky_qiu/archive/2010/11/04/5986089.aspx">http://blog.csdn.net/jacky_qiu/archive/2010/11/04/5986089.aspx</a></p><p>最后:
 如果此份代码为你带来了帮助,并且使你心生感谢之意。那我可否请你
 诚心恭敬地念10遍“南(音:拿na)无(音:摩mo)阿弥陀佛”?
 愿得佛力加持,使你工作顺利,合家幸福!
 
           Jacky
           2011-11-7
           <a href="mailto:qiujiejia@gmail.com">qiujiejia@gmail.com</a></p><p>========================================================================*/</p><p> </p><p>
#ifndef _EASY_TRACE_H_
#define _EASY_TRACE_H_</p><p>
//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</p><p>//trace宏的参数是4个,当参数少于4个,编译器会给出警告,我们手动关闭这个
//警告(disable warning C4003: not enough actual parameters for macro)
#pragma warning(disable: 4003)
#pragma warning(disable: 4002)</p><p>
#define TRACE_WND_TEXT _T("TraceWnd") //窗口标题
#define AUTO_HIDE_TIME 3000   //定义多少毫秒后自动窗口</p><p>#include <Windows.h> //需要的头文件
#include <tchar.h>
#include <sstream>
#ifndef ASSERT
#include <crtdbg.h> 
#define ASSERT(X) _ASSERT(X);
#endif</p><p>//Not #define TRACE_WINDOW
#ifndef TRACE_WINDOW 
#define trace(X)
#define tracef __noop
#define traceLastError() 
#define traceRel(X)   
#define traceClear(X)    
#define BEGINTRACE  
#define ENDTRACE  
#endif</p><p>
//#define TRACE_WINDOW
#ifdef TRACE_WINDOW </p><p>//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━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); }</p><p>#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 BEGINTRACE   { CTraceWnd::ConfigData().IsReceive=true;  }
#define ENDTRACE   { CTraceWnd::ConfigData().IsReceive=false;  }
//━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</p><p> </p><p>class CTraceWnd
{
 struct TRACEWNDCONFIG
 {
  int  x;
  int  y;
  int  cx;
  int  cy;
  BOOL IsContinue ; //当输出字符串时是否清空之前的数据
  BOOL IsAutoWidth ; //是否根据字符串长度自动调整窗口宽度
  BOOL IsAutoHide ; //是否自动隐藏
  BOOL IsHide  ; //是否隐藏
  BOOL IsName  ; //是否自动补上变量名
  BOOL IsIndex  ; //添加行号索引
  BOOL IsSplitter ; //2条字符串输入时间差大于1秒时添加分隔符
  BOOL IsDeleteBefore; //2条字符串输入时间差大于1秒时删除前面的所有输出字符串
  BOOL IsReceive ; //是否接受数据
 };</p><p>public:
 ~CTraceWnd(){ ::DestroyWindow(::FindWindow(NULL,TRACE_WND_TEXT)); }
 </p><p> static int& IndexNum()
 {
  static int num=1;
  return num;
 }</p><p> static HWND& SaveEditWnd()
 {
  static HWND wnd=NULL;
  return wnd;
 }
 
 static TRACEWNDCONFIG& ConfigData()
 {
  static TRACEWNDCONFIG config={ 0 , 0, 400, 400 , TRUE , FALSE , FALSE , FALSE , TRUE , TRUE , FALSE , FALSE , TRUE };
  return config;
 }</p><p> /****************************************************************************
 行首序列号
 ****************************************************************************/
 static TCHAR* GetIndex()
 {
#define _INDEX_NUM_MAX 4
  static TCHAR SrcIndex[11]={0};
  static TCHAR NewIndex[_INDEX_NUM_MAX+1]={' ',' ',' ',' ',0};</p><p>  //reset NewIndex buffer
  if ( IndexNum()==1 )
   for( int i=0 ;i < _INDEX_NUM_MAX ; i++ )
    NewIndex[i]=' ';</p><p>  _itot( IndexNum()++,SrcIndex,10);//int 转文本
  int len=_tcslen(SrcIndex);
  int count=  _INDEX_NUM_MAX  -len;    // 4 - 对齐的位数
  if (count>0)
  {
   for ( int i= count , j=0 ; i< _INDEX_NUM_MAX ;i++ ,j++) 
    NewIndex[i]=SrcIndex[j];</p><p>   return NewIndex;
  }
  else
   return SrcIndex;
 }</p><p>
 /****************************************************************************
 输出的字符串到窗口
 ****************************************************************************/
 static void CTraceWnd::PrintString(const TCHAR* OutputStr)
 {
  if ( SaveEditWnd()==NULL )
  {
   //寻找已创建的输出窗口
   HWND MainWnd=::FindWindow(NULL,TRACE_WND_TEXT);</p><p>   //如果不存在,则创建窗口并初始化设置
   if ( !MainWnd )
   {
    //定义这个对象是为了程序退出是调用析构函数来
    //保存文件和关闭窗口,除此之外没有其他用处了
    static CTraceWnd ForGetCloseMessage;</p><p>    //创建窗口
    MainWnd= CreateMainWnd() ;
    SaveEditWnd()=CreateEditWnd(MainWnd);</p><p>    if (!MainWnd) 
    {
     ::MessageBox(::GetFocus(),_T("无法创建trace窗口"),NULL,MB_OK);
     return;
    }
   }
  }</p><p>  if ( CTraceWnd::ConfigData().IsReceive==false ) 
   return ;</p><p>  //将字符串输出到窗口
  ::SendMessage(  SaveEditWnd() , EM_REPLACESEL,FALSE,(LPARAM)OutputStr); 
 }</p><p> /****************************************************************************
 //保存窗口配置
 ****************************************************************************/
 static void SaveConfig(TRACEWNDCONFIG& config)
 {
  HKEY hKey;
  if (::RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\") ,0,KEY_WRITE,&hKey)==ERROR_SUCCESS )
  {
   ::RegSetValueEx(hKey,_T("config"),0,REG_BINARY,(LPBYTE)&config,sizeof(config));
   ::RegCloseKey(hKey);
  }
 }
 
 static BOOL GetConfig(TRACEWNDCONFIG& config)
 {
  HKEY hKey;
  long ret=::RegOpenKeyEx(HKEY_CURRENT_USER,  _T("Software\\") ,0,KEY_READ,&hKey);
  if ( ret==ERROR_SUCCESS )
  {
   DWORD type=REG_BINARY;
   DWORD cbData=sizeof(config);
   ::RegQueryValueEx(hKey,_T("config"),0,&type,(LPBYTE)&config,&cbData);
   ::RegCloseKey(hKey);
   return TRUE;
  }</p><p>  return FALSE;
 }</p><p> static void ShowTraceWnd()
 {
  ::SetWindowPos( ::FindWindow(NULL,TRACE_WND_TEXT) ,HWND_TOPMOST, 
   ConfigData().x,ConfigData().y,ConfigData().cx,ConfigData().cy,  SWP_NOACTIVATE);
  ConfigData().IsHide=false;
 }</p><p> static void HideTraceWnd()
 {
  ::SetWindowPos( ::FindWindow(NULL,TRACE_WND_TEXT) ,HWND_TOPMOST,-100,0,104,GetSystemMetrics(SM_CYSCREEN),NULL);
  ConfigData().IsHide=true;
 }</p><p>
 static HWND CreateEditWnd(  HWND ParentWnd )
 {
  RECT rect;
  ::GetClientRect(ParentWnd,&rect);</p><p>  HWND EditWnd=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW,TEXT("Edit"),TRACE_WND_TEXT ,
   WS_CHILD|WS_VSCROLL|WS_HSCROLL|WS_VISIBLE|
   ES_AUTOHSCROLL|ES_WANTRETURN|ES_MULTILINE , 
   0,0,rect.right,rect.bottom,
   ParentWnd,NULL,NULL,NULL);</p><p>  //把hWnd的默认窗口过程替换为WindowProc,返回默认函数过程的函数指针
  WNDPROC OldWndProc=(WNDPROC)SetWindowLongPtr(EditWnd,GWLP_WNDPROC, (LONG_PTR)EditWindowProc);
  ASSERT(OldWndProc);
  //保存OldWndProc
  ::SetWindowLongPtr(EditWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(OldWndProc));</p><p>  
  //修改edit框的限制字符个数
  ::SendMessage(EditWnd,EM_SETLIMITTEXT,1000000, 0);</p><p>  //清空Edit
  ::SendMessage(EditWnd,WM_SETTEXT,NULL,(LPARAM)_T("")); </p><p>  // 设置字体参数
  LOGFONT LogFont;
  ::memset(&LogFont, 0, sizeof(LOGFONT));
  lstrcpy(LogFont.lfFaceName,_T("Fixedsys"));
  LogFont.lfHeight = -12; // 字体大小
  LogFont.lfCharSet = GB2312_CHARSET;
  // 创建字体
  HFONT hFont=CreateFontIndirect(&LogFont); 
  // 设置字体
  ::SendMessage(EditWnd, WM_SETFONT, (WPARAM)hFont, 0); </p><p>  ::PostMessage(EditWnd, WM_RBUTTONDOWN,NULL,MAKELPARAM(-10000,-10000));</p><p>  return EditWnd;
 }</p><p>
 static HWND CreateMainWnd()
 {
  TRACEWNDCONFIG& config=ConfigData();</p><p>  GetConfig( config ) ;
  config.IsReceive=true;
  </p><p>  //超出屏幕重新调整
  int SrcCx=GetSystemMetrics(SM_CXSCREEN);
  int SrcCy=GetSystemMetrics(SM_CYSCREEN);
  if (config.x<0 || config.x>=SrcCx) config.x=0;
  if (config.y<0 || config.y>=SrcCy) config.y=0;
  if (config.cx<100) config.cx=100;
  if (config.cy<40) config.cy=40;
  if (config.x+config.cx>SrcCx) config.x=SrcCx-config.cx;
  if (config.y+config.cy>SrcCy) config.y=SrcCy-config.cy;</p><p>  
  //━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  HWND hWnd;
  if (config.IsHide)  //如果窗口是隐藏状态
  {
   hWnd=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW,_T("#32770"),TRACE_WND_TEXT ,
    WS_OVERLAPPEDWINDOW , 
    -100, 0 , 104 ,  GetSystemMetrics(SM_CYSCREEN) , NULL,NULL,NULL,NULL);
  }
  else
  {
   hWnd=CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW,_T("#32770"),TRACE_WND_TEXT ,
    WS_OVERLAPPEDWINDOW , 
    config.x,config.y,config.cx,config.cy,   NULL,NULL,NULL,NULL);
  }</p><p>  ::ShowWindow(hWnd,SW_SHOWNOACTIVATE); //显示时无焦点</p><p>  //ASSERT(hWnd);
  if (hWnd==NULL)
   return NULL;</p><p>  //把hWnd的默认窗口过程替换为WindowProc,返回默认函数过程的函数指针
  WNDPROC OldWndProc=(WNDPROC)SetWindowLongPtr(hWnd,GWLP_WNDPROC, (LONG_PTR)MainWindowProc);
  ASSERT(OldWndProc);
  //保存OldWndProc
  ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(OldWndProc));
  //━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</p><p> </p><p>  //━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━创建菜单
  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, 12, _T("2条字符串输入时间差大于1秒时添加分隔符"));
  AppendMenu(hSubMenu,MF_STRING, 13, _T("2条字符串输入时间差大于1秒时删除前面的所有输出字符串"));
  AppendMenu(hSubMenu,MF_STRING, 8,  _T("帮助"));
  //-----------------sub menu
  AppendMenu(hMenu, MF_POPUP,UINT(hSubMenu), _T("选项")) ;
  ::SetMenu(hWnd,hMenu); 
  //━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</p><p>  return hWnd;
 }</p><p> </p><p> static LRESULT CALLBACK MainWindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
 {
  TRACEWNDCONFIG& config=ConfigData();</p><p>  switch(message)
  {</p><p>  case WM_COMMAND:
   ::SendMessage( ::GetWindow(hWnd, GW_CHILD) , WM_COMMAND, wParam , lParam );
   break;</p><p>  case WM_CLOSE:
   ::DestroyWindow(hWnd);
   break;</p><p>  case WM_DESTROY:
   DestroyMenu(GetMenu(hWnd));
   break;</p><p>  case WM_SIZE:
   {
    int cx=LOWORD(lParam);
    int cy=HIWORD(lParam);
    ::SetWindowPos( ::GetWindow(hWnd, GW_CHILD) ,NULL,0,0,cx,cy,SWP_NOMOVE);
   }
   break;</p><p>  case WM_INITMENUPOPUP:
   {
    HMENU hSubMenu=(HMENU)wParam;
    CheckMenuItem(hSubMenu,6, MF_BYCOMMAND | config.IsAutoHide ? MF_CHECKED : MF_UNCHECKED );
    CheckMenuItem(hSubMenu,7, MF_BYCOMMAND | config.IsReceive  ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hSubMenu,4, MF_BYCOMMAND | config.IsAutoWidth? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hSubMenu,9, MF_BYCOMMAND | config.IsContinue ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hSubMenu,10,MF_BYCOMMAND | config.IsName     ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hSubMenu,11,MF_BYCOMMAND | config.IsIndex    ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hSubMenu,12,MF_BYCOMMAND | config.IsSplitter ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hSubMenu,13,MF_BYCOMMAND | config.IsDeleteBefore ?MF_CHECKED : MF_UNCHECKED);
   }
   break;</p><p> </p><p>  case WM_NCLBUTTONDOWN:
   {
    POINT point={ LOWORD(lParam),HIWORD(lParam) };
    UINT nHitTest =wParam;</p><p>    RECT rect={-10000,0,0,0};</p><p>    if (   nHitTest== HTTOPLEFT  || nHitTest== HTTOPRIGHT 
     || nHitTest== HTBOTTOMLEFT || nHitTest== HTBOTTOMRIGHT 
     || nHitTest== HTLEFT  || nHitTest== HTRIGHT 
     || nHitTest== HTTOP   || nHitTest== HTBOTTOM 
     || nHitTest== HTCAPTION )
    {
     ::GetWindowRect(hWnd,&rect);
    }</p><p>    LRESULT ret=DefWindowProc(hWnd,message,wParam,lParam);</p><p>    if ( config.IsHide )
    {
     ShowTraceWnd(); //重新显示窗口
    }</p><p>    if ( rect.left!=-10000 )
    {
     RECT NewRect;
     ::GetWindowRect(hWnd,&NewRect);
     if ( 0!=memcmp(&rect,&NewRect,sizeof(rect)))
     {
      config.x=NewRect.left;
      config.y=NewRect.top;
      config.cx=NewRect.right-NewRect.left;
      config.cy=NewRect.bottom-NewRect.top;</p><p>      SaveConfig(config);
     }
    }</p><p>    return ret;
   }
   break;</p><p>
  default:
   {
    WNDPROC  OldWndProc= reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
    ASSERT(OldWndProc!=NULL);
    return ::CallWindowProc(OldWndProc, hWnd, message, wParam, lParam); 
   }
  }</p><p>  return 0;
 }</p><p>
 /****************************************************************************
 Edit Window的窗口过程
 ****************************************************************************/
 static LRESULT CALLBACK EditWindowProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
 {
  static HWND  StaticWnd  = NULL; //</p><p>  TRACEWNDCONFIG& config=ConfigData();</p><p>  switch(message)
  {
/*
  case WM_ACTIVATE:
   {
    if (LOWORD(wParam)==WA_INACTIVE ) //窗口失去焦点
    {
     if (config.IsAutoHide)
     {
      ::SetTimer(hWnd,1,200,NULL); //延长200ms后hide
     }
    }
   }
   break;
*/</p><p>  case WM_RBUTTONDOWN:
   {
    if ( lParam==MAKELPARAM(-10000,-10000) )
    {
     //如果没有开启自动隐藏并且又处于隐藏状态,则弹出提示窗口
     if (!config.IsAutoHide && config.IsHide)
     {
      StaticWnd=CreateWindowEx( WS_EX_TOOLWINDOW|WS_EX_TOPMOST&~WS_EX_APPWINDOW, //取消任务栏标题
       _T("Static"),
       _T("Trace窗口隐藏在屏幕左边\n点击屏幕左边可恢复窗口"),
       WS_POPUP|WS_VISIBLE|WS_BORDER|
       SS_CENTER ,
       0,200,200,40,NULL,NULL,NULL,NULL); </p><p>      SetTimer(hWnd,2,2000,NULL);
     }
    }
   }
   break;</p><p>  case WM_TIMER:
   {
    if (wParam==2) //关闭提示窗口
    {
     ::DestroyWindow(StaticWnd); 
     ::KillTimer(hWnd,2);
     break;
    }</p><p>    if ( !config.IsHide && ::GetForegroundWindow()!=GetParent(hWnd) )
    {
     HideTraceWnd(); //隐藏窗口
    }
   }
   break;
  </p><p>  case WM_COMMAND:
   {
    switch(wParam)
    {
    case 3//清空内容
     {
      IndexNum()=1;
      ::SendMessage( hWnd ,WM_SETTEXT,NULL,(LPARAM)_T("")); 
     }
     break;</p><p>    case 8:  
     ::SendMessage(  hWnd ,WM_SETTEXT,NULL,(LPARAM)_T("帮助及更新:\r\nhttp://blog.csdn.net/jacky_qiu/article/details/5986089 \r\n下载更新代码可到qq邮箱:<a href="mailto:vcshare@qq.com">vcshare@qq.com</a>(密码:share88) \r\n\r\n\t\tEmail: <a href="mailto:qiujiejia@gmail.com">qiujiejia@gmail.com</a>")); 
     break;</p><p>    case 5//hide window int the left of the screen
     {
      HideTraceWnd(); //隐藏窗口</p><p>      //隐藏窗口后要禁止自动隐藏
      config.IsAutoHide=false;
      KillTimer(hWnd,1);
      SaveConfig(config);
     }
     break;</p><p>    case 4//modify the Auto Adjust window width option
     {
      config.IsAutoWidth=!config.IsAutoWidth;
      SaveConfig(config);
     }
     break;</p><p>    case 6//modify the Auto hide window option
     {
      config.IsAutoHide=!config.IsAutoHide;
      if(config.IsAutoHide) 
       ::SetTimer( hWnd ,1,AUTO_HIDE_TIME,NULL);
      else   
       ::KillTimer(hWnd,1);</p><p>      SaveConfig(config);
     }
     break;</p><p>    case 7//modify the receivd date option
     {
      if(config.IsReceive)
       PrintString( _T("\r\n注意:当前处于禁止接收数据状态\r\n") );
      config.IsReceive=!config.IsReceive;
      SaveConfig(config);
     }
     break;</p><p>    case 9//modify the receivd date option
     {
      config.IsContinue=!config.IsContinue;
      SaveConfig(config);
     }
     break;</p><p>    case 10:  
     {
      config.IsName=!config.IsName;
      SaveConfig(config);
     }
     break;</p><p>    case 11:  
     {
      config.IsIndex=!config.IsIndex;
      SaveConfig(config);
     }
     break;
    case 12:  
     {
      config.IsSplitter=!config.IsSplitter;
      if (config.IsSplitter) config.IsDeleteBefore=FALSE;
      SaveConfig(config);
     }
     break;
    case 13:  
     {
      config.IsDeleteBefore=!config.IsDeleteBefore;
      if (config.IsDeleteBefore) config.IsSplitter=FALSE;
      SaveConfig(config);
     }
     break;
    }
   }
   break;</p><p>  case EM_REPLACESEL:
   {
    if(!config.IsReceive) 
     return 0;</p><p>    if (config.IsContinue)
    {
     //光标指向最后
     ::SendMessage(hWnd,EM_SETSEL,4294967290, 4294967290); </p><p>     WNDPROC  OldWndProc= reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));</p><p>     if (config.IsSplitter)
     {
      static DWORD begin;
      DWORD end=GetTickCount();</p><p>      if (end-begin>1000)
      {
       TCHAR fen[]=_T("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\r\n");
       TCHAR* outputstr=(TCHAR*)lParam;
       int len=_tcslen(outputstr);
       TCHAR* p=new TCHAR[ len  + sizeof(fen)/sizeof(TCHAR) ];
       _tcscpy(p,fen);
       _tcscpy( p  + sizeof(fen)/sizeof(TCHAR) -1   , outputstr);</p><p>       //调用默认过程添加字符串到edit 窗口
       ::CallWindowProc(OldWndProc, hWnd, message, wParam, (LPARAM)p); </p><p>       delete p;
      }
      else
       ::CallWindowProc(OldWndProc, hWnd, message, wParam, lParam); </p><p>      begin=end;
     }
     else if (config.IsDeleteBefore)
     {
      static DWORD begin;
      DWORD end=GetTickCount();</p><p>      if (end-begin>1000)
      {
       ::SetWindowText( hWnd , (TCHAR*)lParam );
      }
      else
       ::CallWindowProc(OldWndProc, hWnd, message, wParam, lParam); </p><p>      begin=end;
     }
     else
     {
      ::CallWindowProc(OldWndProc, hWnd, message, wParam, lParam); 
     }
    }
    else
    {
     ::SendMessage(hWnd,WM_SETTEXT,NULL,lParam);
    }
    
    
    //开启了自动隐藏功能
    if (config.IsAutoHide)
    {
     if (config.IsHide)
     {
      ShowTraceWnd(); //重新显示窗口
     }</p><p>     //设置AUTO_HIDE_TIME后隐藏窗口
     ::SetTimer( hWnd ,1,AUTO_HIDE_TIME,NULL);
    }</p><p>    //开启了自动调整窗口的宽度功能
    if (config.IsAutoWidth)
    {
     if (!config.IsHide)
     {
      static int m_WindowWidth = 200//窗口宽度</p><p>      int MinPos,MaxPos;
      GetScrollRange(hWnd,SB_HORZ, &MinPos,&MaxPos);
      if (m_WindowWidth<MaxPos+40)
      {
       HWND ParentWnd=GetParent(hWnd);</p><p>       m_WindowWidth=MaxPos+40;
       RECT rect; 
       ::GetWindowRect(ParentWnd,&rect);
       ::SetWindowPos(ParentWnd,NULL,0,0,m_WindowWidth,rect.bottom-rect.top,SWP_NOMOVE|SWP_NOACTIVATE);
      }
     }
    }
   }
   break;</p><p>  case WM_DESTROY:
   {
    IndexNum()=1;
    SaveEditWnd()=NULL;</p><p>    //删除字体
    DeleteObject( (HFONT)::SendMessage(hWnd,WM_GETFONT,0,0) );</p><p>    //设置程序运行的目录跟程序文件所在目录相同
    //当我们的程序被其他程序打开时,它的工作目录和打开它的那。
    //个程序的目录是相同的。所以我们需要把目录改回来
    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;</p><p> </p><p>  case WM_KEYDOWN:
   {
    //select all
    if (wParam=='A' && GetKeyState(VK_CONTROL)<0)
     ::SendMessage(hWnd,EM_SETSEL,0,-1);
   }
   break;</p><p> </p><p>  default:
   {
    WNDPROC  OldWndProc= reinterpret_cast<WNDPROC>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));
    ASSERT(OldWndProc!=NULL);
    return ::CallWindowProc(OldWndProc, hWnd, message, wParam, lParam); 
   }
  }</p><p>  return 0;
 }
};</p><p> </p><p> </p><p>/****************************************************************************
CEasyTrace
****************************************************************************/
class CEasyTrace
{
private:</p><p>#ifdef _UNICODE 
 std::wostringstream m_str;
#else 
 std::ostringstream m_str;
#endif </p><p>public:
 void add(){}  //当trace宏参数不足时会调用此函数
 void name(){}  //当trace宏参数不足时会调用此函数</p><p> //初始化一个ostringstream对象并且添加序列号
 CEasyTrace() 
 { 
  if ( CTraceWnd::ConfigData().IsIndex )
   m_str<<CTraceWnd::GetIndex()<<_T("  ");    
  else
   m_str<<_T("  ");    
 }</p><p> //析构时将字符串输出到Edit窗口
 ~CEasyTrace()
 {
  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 
 }</p><p> //输出变量名
 void name(char* pStr)
 {
  if(!CTraceWnd::ConfigData().IsName) return;</p><p>  if (strchr(pStr,'\"')!=NULL) return;
#ifdef _UNICODE 
  wchar_t* UnicodeStr=AnsiToUnicode(pStr);
  m_str<<UnicodeStr<<_T("=");
  delete[] UnicodeStr;
#else
  m_str<<pStr<<_T("=");
#endif
 }</p><p> //输出一般类型的变量
 template <class T> void add(T t)  { m_str<<t<<_T("\t"); }</p><p> //输出point
 void add(POINT point) { m_str<<(_T("("))<<point.x<<(_T(","))<<point.y<<(_T(")\t")); }</p><p> //输出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")); }</p><p> //输出窗口信息
 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);</p><p>  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(); }</p><p> //输出函数执行的结果
 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)") ); 
 }</p><p> //输出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 </p><p> //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;
 }</p><p> //输出格式化字符串,类似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); //输出字符串
 }
};</p><p>
#endif // #define TRACE_WINDOW
#endif // #define _EASY_TRACE_H_
</p>

 

原文地址:https://www.cnblogs.com/ArRan/p/2842767.html