【问题标题】:Push button and combo box WinAPI按钮和组合框 WinAPI
【发布时间】:2015-01-20 09:05:02
【问题描述】:

我正在尝试做一些 Windows 编程。我创建了一个组合框和一个按钮。我的目标是,当用户在组合框中选择一个项目时,按钮被激活并且需要单击才能继续。到目前为止,我已经做了类似的事情:

这就是我创建组合框的方式:

Func.h

#ifndef FUNCS_H

#define FUNCS_H

// Winapi headers....
#include <windows.h>
#include <windowsx.h>
#include <shlobj.h>

//created lib
#include "Resource.h"

// Standard C/C++ headers...
#include <iostream>
#include <string>
#include <dirent.h> // directory manipulation....
#include <cstring>
#include <fstream>


using std::cout;
using std::endl;
using std::string;
using std::ofstream;


HWND hselectOK;
HWND hComboBox1;




void createControls(HWND hwnd) // Create our combo box
{

    HWND hselectFeature;



    HINSTANCE hInstance = GetModuleHandle(NULL);

    // Create our List box
    hComboBox1 = CreateWindow(WC_COMBOBOX,"", CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD |WS_OVERLAPPED |WS_VISIBLE , 7, 20, 300, 100, hwnd, NULL, hInstance, NULL);
    SendMessage(hComboBox1, CB_ADDSTRING, 0,(LPARAM)"Histogram of Oriented Gradients (HOG)");
    SendMessage(hComboBox1, CB_ADDSTRING, 0,(LPARAM)"Scale Invariant Feature Transform (SIFT)");
    SendMessage(hComboBox1, CB_ADDSTRING, 0,(LPARAM)"Speeded Up Robust Features (SURF)");

   // SendMessage(hComboBox1, CB_SETCURSEL, (WPARAM)2,(LPARAM)0); //CB_SETCURSEL

    // Create our push bottons
    hselectFeature = CreateWindow("STATIC", "Select Feature", SS_LEFT | WS_CHILD, 320,20, 100, 21,hwnd, (HMENU)1, hInstance, NULL);
    ShowWindow(hselectFeature,1);

    hselectOK = CreateWindow("BUTTON", "Ok", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON | WS_DISABLED, 320,45, 100, 21,hwnd, NULL, hInstance, NULL);


}

#endif // FUNCS_H

WinProc.h

#ifndef WINPROC_H

#define WINPROC_H

// Winapi Headers
#include <CommDlg.h>
#include <winuser.h>

// OpenCV headers
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

// Standard C/C++ headers
#include <iostream>
#include <string>

// Created headers;
#include "Funcs.h"
#include "Resource.h"

using std::cout;
using std::endl;
using std::string;

using namespace cv;

int classNumber;


LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

    string dirPath;
    int comboIndex;

    switch (message)                  /* handle the messages */
    {
        case WM_CREATE:

            createControls(hwnd);
            break;

        case WM_COMMAND:
            {

                switch(HIWORD(wParam))
                    {
                        case  CBN_SELCHANGE: // When user select item in combo box, enable the button.
                            {

                                EnableWindow(hselectOK, TRUE); // enable the button

                            }

                            break;

                            case BN_CLICKED: // When user has chosen a list, the button is used to proceed with further task associated to the selected item.
                            {


                                char listName[200];
                                comboIndex = SendMessage(hComboBox1, (UINT) CB_GETCURSEL, 0, 0);
                                SendMessage(hComboBox1, (UINT)CB_GETLBTEXT, (WPARAM)comboIndex, (LPARAM)listName);

                                if(comboIndex == 0)
                                {
                                   MessageBox(hwnd,listName, "You chose", MB_OK);
                                   // Want to Do some function here.

                                }

                                else if(comboIndex == 1)
                                {
                                   MessageBox(hwnd,listName, "You chose", MB_OK);
                                    // Want to Do some function here.

                                }

                                else if(comboIndex == 2)
                                {
                                    MessageBox(hwnd,listName, "You chose", MB_OK);
                                          // Want to Do some function here.
                                }

                            }

                            break;
                     }





                switch LOWORD(wParam)
                    {
                        case IDM_IMG_PATH:
                            {
                               dirPath = browseFolder(hwnd);

                               DialogBox(GetModuleHandle(NULL),MAKEINTRESOURCE(IDD_CLASS),hwnd, ClassDlgProcedure);
                               createClassLabelFile(hwnd, dirPath, classNumber);

                               return 0;
                            }

                        case IDM_EXIT:
                            {

                               PostMessage(hwnd, WM_CLOSE,0 , 0);

                            }

                            break;

                    }
            }
            break;

        case WM_DESTROY:
            PostQuitMessage(0);       /* send a WM_QUIT to the message queue */
            break;
        default:                      /* for messages that we don't deal with */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}




