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

捕获窗口控件并修改其属性

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (55投票s)

2005 年 2 月 10 日

GPL3

2分钟阅读

viewsIcon

225623

downloadIcon

7701

一个类似于 MS Spy++ 的 Spy 工具程序,允许您捕获窗口控件并修改其属性。有助于学习窗口句柄及其属性。

Sample Image - windowspy.gif

引言

我一直想有一个像 Microsoft Visual Studio 中的 Spy++ 这样的工具,但我希望该工具能够修改窗口控件。例如,有时我们需要在运行时启用程序中的一些无效控件。MS Spy++ 没有任何此类功能,所以我自己做了这个工具。

此程序可用于获取窗口句柄、标题、类名、样式和大小。此外,它还可以方便地在运行时加载时更改目标窗口控件的标题名称、样式和扩展样式。

该应用程序是一个不使用 MFC 的 Win32 项目。它通过 `WindowFromPoint()` user32 API 挂钩目标窗口。它有一个算法,通过巧妙地使用 `GetWindowRect()` 和 `GetWindow()` 在子窗口和父窗口中搜索,以捕获程序内的子窗口。它应用 `GetWindowLong()` 获取窗口属性,并应用 `SetWindowLong()` 修改它们。

挂钩目标窗口

我们可以通过 `WM_MOUSEMOVE` 鼠标事件挂钩目标窗口

case WM_MOUSEMOVE:
if (bSeeking)
{
  HWND hWindowUnderTheMouse;
  //HWND hWindowUnderTheMouseChild;

  points = MAKEPOINTS(lParam); 
  point.x=points.x;
  point.y=points.y;
  ClientToScreen(hDlg,&point);
  hWindowUnderTheMouse = WindowFromPoint(point);
  if((hwndMain==hWindowUnderTheMouse)||
    (hwndMain==GetParent(hWindowUnderTheMouse)))
  {
    break;
  }
  //------------------------------

  hChildFound=NULL;
  SeekDumpWindow(hWindowUnderTheMouse,point);
  if((IsWindow(hChildFound))&&(hChildFound!=NULL))
  {
    hWindowUnderTheMouse=hChildFound;
  }
  //------------------------------

  if(hWindowUnderTheMouse != hSeekedWindow)
  {
    //

    FrameWindow(hSeekedWindow);
    hSeekedWindow = hWindowUnderTheMouse;
    FrameWindow(hSeekedWindow);
    // update the twin window

    strcpy(szSeekedWindow,"0x");
    _itoa((DWORD)hSeekedWindow,szSeekedWindow+2,16);
    CharUpperBuff(szSeekedWindow+2,(DWORD)strlen(szSeekedWindow));
    SetDlgItemText(hDlg,IDC_WINDOWHANDLE,szSeekedWindow);
    GetWindowInfo(hSeekedWindow);
  }
}
else
{
  points = MAKEPOINTS(lParam); 
  point.x=points.x;
  point.y=points.y;
}
break;

它通过搜索其父级和子级来查找正确的窗口目标,方法是使用程序内 `<DumpSeek.h>` 中定义的 `SeekDumpWindow()`。

修改目标窗口

通过其句柄修改目标窗口非常容易。如果您拥有窗口句柄,则可以通过 `GetWindowLong()` 和 `SetWindowLong()` 非常轻松地获取和更改样式,也可以通过使用 `SetWindowText()` 和 `SendDlgItemMessage()` 更改窗口标题。查看程序中的 `UpdateFlags()`,您将找到执行此操作以修改目标窗口的代码。

if(TopMost) 
{
  dwExtendedStyle|=WS_EX_TOPMOST; 
  SetWindowPos(hHandle, 
  HWND_TOPMOST, 0, 0, 0, 0,
  SWP_NOSIZE|SWP_NOMOVE);
}
else
{
  dwExtendedStyle&=~WS_EX_TOPMOST;
  SetWindowPos(hHandle, 
  HWND_NOTOPMOST, 0, 0, 0, 0,
  SWP_NOSIZE|SWP_NOMOVE);
}
//----------------------------------------------

if(BACKdwID!=dwID) SetWindowLong(hHandle, GWL_ID, dwID);
if(BACKdwStyle!=dwStyle)SetWindowLong(hHandle, GWL_STYLE, dwStyle);
if(BACKdwExtendedStyle=dwExtendedStyle)
SetWindowLong(hHandle, GWL_EXSTYLE, dwExtendedStyle);
if(Visible)
{
  ShowWindow(hHandle,SW_HIDE);
  ShowWindow(hHandle,SW_SHOW);
}
else
{
  ShowWindow(hHandle,SW_SHOW);
  ShowWindow(hHandle,SW_HIDE);
}
UpdateWindow(GetParent(hHandle));

更改标题的代码取决于窗口控件的类型。要更改编辑控件和框控件的标题,必须使用 `SendDlgItemMessage()` 而不是其他窗口控件中的 `SetWindowText()`。

if((strstr(_szClassName,"EDIT")==NULL)&&(strstr(_szClassName,"BOX")==NULL))
{
  SetWindowText(hHandle,szTitle);
}
else
{
  HWND hWndParent=GetParent(hHandle);
  SendDlgItemMessage(hWndParent,dwID,WM_SETTEXT,0,(LPARAM)szTitle);
}

结论

我希望这个工具能够帮助刚接触这个领域的人了解窗口类及其操作。这将是制作窗口 Spy 工具和使用句柄的入门介绍。

最后,如果您能抽出时间提出您的想法、建议以及您可能在此程序中发现的任何错误,我将不胜感激。

© . All rights reserved.