65.9K
CodeProject 正在变化。 阅读更多。
Home

UI 控件数据侦探

starIconstarIconstarIconstarIconstarIcon

5.00/5 (12投票s)

2009年10月1日

CPOL

2分钟阅读

viewsIcon

59639

downloadIcon

5028

一个用于从 TreeCtrl、ListCtrl、ComboBox、ListBox 等控件捕获数据的工具。

引言

这是一个用于从 UI 控件捕获文本数据的工具。这些控件包括 TreeCtrl、ListCtrl、ComboBox、ListBox、HeaderCtrl、Edit 等。例如,可以以文本格式获取 Windows 资源管理器文件夹树数据和文件夹列表数据。

用法

定位窗口类似于 Microsoft Spy++。以下部分将逐步描述使用方法。

  1. 可以使用 Finder 工具定位 控件窗口。 它可以被点击并拖动到任何窗口,相应的窗口将被突出显示。 此外,可以从 窗口树 中定位窗口。
  2. 单击 获取数据 按钮将捕获所选窗口(控件)的数据。
  3. 捕获的数据可以从“获取数据”按钮下方的文本区域中选择和复制,或者只需单击 复制数据 按钮即可。

此外,选项 最小顶部 确定是否搜索面积最小的窗口。 当必须定位被组框包围的控件时,它很有用。 如果未选择此项,将使用简单的 WindowFromPoint API 进行搜索。

此外,可以通过单击 闪烁 按钮来确认定位的窗口。 另一种方法是右键单击 窗口树 并在上下文菜单中选择 闪烁

从 ListCtrl 和 TreeCtrl 捕获的数据使用 TAB 作为分隔符。 这有助于轻松管理数据,以便在 MS Word 或 Excel 中粘贴和格式化。 下图显示了这一点

scrn2.png

从 Windows 资源管理器捕获了 Windows\System 文件夹。 然后将其粘贴并格式化为 MS Word 中的表格,如下所示

scrn2.png

关注点

通过“最小顶部”方法定位窗口非常有趣。 为此,首先需要鼠标光标下的窗口。 之后,将检查位于相同鼠标光标位置的该窗口的所有兄弟窗口的面积(宽度 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;
};

历史

  • 初始版本。
© . All rights reserved.