按钮和组合框WinAPI

时间:2015-01-20 09:05:02

标签: c++ c winapi user-interface

我正在尝试做一些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

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

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

2 个答案:

答案 0 :(得分:1)

问题在于您假设WM_COMMAND是您的ComboBox唯一的消息,而不是。

看看这个旧的但是金blog post

引自作者,

  

wParam参数的高位字&#34;指定   通知代码,如果消息来自控件&#34;。是什么   &#34;控制&#34;这意味着什么请记住,你必须把事情放在上下文中。   WM_COMMAND消息正在Win32的上下文中呈现   一般而言,特别是在窗口管理器的上下文中。   通常是诸如编辑框,按钮和列表框之类的窗口   调用&#34;控制&#34;,以及&#34;常见的所有窗口类   控制图书馆&#34;。在窗口管理器的世界中,一个&#34;控制&#34;是   一个窗口,其目的是提供一定程度的交互性   (在静态控制的情况下,可能没有交互性   在其父窗口的服务中。这个事实   WM_COMMAND主要用于对话框的上下文中   强调术语&#34;控制&#34;这只是一个同义词   for&#34; child window&#34;。

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

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

另一个选项是定义自己的消息并检查WndProc处理程序中的消息。 Web上有很多关于如何定义自己的应用程序/控件特定消息的示例。

答案 1 :(得分:0)

当您单击“退出”菜单时,窗口还会向“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;