Introduction
This is a tool for capturing text data from UI controls. These include TreeCtrl, ListCtrl, ComboBox, ListBox, HeaderCtrl, Edit, etc. For example, the Windows Explorer folder tree data and folder list data can be obtained in text format.
Usage
Locating a window is similar to that in Microsoft Spy++. The following section will describe the usage step by step:.
- The control or window can be located using the Finder tool. It can be clicked and dragged to any window and the corresponding window will be highlighted. Also, the window can be located from the Window Tree.
- Clicking the Get Data button will capture the data from the selected window (control).
- The captured data can be selected and copied from the text area below the Get Data button, or by just clicking the Copy Data button.
Additionally, the option Smallest Top determines whether to search for the window that has the smallest area. It is useful when a control surrounded by a group box has to be located. If this is not selected, the simple WindowFromPoint
API will be used for the search.
Also, the located window can be confirmed by clicking the Flash button. Another way is to right click the Window Tree and select Flash in the context menu.
The data captured from ListCtrl and TreeCtrl are using TAB as delimiters. This helps to easily manage the data to paste and format in MS Word or Excel. The following image shows this:
The Windows\System folder is captured from Windows Explorer. Then it is pasted and formatted as a table in MS Word, as shown below:
Points of Interest
Locating a window by the Smallest Top method is really interesting. For that, first of all, the window under the mouse cursor is needed. After that, the all the siblings of this window coming under the same mouse cursor position will be checked for its area (Width x Height). From this, the window having the smallest area will be determined. The main code fragment is given below:
HWND hWnd = ::WindowFromPoint( point );
CPoint pointClient( point );
::ScreenToClient( hWnd, &pointClient );
HWND hWndChild = ::ChildWindowFromPoint( hWnd, pointClient );
if(( 0 != hWndChild ) && ::IsWindowVisible( hWndChild ))
{
hWnd = hWndChild;
}
if( m_bFindSmallestTop )
{
DWORD dwWndArea = MAXDWORD;
HWND hWndParent = ::GetParent( hWnd );
if( 0 != hWndParent )
{
if( 0 == ( ::GetWindowLong( hWnd, GWL_STYLE ) & WS_POPUP ))
{
HWND hWndChild = ::GetWindow( hWndParent, GW_CHILD );
while( 0 != hWndChild )
{
if( ::IsWindowVisible( hWndChild ))
{
CRect rect;
::GetWindowRect( hWndChild, &rect );
if( rect.PtInRect( point ))
{
DWORD dwChildArea = rect.Width() * rect.Height();
if( dwChildArea < dwWndArea )
{
dwWndArea = dwChildArea;
hWnd = hWndChild;
}
}
}
hWndChild = ::GetWindow( hWndChild, GW_HWNDNEXT );
}
}
}
}
For capturing data from different controls like ListCtrl, TreeCtrl, etc., the memory should be allocated within the virtual address space of the process of that window. A class named ProcMem
is used for this purpose. It will do the necessary things to simply handle the process memory. The class declaration is given below:
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;
};
History