#endif // WINPROC_H

这些部分只是代码的一些相关部分。

问题是,当我使用 case IDM_EXIT 退出程序时,总是出现 case BN_CLICKED 下的消息框,然后程序关闭。我期待当我们关闭程序时,不会出现这样的消息框,但事实并非如此。我的意思是,消息框出现两次,一次是选择单击按钮时,一次是要关闭程序时。为什么会这样。任何想法或建议?

【问题讨论】:

    标签: c++ c winapi user-interface


    【解决方案1】:

    问题是您假设 WM_COMMAND 是您的 ComboBox 独有的消息,但事实并非如此。

    看看这个古老但黄金的blog post

    引自作者,

    wParam 参数的高位字“指定 如果消息来自控件,则通知代码”。什么是 这里的“控制”是什么意思?请记住,您必须根据上下文来看待事情。 WM_COMMAND 消息在 Win32 的上下文中呈现 一般,特别是在窗口管理器的上下文中。 编辑框、按钮和列表框等窗口通常是 称为“控件”,就像“通用”中的所有窗口类一样 控件库”。在窗口管理器的世界中,“控件”是 一个窗口,其目的是提供某种程度的交互性 (在静态控件的情况下,可能没有交互性 完全)在其父窗口的服务中。事实是 WM_COMMAND 主要在对话框的上下文中进一步使用 强调一点,这里的“控制”一词只是一个同义词 对于“子窗口”。

    总而言之,在应用程序窗口内单击的任何按钮都将转换为带有 BN_CLICKED wParam 的 WM_COMMAND。这包括窗口的关闭按钮。

    要处理组合框中的特定点击,您有两种选择。最简单的方法是过滤发送消息的控件的 hWnd,您应该已经知道组合框的窗口句柄,与它进行比较应该不是问题。

    另一种选择是定义您自己的消息并在您的 WndProc 处理程序中检查这些消息。网络上充满了如何定义自己的应用程序/控件特定消息的示例。

    【讨论】:

    • 很好的解释。我很感激您为我指明了正确的方向。
    【解决方案2】:

    当您单击“退出”菜单时,Windows 还会向“WindowProcedure”函数发送“BN_CLICKED”消息,这就是出现消息框的原因。您应该为按钮使用 ID,而不是像这样将“hmenu”参数设置为“NULL”:

        hselectOK = CreateWindow("BUTTON", "Ok", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON | WS_DISABLED, 320,45, 100, 21,hwnd, 
    (HMENU)305, // Here is the ID of your button ( You may use your own ID )
    hInstance, NULL);
    

    您必须在您的“案例 BN_CLICKED”中添加一些 ID 检查代码,如下所示:

    case BN_CLICKED: // When user has chosen a list, the button is used to proceed with further task associated to the selected item.
    {
        // You must do this check otherwise the message box will appear again when you click the 'Exit' menu
        if ( LOWORD(wParam) == 305 ) // '305' is the ID which I have used as the button ID in above code
        {
            // Now add your click event code here
        }
    }
    break;
    

    【讨论】:

    • 非常感谢。现在我明白为什么会这样了。再次感谢
    猜你喜欢
    • 2011-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    相关资源
    最近更新 更多