C++ win32中的WM_COMMAND捕捉按钮按下

2022-01-15 00:00:00 windows button winapi event-handling c++

我正在尝试使用 WM_Command

HWND hBtn;
HWND  hBtnParent = HWND("UploadVideo");
HWND SelectVideoBTN, UploadBTN;
HWND hWnd;

HINSTANCE hUpload;
WNDCLASSEX wcexUpload;
int nCmdShowUpload = 1;
using namespace std;

LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    loader::alert("rrr");
    switch (message)
    {
    case WM_COMMAND:
        if (LOWORD(wParam) == WORD(SelectVideoBTN)) {
            loader::alert("hello");
        }
        break;
    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

SelectVideoBTN = CreateWindow(
            L"BUTTON",  // Predefined class; Unicode assumed 
            L"Select Video's",      // Button text 
            WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,  // Styles 
            10,         // x position 
            460,         // y position 
            100,        // Button width
            25,        // Button height
            hWnd,     // Parent window
            NULL,       // No menu.
            (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
            NULL);      // Pointer not needed.

        UploadBTN = CreateWindow(
            L"BUTTON",  // Predefined class; Unicode assumed 
            L"Upload",      // Button text 
            WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,  // Styles 
            390,         // x position 
            460,         // y position 
            100,        // Button width
            25,        // Button height
            hWnd,     // Parent window
            NULL,       // No menu.
            (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
            NULL);      // Pointer not needed.

我一直在看这个例子 - http:///forums.devshed.com/programming-42/create-button-clicked-148407.html - 但我不能让它工作,它甚至不会调用 CALLBACK WindowProcedure代码> - 有没有人可以帮助我?

I've been looking at this example - http://forums.devshed.com/programming-42/create-button-clicked-148407.html - but I can't quite get it to work, it won't even call the CALLBACK WindowProcedure - is there anyone who could help me?

按钮出现在我创建的 window 上,我通过以下方式创建 window -

The buttons are present on the window I've created, I create the window by doing -

WNDCLASSEX vidUploader;

    vidUploader.cbSize = sizeof(WNDCLASSEX);

    vidUploader.style = CS_HREDRAW | CS_VREDRAW;
    vidUploader.lpfnWndProc = WndProc;
    vidUploader.cbClsExtra = 0;
    vidUploader.cbWndExtra = 0;
    vidUploader.hInstance = hUpload;
    vidUploader.hIcon = LoadIcon(hUpload, MAKEINTRESOURCE(IDI_P2GOVIDEOUPLOADER20));
    vidUploader.hCursor = LoadCursor(NULL, IDC_ARROW);
    vidUploader.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    vidUploader.lpszMenuName = MAKEINTRESOURCE(IDC_P2GOVIDEOUPLOADER20);
    vidUploader.lpszClassName = (LPCWSTR)(L"UploadVideo");
    vidUploader.hIconSm = LoadIcon(wcexUpload.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    RegisterClassEx(&vidUploader);

    hInst = hUpload; // Store instance handle in our global variable

然后创建窗口

    hWnd = CreateWindow((LPCWSTR)(L"UploadVideo"), (LPCWSTR)(L"Upload Video's"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 100, NULL, NULL, hUpload, NULL);
if (!hWnd)
        {
            MessageBox(NULL, _T("Call to CreateWindow failed!"), _T("Win32 Guided Tour"), NULL);

            return 1;
        }


    // The parameters to ShowWindow explained:
    // hWnd: the value returned from CreateWindow
    // nCmdShow: the fourth parameter from WinMain
    ShowWindow(hWnd,
        nCmdShowUpload);

    UpdateWindow(hWnd);

推荐答案

子窗口(即具有 WS_CHILD 窗口样式的窗口)由唯一的数值标识,通常称为控件 ID 或窗口 ID.例如,当它接收到 WM_COMMAND 消息时,它会传递给父级.但是,您从未为按钮控件分配控件 ID,并且父窗口无法识别它们.如果是子窗口,则调用 hMenu 参数rel="noreferrer">CreateWindow 被重载以携带唯一标识符:

Child windows (i.e. windows with the WS_CHILD window style) are identified by a unique numeric value, often called control ID or window ID. It is passed to the parent when it receives a WM_COMMAND message, for example. You never assigned a control ID to your button controls, though, and the parent window cannot identify them. In case of a child window, the hMenu parameter in the call to CreateWindow is overloaded to carry the unique identifier:

hMenu
对于子窗口,hMenu 指定子窗口标识符,对话框控件用来通知其父级事件的整数值.应用程序确定子窗口标识符;对于具有相同父窗口的所有子窗口,它必须是唯一的.

hMenu
For a child window, hMenu specifies the child-window identifier, an integer value used by a dialog box control to notify its parent about events. The application determines the child-window identifier; it must be unique for all child windows with the same parent window.

换句话说,您的应用程序选择一个数值来分配给控件.由于对话管理器已经使用了较低的 ID(例如 IDOK),因此通常的做法是从 100 开始分配控件 ID(请参阅 为什么对话框编辑器开始分配控件 ID 为 100?).

In other words, your application picks a numeric value to assign to controls. Since the lower IDs are used by the dialog manager already (e.g. IDOK), it is common practice to start assigning control IDs starting at 100 (see Why do dialog editors start assigning control IDs with 100?).

在您的 WM_COMMAND 处理程序中,您可以进行比较LOWORD(wParam) 到分配给您的按钮控件的标识符.

In your WM_COMMAND handler you can then compare LOWORD(wParam) to the identifier assigned to your button controls.

您需要对您的代码应用以下更改.

You need to apply the following changes to your code.

// Declare control IDs. This is usually done in a file called Resource.h
#define IDC_SELECT_VIDEO (100)

更改您的窗口创建代码:

Change your window creation code:

SelectVideoBTN = CreateWindow(
            L"BUTTON",  // Predefined class; Unicode assumed 
            L"Select Video's",      // Button text 
            WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,  // Styles 
            10,         // x position 
            460,        // y position 
            100,        // Button width
            25,         // Button height
            hWnd,       // Parent window
            (HMENU)IDC_SELECT_VIDEO, // Assign appropriate control ID
            (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
            NULL);      // Pointer not needed.

检查 WM_COMMAND 处理程序中的控件 ID:

Check for the control ID in your WM_COMMAND handler:

    switch (message)
    {
    case WM_COMMAND:
        if (LOWORD(wParam) == IDC_SELECT_VIDEO) {
            loader::alert("hello");
        }
        break;
    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }


如果您的窗口过程根本没有被调用,这可能意味着您没有在调用线程上分派消息.GUI 线程总是需要一个消息循环.标准的消息循环就足够了:


If your window procedure isn't called at all, this could mean that you aren't dispatching messages on the calling thread. A GUI thread always needs a message loop. The standard message loop suffices:

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

相关文章