按钮上 EnableWindow 的奇怪行为

问题描述 投票:0回答:1

我有一个简单的 Win32 应用程序,用于创建一个按钮。创建按钮后,我使用

EnableWindow(FALSE)
中的
<windows.h>
功能禁用了它。当按钮大小大于应用的文本时,它可以正常工作。 但是,当按钮尺寸小于按钮文本时,整个窗口的客户区似乎复制了屏幕的内容。

The size is greater that the text (Normal)

The size is smaller that the text (Problem)

导致错误的代码:

#include <Windows.h>

LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR    lpCmdLine, _In_ int       nCmdShow)
{
    WNDCLASSEX wcex = { 0 };

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.lpfnWndProc = WndProc;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.lpszClassName = L"MYWINDOWCLASS";
    
    if (RegisterClassExW(&wcex) == 0)
        return -1;

    HWND hWnd = CreateWindowW(L"MYWINDOWCLASS", L"MYWINDOW", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

    if (!hWnd)
        return -1;

    HWND buttonHWnd = CreateWindowW(L"BUTTON", L"MYWINDOW", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
        100, 100, 40, 30, hWnd, nullptr, hInstance, nullptr);

    if (!buttonHWnd)
        return -1;

    EnableWindow(buttonHWnd, FALSE);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    MSG msg;
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

c++ windows winapi button
1个回答
0
投票

您在 Win32 应用程序中遇到的这个问题非常有趣,其中按钮的文本比按钮本身大,导致意外的屏幕复制,并且可能涉及 Windows 如何处理禁用的控件及其绘制的一些细微差别。以下是可能发生的情况的详细信息以及可能解决或理解该问题的一些步骤:

可能原因:

  1. 禁用控件的绘画问题:

    • 当禁用按钮等控件时,Windows 可能无法正确重绘控件的背景,特别是当控件的大小小于其内容时。这可能会导致底层屏幕或窗口内容显示出伪影。
  2. 文字溢出:

    • 如果按钮的文本长于按钮的宽度,Windows 可能会以意外的方式处理溢出,特别是当按钮被禁用时。通常,文本应被截断或不完全显示,但在禁用状态下,行为可能会有所不同。
  3. 窗口重绘:

    • EnableWindow(FALSE)
      函数可能不会触发控件或其父窗口的完全重绘,从而导致这些视觉异常。

潜在的解决方案:

  • 重画窗口:

    • 禁用按钮后,强制重绘窗口或按钮本身:
      InvalidateRect(hWndButton, NULL, TRUE);
      UpdateWindow(hWndButton);
      
  • 调整按钮大小:

    • 确保按钮大小动态调整以适合其文本或至少不小于文本。您可以使用
      GetTextExtentPoint32
      来计算文本大小并相应地调整按钮尺寸。
  • 自定义绘图:

    • 重写窗口过程中的
      WM_CTLCOLORBTN
      消息,以便在按钮禁用时自行处理按钮的绘制。这将使您可以控制按钮在禁用时的外观:
      case WM_CTLCOLORBTN:
          if ((HWND)lParam == hWndButton) {
              SetBkMode((HDC)wParam, TRANSPARENT);
              SetTextColor((HDC)wParam, GetSysColor(COLOR_GRAYTEXT));
              return (LRESULT)GetSysColorBrush(COLOR_BTNFACE);
          }
          break;
      
  • 检查重叠窗口:

    • 确保没有其他窗口或桌面部分重叠或复制到应用程序的客户端区域。这可能不太可能,但值得检查。
  • 调试:

    • 使用 Spy++ 等工具来查看发送到窗口和按钮禁用时的消息。这可能会提供有关为什么屏幕内容被复制的线索。

其他提示:

  • 测试:使用不同的主题和视觉样式进行测试,看看问题是否仍然存在。有时,这可能是特定于主题的。

  • 文档:查看 MSDN 文档或有关禁用控件在不同版本的 Windows 中应如何表现的任何更新。

如果这些解决方案不能解决问题,则可能值得更深入地探索 Windows 如何处理禁用的控件,可能会查看类似应用程序的源代码或深入研究 Windows API 文档,以在禁用时对按钮的外观进行更具体的控制.

© www.soinside.com 2019 - 2024. All rights reserved.