如何在调试时获取CEdit(或CWnd)文本

时间:2013-07-25 09:28:36

标签: c++ oop debugging visual-c++ mfc

当我调试我的项目时,CEdit对象的文本被更改,我希望看到新值。但是监视窗口不显示文本成员 文本存储在哪里?

编辑:我忘了写我使用的是Visual C ++ 6.0('98版)

观察窗口中的CEdit树如下所示:

m_editBox
|  
+ [CWnd]  
  |  
  + CCmdTarget  
  + classCWnd
  + m_hWnd  
  + wndTop
  + wndBottom
  + wndTopMost
  + wndNoTopMost
  + m_hWndOwner
  - m_nFlags
  - m_pfnSuper
  - m_nMsgDragList
  - m_nModalResult
  + m_pDropTarget
  + m_pCtrlCont
  + m_pCtrlSite
  + _messageEntries
  + messageMap
+ CWnd
  |
  + CCmdTarget
  + m_hWnd
  + m_hWndOwner
  - m_nFlags
  - m_pfnSuper
  - m_nModalResult
  + m_pDropTarget
  - m_pCtrlCont
  - m_pCtrlSite

4 个答案:

答案 0 :(得分:1)

回答你提前存储窗口文本的问题:我真的不知道,也没有任何给定的窗口。要获得该信息,您必须向窗口管理员询问。

与窗口有关的所有信息都存储在由窗口管理器维护的内部结构中。窗口管理器由Win32k.sys实现,因此这些内部结构驻留在内核内存中。 HWND用作窗口管理器控制的表的索引。即使表条目以只读方式映射到用户空间内存中,获取所需信息也相当繁琐。

到目前为止,非常糟糕。然而,并非所有人都失去了。您仍然可以获得所需的信息。

最简单的选择是使用Spy ++(Spyxx.exe)。它作为Visual Studio的一部分提供,有助于检索窗口特定信息,其他方面它将显示窗口的文本。根据您的要求,您将转到 Spy - > 查找窗口... (或按 [Ctrl] + F )并输入窗口的句柄(不带0x前缀的十六进制)。但是,该信息不会自动刷新。您需要手动单击刷新按钮。

如果您想在Visual Studio的调试器中获得实时信息,则必须编写调试器表达式评估插件。 Microsoft未正式支持表达式评估程序。因此,没有官方文件。如果您想沿着这条路线前进,How to write a custom native visualizer DLL for Visual Studio 2012 debugger?会提供有用的信息。显示窗口文本条目的表达式计算器如下所示:

HwndEEAddin.h:

// HwndEEAddin.h : main header file for the NatvisAddIn DLL
//

#if !defined( INC_HWNDEEADDIN_H_ )
#define INC_HWNDEEADDIN_H_

#pragma once

#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
#include <windows.h>


#define ADDIN_API extern "C" __declspec(dllexport)

/* DebugHelper structure used from within the */
typedef struct tagDEBUGHELPER
{
  DWORD dwVersion;
  BOOL (WINAPI *ReadDebuggeeMemory)( struct tagDEBUGHELPER *pThis, DWORD dwAddr, DWORD nWant, VOID* pWhere, DWORD *nGot );
  // from here only when dwVersion >= 0x20000
  unsigned __int64 (WINAPI *GetRealAddress)( struct tagDEBUGHELPER *pThis );
  BOOL (WINAPI *ReadDebuggeeMemoryEx)( struct tagDEBUGHELPER *pThis, unsigned __int64 qwAddr, DWORD nWant, VOID* pWhere, DWORD *nGot );
  int (WINAPI *GetProcessorType)( struct tagDEBUGHELPER *pThis );
} DEBUGHELPER;

/* Exported Functions */
ADDIN_API HRESULT WINAPI AddIn_HWND( DWORD dwAddress, DEBUGHELPER *pHelper, int nBase, BOOL bUniStrings, char *pResult, size_t maxResult, DWORD reserved );

#endif  // !defined( INC_HWNDEEADDIN_H_ )

HwndEEAddin.cpp:

#include "HwndEEAddin.h"

#include <strsafe.h>


ADDIN_API HRESULT WINAPI AddIn_HWND( DWORD dwAddress, DEBUGHELPER* pHelper, int /*nBase*/, BOOL bUniStrings, char *pResult, size_t maxResult, DWORD /*reserved*/ )
{
  HRESULT hr = E_FAIL;

  HWND hWnd = reinterpret_cast< HWND >( dwAddress );
  if ( hWnd != NULL )
  {
    bool bGotWindowText = false;

    CHAR asciiWindowText[ 128 ] = { 8 };
    if ( IsWindowUnicode( hWnd ) )
    {
      WCHAR buffer[ 128 ] = { 0 };
      if ( GetWindowTextW( hWnd, buffer, ARRAYSIZE( buffer ) ) )
      {
        if ( WideCharToMultiByte( CP_THREAD_ACP, 0x0, buffer, -1, asciiWindowText, ARRAYSIZE( asciiWindowText ), NULL, NULL ) > 0 )
        {
          bGotWindowText = true;
        }
      }
    }
    else
    {
      if ( GetWindowTextA( hWnd, asciiWindowText, ARRAYSIZE( asciiWindowText ) ) )
      {
        bGotWindowText = true;
      }
    }

    if ( bGotWindowText )
    {
      hr = StringCbPrintfA( pResult, maxResult, "{pText=\"%s\"}", asciiWindowText );
    }
  }

  return hr;
}

要在Visual Studio 2010及更高版本中注册插件,您必须将.dll与以下文件一起复制到%USERPROFILE%\ Documents \ Visual Studio 2012 \ Visualizers。

HwndEEAddin.natvis:

<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">

  <!-- Place this file and the AddIn-DLL to this folder: %USERPROFILE%\My Documents\Visual Studio 2012\Visualizers\ -->

  <Type Name="HWND__">
    <DisplayString LegacyAddin="HwndEEAddin.dll" Export="_AddIn_HWND@28"></DisplayString>
  </Type>

</AutoVisualizer>

在2010之前的Visual Studio版本中,您必须通过将以下条目添加到[AutoExpand]部分来编辑autoexp.dat:

HWND__ = $ADDIN(HwndEEAddin.dll,_AddIn_HWND@28)

.dll必须位于devenv.exe目录或PATH上。否则,您将必须使用完全限定的路径名​​。有关VS 2010之前的Visual Studio Expression Evaluators的更多信息,请访问Customizing the Visual Studio Debugger Display of Your Data

答案 1 :(得分:0)

实际文本保存在控件的某种相关内存中,而这些内存无法直接访问。您只有控件的句柄HWND包含在CEdit类中。为了从那里获取文本,您需要提前从代码CEdit::GetWindowText进入本地内存,然后使用调试器进行检查。

答案 2 :(得分:0)

如果要查看新值,则必须使用变量并从窗口中检索文本。

CString text;
GetDlgItemText(ID, text);

答案 3 :(得分:-1)

CEdit的“GetWindowText”方法LITERALLY发送一个Windows消息来获取文本,而不是用文本的简单访问器方法调用函数.m_hWnd是O /深内部的一些数据结构的“句柄” S只有窗口的操作系统代码知道如何检索文本。

我希望它更简单,但MFC只是Win32 API的包装器。您可以尝试使用C#,它可以更好地将UI呈现为对象(与间接访问的C / Pascal /程序集结构的包装器相比)