简体   繁体   中英

win32 button not showimg

I tried to create a single button in a 500x500 window, the problem is, the button does not appear in the windows, and clicking the windows alone triggers the procedure/handler for the button:

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

What did i miss?

That is not how you create a button.

A button control uses a special window class, pre-defined by the common controls library. You don't need to register the window class, it is already registered. Recommended reading on using common controls is here on MSDN .

All you need is the call to CreateWindow , just make sure you use the correct class name: WC_BUTTON (which is defined by the common controls header file to be "BUTTON" ).

For controls, you also generally want to include the WS_TABSTOP style, and for a button specifically, you need to include one of the button styles —eg, BS_DEFPUSHBUTTON or BS_PUSHBUTTON .

Finally, you're passing the wrong value for the hMenu parameter when you call CreateWindow . For child windows (like controls), this is a unique identifier of the control, not the handle of its parent window. If it's the first control, you might give it an ID of 1 . It's best to use constants in your code for this so that you can interact with the controls later programmatically.

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

And since you've included the WS_VISIBLE style, you don't need this code (and you probably should not use nCmdShow with your child windows anyway):

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

Finally, I can't help but notice that you're using ANSI string literals. All Windows applications today should be built with Unicode support, which requires that you use wide string literals. To get those, prefix each of them with an L and use the LPCWSTR type: LPCWSTR FrameClassName = L"MainWindow"; Not doing so should have been generating a compiler error; the default settings for a new project define the UNICODE preprocessor symbol. If that's not done for your project, you should do it now.

When creating button with visual style under Windows XP, you need to load 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM