设置菜单值时按钮不显示,未设置时显示奇怪的样式

Button didn't show up when menu value is set and shows odd style when not set

我想将特定 window 设置为按钮的父级,但我得到了预期的行为。

设置 CreateWindow() 上的 hMenu 值时,按钮不显示:

CreateWindow(L"Button",
                            L"Click me!",
                            WS_TABSTOP,
                            20, 
                            50,
                            60,
                            90,
                            NULL, 
                            (HMENU)1, 
                            NULL, NULL); 

但是当我删除 hMenu 参数时,按钮确实出现了,但样式很奇怪:

CreateWindow(L"Button",
                        L"Click me!",
                        WS_TABSTOP,
                        20, 
                        50,
                        60,
                        90,
                        NULL, 
                        NULL, 
                        NULL, NULL); 

我不会将主要 window 的 CreateWindow() 返回的 HWND 传递到按钮的 hwndParent 中,因为它们未按该顺序调用.

下面的代码是我真实代码的缩减版。

我错过了什么?

完整代码:

#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "Gdi32.lib")

#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE

#include <windows.h>

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

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PWSTR pCmdLine, int nCmdShow) {

  MSG  msg = {0};
  WNDCLASSW wc = {0};

  wc.lpszClassName = L"Window";
  wc.hInstance     = hInstance;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc;
  wc.hCursor = LoadCursor(0, IDC_ARROW);
  
  RegisterClassW(&wc);
  
  HWND
  hwndMainWindow = CreateWindow(wc.lpszClassName, L"Window",
                    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                    CW_USEDEFAULT, CW_USEDEFAULT, 500, 350, 
                    NULL, NULL, hInstance, NULL);
    HWND hButton = CreateWindow(L"Button",
                                L"Click me!",
                            WS_TABSTOP,
                            20, 
                            50,
                            60,
                            90,
                            NULL, 
                            NULL, 
                            NULL, NULL); 

    SetParent(hButton, hwndMainWindow);
    ShowWindow(hButton, SW_SHOWNORMAL);
    UpdateWindow(hwndMainWindow);

  while (GetMessage(&msg, NULL, 0, 0))
  {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
  }
  
  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

  switch(msg)
  {
      case WM_CLOSE:
        DestroyWindow(hwnd);
        break;

      case WM_DESTROY:
          PostQuitMessage(0);
          return 0;
  }

  return DefWindowProcW(hwnd, msg, wParam, lParam);
}

您没有在按钮上指定 WS_CHILD 样式。 SetParent() 没有为您设置此样式。

当您设置没有 WS_CHILD 的 window 的“父级”时,您实际上是在设置它的“所有者”。 Owner and Parent are not the same thing. Also see A window can have a parent or an owner but not both.

您的按钮没有出现在主按钮 window 中,因为该按钮不是主按钮的子按钮 window。

因此,在创建按钮时,您需要包含 WS_CHILD 样式。您还应该包括 WS_VISIBLE 样式而不是使用 ShowWindow()(除非您想要创建最初隐藏的按钮)。并且你应该在创建时指定父级window,而不是使用SetParent().

您还应该将创建的按钮移动到主 window 的 WndProc()WM_CREATE 处理程序中。

试试这个:

#pragma comment(lib, "user32.lib")
#pragma comment(lib, "Comctl32.lib")
#pragma comment(lib, "Gdi32.lib")

#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE

#include <windows.h>

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

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PWSTR pCmdLine, int nCmdShow) {

  MSG  msg = {0};
  WNDCLASS wc = {0};

  wc.lpszClassName = L"Window";
  wc.hInstance     = hInstance;
  wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
  wc.lpfnWndProc   = WndProc;
  wc.hCursor       = LoadCursor(0, IDC_ARROW);
  
  RegisterClass(&wc);
  
  HWNDhwndMainWindow = CreateWindow(wc.lpszClassName, L"Window",
                           WS_OVERLAPPEDWINDOW,
                           CW_USEDEFAULT, CW_USEDEFAULT, 500, 350, 
                           NULL, NULL, hInstance, NULL);

  ShowWindow(hwndMainWindow, SW_SHOWNORMAL);
  UpdateWindow(hwndMainWindow);

  while (GetMessage(&msg, NULL, 0, 0))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  
  return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  switch(msg)
  {
      case WM_CREATE:
          CreateWindow(L"Button",
                       L"Click me!",
                       WS_CHILD | WS_VISIBLE | WS_TABSTOP,
                       20, 
                       50,
                       60,
                       90,
                       hwnd,
                       (HMENU)1, 
                       NULL, NULL); 
          break;

      case WM_COMMAND:
          if ((LOWORD(wParam) == 1) && (HIWORD(wParam) == BN_CLICKED)) {
              MessageBox(hwnd, L"Yea, you clicked me!", L"Window", MB_OK);
              return 0;
          }
          break;

      case WM_CLOSE:
          DestroyWindow(hwnd);
          break;

      case WM_DESTROY:
          PostQuitMessage(0);
          return 0;
  }

  return DefWindowProc(hwnd, msg, wParam, lParam);
}