首页 > 解决方案 > 如何检查按钮是否是 64 位窗口上的复选框?

问题描述

我正在检查一个按钮是否是 64 位 windows10 上的 32 位进程的复选框。

问题是我无法将复选框与普通按钮区分开来。

Window-Detective中的按钮不同:

在此处输入图像描述

重新启动应用程序后,即使 Window-Detective 现在也显示它是一个按钮!

但是复选框不能被识别为 Spy++ 中的复选框

在此处输入图像描述

BS_CHECKBOX未列出。

代码(编译为 32 位):

TEST_METHOD(ShouldCheckStyle) {
    auto styleOfButton =    ::GetWindowLongPtr((HWND)0x003F06E8, GWL_STYLE);
    auto styleOfCheckbox =  ::GetWindowLongPtr((HWND)0x01101642, GWL_STYLE);
    auto bsOfButton =       styleOfButton & BS_TYPEMASK;
    auto bsOfCheckbox =     styleOfCheckbox & BS_TYPEMASK;
    auto resultOfButton =   (bsOfButton == BS_CHECKBOX);
    auto resultOfCheckbox = (bsOfCheckbox == BS_CHECKBOX);
    auto debugger = 0;
}

调试输出

在此处输入图像描述

代码表明他们都有BS_OWNERDRAW. 以上对于按钮和复选框的行为相同。

奇怪的是 Window-Detective 可以识别复选框的样式。代码与我上面使用的相同。这是一段代码:

Window* WindowManager::createWindow(HWND handle) {
    WindowClass* windowClass = getWindowClassFor(handle);

    String className = windowClass->getName().toLower();
    if (className == "button") {
        LONG typeStyle = GetWindowLong(handle, GWL_STYLE) & BS_TYPEMASK;
        switch (typeStyle) {
          case BS_CHECKBOX:
          case BS_AUTOCHECKBOX:
          case BS_3STATE:
          case BS_AUTO3STATE: {
              return new CheckBox(handle, windowClass);
          }
          case BS_RADIOBUTTON:
          case BS_AUTORADIOBUTTON: {
              return new RadioButton(handle, windowClass);
          }
          case BS_GROUPBOX: {
              return new GroupBox(handle, windowClass);
          }
          default: {
              // If none of the above is true, then the control is just a Button
              return new Button(handle, windowClass);
          }
        }
    }

标签: winapivisual-c++

解决方案


经过一番讨论,您可以使用GetWindowText从每个控件中获取文本并比较特定文本。

BS_CHECKBOX由于BS_OWNERDRAW,无法从“复选框”控件的属性中检测到。

创建一个所有者绘制的按钮。当按钮的视觉方面发生变化时,所有者窗口会收到 WM_DRAWITEM 消息。不要将 BS_OWNERDRAW 样式与任何其他按钮样式结合使用。

试试下面的代码:

WCHAR str1[20];
WCHAR str2[] = L"Agree me";

GetWindowText(hwnd_checkbox, str1, 256);
if (_tcscmp(str1, str2) == 0)
{
    //it is checkbox                        
}
else
{
    //it isn't checkbox
}

获得复选框的正确控制句柄后,您可以使用SendDlgItemMessageSendMessage发送BM_SETCHECK检查消息。

SendMessage(hwnd_checkbox, BM_SETCHECK, BST_CHECKED, 0);


推荐阅读