首页 > 解决方案 > 设置菜单值时按钮不显示,未设置时显示奇怪的样式

问题描述

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

当设置hMenu值 on时CreateWindow(),按钮不显示:

图片

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); 

我没有将主窗口HWND返回的值传递给按钮,因为它们不是按那个顺序调用的。CreateWindow()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);
}

标签: cwinapibuttonparent

解决方案


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

当您设置没有 的窗口的“父级”时,WS_CHILD实际上是在设置它的“所有者”。 Owner 和 Parent 不是一回事。另请参阅窗口可以有父级或所有者,但不能同时拥有

您的按钮不会出现在主窗口中,因为该按钮不是主窗口的子窗口。

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

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

尝试这个:

#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);
}

推荐阅读