WM_COMMAND 在 c++ win32 中按下按钮

问题描述 投票:0回答:2

我正在尝试使用

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
2个回答
13
投票

子窗口(即具有

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

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

换句话说,您的应用程序选择一个数值分配给控件。由于较低的 ID 已被对话管理器使用(例如

IDOK
),通常的做法是从 100 开始分配控件 ID(请参阅为什么对话框编辑器开始使用 100 分配控件 ID?)。

在您的 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);
}

0
投票

根据MSDN的文档,lParam返回控件(窗口)的句柄,wParam的低位字(LOWORD)返回控件的标识符,wParam的高位字(HIWORD)返回WM_COMMAND消息中的通知代码。

没有标识符的方法一

否则:

case WM_COMMAND: {

     if((HWND)lParam==SelectVideoBTN) {
        printf("Button was clicked!\n"); //Do whatever you wish
     }

}

使用开关盒

 case WM_COMMAND: {

  switch((HWND)lParam){
    case VDOBTN_ID:{
      printf("Button was clicked!\n");
      break;
     }
  }

 }

带标识符的方法二

第一步: 声明一个具有标识符值的全局宏。名称和 ID 可以是您想要的任何内容,但在整个项目中必须是唯一的。 像这样……

#define VDOBTN_ID 440 

然后,第二步:

case WM_COMMAND: {

  switch(LOWORD(wParam)){
      case VDOBTN_ID:{
        printf("Button was clicked\n"); // Do whatever you wish
        break;
      }
  }

}

有了 if else,它应该看起来像这样……

case WM_COMMAND: {

  if(LOWORD(wParam)==VDOBTN_ID){
    printf("Button was clicked\n"); // Do whatever you wish
  }

}

如果不是为了特定目的,我个人更喜欢和推荐第一种方法,因为它简化了程序,并且不需要再定义一个宏,也不需要观察HIWORD和LOWORD。 欢迎评论和指正...

© www.soinside.com 2019 - 2024. All rights reserved.