按钮和组合框 WinAPI
Posted
技术标签:
【中文标题】按钮和组合框 WinAPI【英文标题】:Push button and combo box 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 下的消息框,然后程序关闭。我期待当我们关闭程序时,不会出现这样的消息框,但事实并非如此。我的意思是,消息框出现两次,一次是选择单击按钮时,一次是要关闭程序时。为什么会这样。任何想法或建议?
【问题讨论】:
【参考方案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;
【讨论】:
非常感谢。现在我明白为什么会这样了。再次感谢以上是关于按钮和组合框 WinAPI的主要内容,如果未能解决你的问题,请参考以下文章
带有按钮、组合框和文本框的 C# WinForms (.NET Framework) DataGridView:使用按钮添加新行以添加组合框项时出错