【问题标题】:WM_COMMAND catch button press in c++ win32C++ win32中的WM_COMMAND捕捉按钮按下
【发布时间】:2016-09-13 06:18:17
【问题描述】:

我正在尝试使用 WM_Command 在 c++ win32 中获取按钮按下事件

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 - 有人可以帮助我吗?

按钮出现在我创建的window 上,我通过执行创建window -

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

【问题讨论】:

    标签: c++ windows winapi button event-handling


    【解决方案1】:

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

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

    换句话说,您的应用程序选择一个数值来分配给控件。由于对话管理器已经使用了较低的 ID(例如IDOK),因此通常的做法是从 100 开始分配控件 ID(请参阅Why do dialog editors start assigning control IDs with 100?)。

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

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

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

    更改您的窗口创建代码:

    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:

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


    如果您的窗口过程根本没有被调用,这可能意味着您没有在调用线程上分派消息。 GUI 线程总是需要一个消息循环。标准的消息循环就足够了:
    MSG msg = {0};
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    

    【讨论】:

    • 我已经按照你说的做了,但是当我将 .dll 文件放入程序时(我正在创建一个插件),窗口是在加载时生成的,但是当我点击按钮时不工作,我已经编辑了我的问题
    • @Gerwin:请不要以某种方式更改问题,这会使已发布的答案无效。我将您的编辑恢复到初始版本。如果您有新问题,请单击 按钮。如果您想添加更多信息,您也可以edit您的问题,如果它不会改变核心问题。
    • 那么加载你插件的东西需要运行一个消息循环。
    • 你不能有一个没有消息循环的窗口。必须有一些东西来运行它。我猜您可以尝试使用单独的线程,但这可能会变得混乱。
    • 仅供参考,使用控件 ID 并不是识别子控件的唯一方法。发送到父窗口的WM_COMMANDWM_NOTIFY 消息也带有子控件的HWND,例如:case WM_COMMAND: if (HWND(lParam) == SelectVideoBTN) { ... }
    猜你喜欢
    • 1970-01-01
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-24
    • 2012-09-21
    • 2012-06-04
    相关资源
    最近更新 更多