Кнопка и поле со списком WinAPI

0

Я пытаюсь сделать некоторые окна программирования. Я создал поле со списком и кнопку. Моя цель заключается в том, что когда пользователь выбирает элемент в поле со списком, кнопка активируется и ее нужно нажать, чтобы продолжить. Я сделал что-то вроде этого до сих пор:

Вот как я создаю поле со списком:

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, а затем программа закрывается. Я ожидаю, что когда мы закроем программу, такого окна сообщений не появится, но это не так. Я говорю, что окно сообщения появляется дважды, один раз, когда вы нажимаете кнопку и когда вы хотите закрыть программу. Почему это происходит. Любые идеи или предложения?

Теги:
user-interface
winapi

2 ответа

0
Лучший ответ

Когда вы нажимаете меню "Выход", окна также отправляют сообщение "BN_CLICKED" в функцию "WindowProcedure", поэтому появляется окно с сообщением. Вы должны использовать идентификатор для кнопки, а не использовать параметр "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" код проверки идентификатора:

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;
  • 0
    Большое спасибо. Теперь я понимаю, почему это происходит. еще раз спасибо
  • 0
    @tarmizi, пожалуйста.
1

Проблема в том, что вы считаете, что WM_COMMAND - это сообщение, уникальное для вашего ComboBox, а это не так.

Взгляните на этот старый, но золотой блог.

Цитируя от автора,

Слово высокого порядка параметра wParam "указывает код уведомления, если сообщение принадлежит элементу управления". Что здесь означает "контроль"? Помните, что вы должны воспринимать вещи в контексте. Сообщение WM_COMMAND представляется в контексте Win32 в целом и в контексте диспетчера окон в частности. Windows, такие как поля редактирования, кнопки и списки, обычно называются "элементами управления", как и все классы окон в "общей библиотеке управления". В мире оконного менеджера "элемент управления" - это окно, целью которого является обеспечение некоторой степени интерактивности (которая в случае статического контроля вообще не может быть никакой интерактивностью) в сервисе его родительского окна. Тот факт, что WM_COMMAND используется в основном в контексте диалоговых окон, еще раз подчеркивает, что термин "контроль" здесь является всего лишь синонимом "дочернего окна".

Подводя итог, любое нажатие кнопки внутри вашего окна приложения будет транслироваться как WM_COMMAND с помощью BN_CLICKED wParam. Это включает кнопку закрытия окна.

Чтобы обрабатывать определенные клики из вашего комбинированного поля, у вас есть два варианта. Простым способом является фильтрация hWnd элемента управления, который отправил сообщение, вы уже должны знать дескриптор окна вашего поля со списком, и это не должно быть проблемой для сравнения с ним.

Другой вариант - определить ваши собственные сообщения и проверить их в обработчике WndProc. В Интернете полно примеров того, как определять собственные сообщения приложения/управления.

  • 0
    Хорошее объяснение. Я благодарен, что вы указали мне правильное направление.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню