UI 控件数据侦探
一个用于从 TreeCtrl、ListCtrl、ComboBox、ListBox 等控件捕获数据的工具。
引言
这是一个用于从 UI 控件捕获文本数据的工具。这些控件包括 TreeCtrl、ListCtrl、ComboBox、ListBox、HeaderCtrl、Edit 等。例如,可以以文本格式获取 Windows 资源管理器文件夹树数据和文件夹列表数据。
用法
定位窗口类似于 Microsoft Spy++。以下部分将逐步描述使用方法。
- 可以使用 Finder 工具定位 控件 或 窗口。 它可以被点击并拖动到任何窗口,相应的窗口将被突出显示。 此外,可以从 窗口树 中定位窗口。
- 单击 获取数据 按钮将捕获所选窗口(控件)的数据。
- 捕获的数据可以从“获取数据”按钮下方的文本区域中选择和复制,或者只需单击 复制数据 按钮即可。
此外,选项 最小顶部 确定是否搜索面积最小的窗口。 当必须定位被组框包围的控件时,它很有用。 如果未选择此项,将使用简单的 WindowFromPoint
API 进行搜索。
此外,可以通过单击 闪烁 按钮来确认定位的窗口。 另一种方法是右键单击 窗口树 并在上下文菜单中选择 闪烁。
从 ListCtrl 和 TreeCtrl 捕获的数据使用 TAB 作为分隔符。 这有助于轻松管理数据,以便在 MS Word 或 Excel 中粘贴和格式化。 下图显示了这一点
从 Windows 资源管理器捕获了 Windows\System 文件夹。 然后将其粘贴并格式化为 MS Word 中的表格,如下所示
关注点
通过“最小顶部”方法定位窗口非常有趣。 为此,首先需要鼠标光标下的窗口。 之后,将检查位于相同鼠标光标位置的该窗口的所有兄弟窗口的面积(宽度 x 高度)。 从这一点,将确定面积最小的窗口。 主要的代码片段如下
HWND hWnd = ::WindowFromPoint( point );
CPoint pointClient( point ); // mouse cursor position
::ScreenToClient( hWnd, &pointClient );
HWND hWndChild = ::ChildWindowFromPoint( hWnd, pointClient );
if(( 0 != hWndChild ) && ::IsWindowVisible( hWndChild ))
{
hWnd = hWndChild;
}
// smallest top window search
if( m_bFindSmallestTop )
{
DWORD dwWndArea = MAXDWORD;
// avoid top level windows
HWND hWndParent = ::GetParent( hWnd );
if( 0 != hWndParent )
{
if( 0 == ( ::GetWindowLong( hWnd, GWL_STYLE ) & WS_POPUP ))
{
// walk through child windows
HWND hWndChild = ::GetWindow( hWndParent, GW_CHILD );
while( 0 != hWndChild )
{
// ignore hidden windows
if( ::IsWindowVisible( hWndChild ))
{
// window under the point
CRect rect;
::GetWindowRect( hWndChild, &rect );
if( rect.PtInRect( point ))
{
// find smallest
DWORD dwChildArea = rect.Width() * rect.Height();
if( dwChildArea < dwWndArea )
{
dwWndArea = dwChildArea;
hWnd = hWndChild;
}
}
}
hWndChild = ::GetWindow( hWndChild, GW_HWNDNEXT );
}
}
}
}
为了从不同的控件(如 ListCtrl、TreeCtrl 等)捕获数据,应该在那个窗口的进程的虚拟地址空间内分配内存。 一个名为 ProcMem
的类被用于此目的。 它将做必要的事情来简单地处理进程内存。 类声明如下
class ProcMem
{
public:
ProcMem( HWND hWnd );
virtual ~ProcMem();
LPVOID Allocate( DWORD dwSize );
BOOL Write( LPVOID lpProcMem, LPVOID lpLocalMem, DWORD dwSize );
BOOL Read( LPVOID lpProcMem, LPVOID lpLocalMem, DWORD dwSize );
private:
HANDLE m_hProcess;
CArray<LPVOID, LPVOID> m_arrayMemoryAllocated;
};
历史
- 初始版本。