zoukankan      html  css  js  c++  java
  • 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>

     

  • 相关阅读:
    ubuntu下cmake自动化编译的一个例子
    KL变换和PCA的数学推导
    tensorflow c++ API加载.pb模型文件并预测图片
    tensorflow c++接口的编译安装与一些问题记录
    深度增强学习--总结下吧
    深度增强学习--DPPO
    深度增强学习--DDPG
    深度增强学习--A3C
    tomcat远程调试
    springboot问题记录
  • 原文地址:https://www.cnblogs.com/ArRan/p/2842767.html
Copyright © 2011-2022 走看看