2

我试图在 500x500 窗口中创建一个按钮,问题是,按钮没有出现在窗口中,单独单击窗口会触发按钮的过程/处理程序:

#include <windows.h>

LRESULT CALLBACK MainWindowHandler(HWND obj, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK ButtonHandler(HWND obj, UINT msg, WPARAM wParam, LPARAM lParam);

LPCSTR FrameClassName = "MainWindow";
LPCSTR ButtonClassName = "Button";

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX Frame;
HWND FrameHandle;
WNDCLASSEX Button;
HWND ButtonHandle;

MSG Msg;

Frame.cbSize        = sizeof(WNDCLASSEX);
    Frame.style         = 0;
    Frame.lpfnWndProc   = MainWindowHandler;
    Frame.cbClsExtra    = 0;
    Frame.cbWndExtra    = 0;
Frame.hInstance     = hInstance;
Frame.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
Frame.hCursor       = LoadCursor(NULL, IDC_ARROW);
Frame.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
Frame.lpszMenuName  = NULL;
Frame.lpszClassName = FrameClassName;
    Frame.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

Button.cbSize        = sizeof(WNDCLASSEX);
    Button.style         = 0;
    Button.lpfnWndProc   = ButtonHandler;
    Button.cbClsExtra    = 0;
    Button.cbWndExtra    = 0;
Button.hInstance     = hInstance;
Button.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
Button.hCursor       = LoadCursor(NULL, IDC_ARROW);
Button.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
Button.lpszMenuName  = FrameClassName;
Button.lpszClassName = ButtonClassName;
    Button.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

if(!RegisterClassEx(&Frame))
{
    MessageBox(NULL,"Registration Failure","ERROR",MB_ICONWARNING|             MB_OK);
    return 0;
}
if(!RegisterClassEx(&Button))
{
    MessageBox(NULL,"Registration Failure","ERROR",MB_ICONWARNING|             MB_OK);
    return 0;
}

FrameHandle = CreateWindowEx(WS_EX_CLIENTEDGE,
                     FrameClassName,
                     "Application",
                     WS_OVERLAPPEDWINDOW,
                     CW_USEDEFAULT, CW_USEDEFAULT, 500, 500,
                     NULL, NULL, hInstance, NULL);

ButtonHandle = CreateWindowEx(0, ButtonClassName, "My Button",
    WS_CHILD | WS_VISIBLE, 250, 250, 30, 20, FrameHandle,
    (HMENU)FrameHandle, hInstance, NULL);

SendDlgItemMessage(ButtonHandle, 12, WM_SETFONT,
    (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(TRUE, 0));


ShowWindow(FrameHandle, nCmdShow);
UpdateWindow(FrameHandle);
ShowWindow(ButtonHandle, nCmdShow);
UpdateWindow(ButtonHandle);

while(GetMessage(&Msg,NULL,0,0)>0)
{
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
}

}

LRESULT CALLBACK MainWindowHandler(HWND obj, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_LBUTTONDOWN:
    MessageBox(obj,"CLICKED!","BUTTON",0);
    break;
    case WM_CLOSE:
    DestroyWindow(obj);
        break;
    case WM_DESTROY:
    PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(obj, msg, wParam, lParam);
}
return 0;
}

LRESULT CALLBACK ButtonHandler(HWND obj, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
    case WM_CLOSE:
    DestroyWindow(obj);
        break;
    case WM_DESTROY:
    PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(obj, msg, wParam, lParam);
}
return 0;
}

我错过了什么?

4

2 回答 2

6

这不是您创建按钮的方式。

按钮控件使用由公共控件库预定义的特殊窗口类。您不需要注册窗口类,它已经注册了。关于使用常用控件的推荐读物在 MSDN 上

您只需要调用CreateWindow,只需确保使用正确的类名:(WC_BUTTON由通用控件头文件定义为"BUTTON")。

对于控件,您通常还希望包含WS_TABSTOP样式,特别是对于按钮,您需要包含其中一种按钮样式,例如,BS_DEFPUSHBUTTONBS_PUSHBUTTON

最后,hMenu当您调用CreateWindow. 对于子窗口(如控件),这是控件的唯一标识符,而不是其父窗口的句柄。如果它是第一个控件,您可能会给它一个 ID 1。最好在代码中为此使用常量,以便以后可以通过编程方式与控件进行交互。

#include <CommCtrl.h>  // somewhere at the top of your code file

ButtonHandle = CreateWindowEx(0,
                              WC_BUTTON,
                              "My Button",
                              WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON,
                              250, 250, 30, 20,
                              FrameHandle,
                              (HMENU)1, // or some other unique ID for this ctrl
                              hInstance,
                              NULL);

而且由于您已经包含了WS_VISIBLE样式,因此您不需要此代码(nCmdShow无论如何您可能不应该与您的子窗口一起使用):

// unnecessary code:
ShowWindow(ButtonHandle, nCmdShow);
UpdateWindow(ButtonHandle);

最后,我不禁注意到您使用的是 ANSI 字符串文字。今天所有的 Windows 应用程序都应该使用 Unicode 支持构建,这要求您使用宽字符串文字。要获得这些,请在每个前面加上一个L并使用LPCWSTR类型:LPCWSTR FrameClassName = L"MainWindow";不这样做应该会产生编译器错误;新项目的默认设置定义了UNICODE预处理器符号。如果您的项目还没有这样做,那么您现在应该这样做。

于 2013-05-26T13:03:15.343 回答
0

在 Windows XP 下创建具有视觉风格的按钮时,需要加载comctl32.dll.

#include <CommCtrl.h>  // somewhere at the top of your code file

#pragma comment(lib, "Comctl32.lib") // if necessary

// create manifest to use XP visual style
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

// before creating button call:
InitCommonControls(); // necessary to enable Visual style on WinXP
于 2019-03-19T21:41:57.363 回答