Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Обработка нажатия на Radiobutton


Автор: gabin 22.10.2011, 21:54
Подскажите как сделать чтобы при нажатии на определённый элемент radiobutton'a выбирался соответствующий элемент listbox'а и наоборот.
Да и нажатие на RADIOGROUP почему-то не обрабатывается.

Вот код:
Код

#include "stdafx.h"
#include "spz_lab2.h"

#define MAX_LOADSTRING 100

// Глобальные переменные:
HINSTANCE hInst;                                // текущий экземпляр
TCHAR szTitle[MAX_LOADSTRING];                    // Текст строки заголовка
TCHAR szWindowClass[MAX_LOADSTRING];            // имя класса главного окна
HWND hWnd20;
// Отправить объявления функций, включенных в этот модуль кода:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: разместите код здесь.
    MSG msg;
    HACCEL hAccelTable;

    // Инициализация глобальных строк
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_SPZ_LAB2, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Выполнить инициализацию приложения:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SPZ_LAB2));

    // Цикл основного сообщения:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  ФУНКЦИЯ: MyRegisterClass()
//
//  НАЗНАЧЕНИЕ: регистрирует класс окна.
//
//  КОММЕНТАРИИ:
//
//    Эта функция и ее использование необходимы только в случае, если нужно, чтобы данный код
//    был совместим с системами Win32, не имеющими функции RegisterClassEx'
//    которая была добавлена в Windows 95. Вызов этой функции важен для того,
//    чтобы приложение получило "качественные" мелкие значки и установило связь
//    с ними.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SPZ_LAB2));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = MAKEINTRESOURCE(IDC_SPZ_LAB2);
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

//
//   ФУНКЦИЯ: InitInstance(HINSTANCE, int)
//
//   НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и создает главное окно.
//
//   КОММЕНТАРИИ:
//
//        В данной функции дескриптор экземпляра сохраняется в глобальной переменной, а также
//        создается и выводится на экран главное окно программы.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;
   HWND hWnd1,hWnd2,hWnd3,hWnd4,hWnd5,hWnd6;
   
   hInst = hInstance; // Сохранить дескриптор экземпляра в глобальной переменной

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
   // Создаём GROUPBOX
   hWnd1 = CreateWindow(L"BUTTON",L"Выберите пункт",BS_GROUPBOX|WS_CHILD,10,10,140,135,hWnd,(HMENU)GROUPBOX_1,NULL,NULL); 
   ShowWindow(hWnd1, SW_SHOW);
   hWnd2 = CreateWindow(L"BUTTON",L"Первый",BS_AUTORADIOBUTTON|WS_CHILD|BST_CHECKED,10,30,80,20,hWnd1,(HMENU)IDE_RADIO_1,NULL,NULL); // Радио кнопка №1
    ShowWindow(hWnd2, SW_SHOW);
   hWnd3 = CreateWindow(L"BUTTON",L"Второй",BS_AUTORADIOBUTTON|WS_CHILD,10,50,80,20,hWnd1,(HMENU)IDE_RADIO_2,NULL,NULL);
   ShowWindow(hWnd3, SW_SHOW);
   hWnd4 = CreateWindow(L"BUTTON",L"Третий",BS_AUTORADIOBUTTON|WS_CHILD,10,70,80,20,hWnd1,(HMENU)IDE_RADIO_3,NULL,NULL);
   ShowWindow(hWnd4, SW_SHOW);
   hWnd5 = CreateWindow(L"BUTTON",L"Четвёртый",BS_AUTORADIOBUTTON|WS_CHILD,10,90,90,20,hWnd1,(HMENU)IDE_RADIO_4,NULL,NULL);
   ShowWindow(hWnd5, SW_SHOW);
   hWnd6 = CreateWindow(L"BUTTON",L"Пятый",BS_AUTORADIOBUTTON|WS_CHILD,10,110,80,20,hWnd1,(HMENU)IDE_RADIO_5,NULL,NULL);
   ShowWindow(hWnd6, SW_SHOW);

   hWnd20 = CreateWindow(L"LISTBOX",L"ListBox1",WS_CHILD|LBS_EXTENDEDSEL,10,160,140,135,hWnd,(HMENU)IDE_LISTBOX_1,hInstance,NULL);
   ShowWindow(hWnd20,SW_SHOW);
   SendMessage(hWnd20,LB_ADDSTRING,0,(LPARAM)TEXT("Первый"));
   SendMessage(hWnd20,LB_ADDSTRING,0,(LPARAM)TEXT("Второй"));
   SendMessage(hWnd20,LB_ADDSTRING,0,(LPARAM)TEXT("Третий"));
   SendMessage(hWnd20,LB_ADDSTRING,0,(LPARAM)TEXT("Четвёртый"));
   SendMessage(hWnd20,LB_ADDSTRING,0,(LPARAM)TEXT("Пятый"));
   SendMessage(hWnd20,LB_SETSEL,TRUE,0);
   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);   
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  НАЗНАЧЕНИЕ:  обрабатывает сообщения в главном окне.
//
//  WM_COMMAND    - обработка меню приложения
//  WM_PAINT    -Закрасить главное окно
//  WM_DESTROY     - ввести сообщение о выходе и вернуться.
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
    int nItem; HWND hwndList;
    switch (message)
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Разобрать выбор в меню:
        switch (wmId)
        {
            
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDE_LISTBOX_1:
            MessageBox(hWnd,L"Listbox Pressed",L"pressed",MB_OK);
            break;
        case GROUPBOX_1:
            MessageBox(hWnd,L"Radiobutton Pressed",L"pressed",MB_OK);     // Не обрабатывается 
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break; 
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: добавьте любой код отрисовки...
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Обработчик сообщений для окна "О программе".
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}


Автор: BorisVorontsov 23.10.2011, 15:07
Во-первых, GroupBox не объединяет RadioButton'ы в группу, для этого служит стиль WS_GROUP, который следует задавать первой кнопке в группе.
Во-вторых, WM_COMMAND от RadioButton'ов отсылается родительскому окну, которым в данном случае является GroupBox

Автор: Earnest 24.10.2011, 07:04
Цитата(BorisVorontsov @  23.10.2011,  16:07 Найти цитируемый пост)
которым в данном случае является GroupBox 

И лучше так не делать, иначе для обработки сообщений от радио-кнопок придется сабклассить еще и этот групбокс, который по сути своей просто статик. Обычно родителем делают основное окно.

Автор: gabin 24.10.2011, 18:16
Цитата(BorisVorontsov @  23.10.2011,  15:07 Найти цитируемый пост)
Во-первых, GroupBox не объединяет RadioButton'ы в группу, для этого служит стиль WS_GROUP, который следует задавать первой кнопке в группе.
Во-вторых, WM_COMMAND от RadioButton'ов отсылается родительскому окну, которым в данном случае является GroupBox

Мой GroupBox событие WM_COMMAND не перехватывает (код выше) . Когда указал стиль WS_GROUP первой RadioButton кнопке, то она исчезла вовсе. Если указываю стиль GroupBox’у то и он исчезает. 
Не пойму как всё-таки перехватить нажатие на RadioButton

Автор: Earnest 25.10.2011, 06:58
Цитата(gabin @  24.10.2011,  19:16 Найти цитируемый пост)
Мой GroupBox событие WM_COMMAND не перехватывает (код выше)

Вот именно. А посылают радио-кнопки именно ему, т.к. ты их создал с родителем = групбокс. А нужно создать кнопки с родителем = главное окно (hWnd), тогда оно и будет получать команды.

Автор: gabin 28.10.2011, 10:53
Earnest, спасибо. 
Решил данную задачку так:
Код

// spz_lab2.cpp: определяет точку входа для приложения.
//

#include "stdafx.h"
#include "spz_lab2.h"

#define MAX_LOADSTRING 100

// Глобальные переменные:
HINSTANCE hInst;                                // текущий экземпляр
TCHAR szTitle[MAX_LOADSTRING];                    // Текст строки заголовка
TCHAR szWindowClass[MAX_LOADSTRING];            // имя класса главного окна
HWND hWnd20;
// Отправить объявления функций, включенных в этот модуль кода:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: разместите код здесь.
    MSG msg;
    HACCEL hAccelTable;

    // Инициализация глобальных строк
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_SPZ_LAB2, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Выполнить инициализацию приложения:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SPZ_LAB2));

    // Цикл основного сообщения:
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}



//
//  ФУНКЦИЯ: MyRegisterClass()
//
//  НАЗНАЧЕНИЕ: регистрирует класс окна.
//
//  КОММЕНТАРИИ:
//
//    Эта функция и ее использование необходимы только в случае, если нужно, чтобы данный код
//    был совместим с системами Win32, не имеющими функции RegisterClassEx'
//    которая была добавлена в Windows 95. Вызов этой функции важен для того,
//    чтобы приложение получило "качественные" мелкие значки и установило связь
//    с ними.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SPZ_LAB2));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = MAKEINTRESOURCE(IDC_SPZ_LAB2);
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

//
//   ФУНКЦИЯ: InitInstance(HINSTANCE, int)
//
//   НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и создает главное окно.
//
//   КОММЕНТАРИИ:
//
//        В данной функции дескриптор экземпляра сохраняется в глобальной переменной, а также
//        создается и выводится на экран главное окно программы.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   HWND hWnd;
   HWND hWnd1,hWnd2,hWnd3,hWnd4,hWnd5,hWnd6;
   
   hInst = hInstance; // Сохранить дескриптор экземпляра в глобальной переменной

   hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
   // Создаём GROUPBOX
   hWnd1 = CreateWindow(L"BUTTON",L"Выберите пункт",BS_GROUPBOX|WS_CHILD,10,10,140,135,hWnd,(HMENU)GROUPBOX_1,NULL,NULL); 
   ShowWindow(hWnd1, SW_SHOW);
   hWnd2 = CreateWindow(L"BUTTON",L"Первый",BS_AUTORADIOBUTTON|WS_CHILD|BST_CHECKED,10,30,80,20,hWnd,(HMENU)IDE_RADIO_1,NULL,NULL); 
    ShowWindow(hWnd2, SW_SHOW);
   hWnd3 = CreateWindow(L"BUTTON",L"Второй",BS_AUTORADIOBUTTON|WS_CHILD,10,50,80,20,hWnd,(HMENU)IDE_RADIO_2,NULL,NULL);
   ShowWindow(hWnd3, SW_SHOW);
   hWnd4 = CreateWindow(L"BUTTON",L"Третий",BS_AUTORADIOBUTTON|WS_CHILD,10,70,80,20,hWnd,(HMENU)IDE_RADIO_3,NULL,NULL);
   ShowWindow(hWnd4, SW_SHOW);
   hWnd5 = CreateWindow(L"BUTTON",L"Четвёртый",BS_AUTORADIOBUTTON|WS_CHILD,10,90,90,20,hWnd,(HMENU)IDE_RADIO_4,NULL,NULL);
   ShowWindow(hWnd5, SW_SHOW);
   hWnd6 = CreateWindow(L"BUTTON",L"Пятый",BS_AUTORADIOBUTTON|WS_CHILD,10,110,80,20,hWnd,(HMENU)IDE_RADIO_5,NULL,NULL);
   ShowWindow(hWnd6, SW_SHOW);

   hWnd20 = CreateWindow(L"LISTBOX",L"ListBox1", WS_CHILD|WS_VISIBLE|LBS_NOTIFY|WS_VSCROLL|WS_BORDER,10,160,140,135,hWnd,(HMENU)IDE_LISTBOX_1,hInstance,NULL);
   ShowWindow(hWnd20,SW_SHOW);
   SendMessage(hWnd20,LB_ADDSTRING,0,(LPARAM)TEXT("Первый"));
   SendMessage(hWnd20,LB_ADDSTRING,0,(LPARAM)TEXT("Второй"));
   SendMessage(hWnd20,LB_ADDSTRING,0,(LPARAM)TEXT("Третий"));
   SendMessage(hWnd20,LB_ADDSTRING,0,(LPARAM)TEXT("Четвёртый"));
   SendMessage(hWnd20,LB_ADDSTRING,0,(LPARAM)TEXT("Пятый"));
   SendMessage(hWnd20,LB_SETSEL,TRUE,0);
   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);   
   UpdateWindow(hWnd);

   return TRUE;
}

//
//  ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  НАЗНАЧЕНИЕ:  обрабатывает сообщения в главном окне.
//
//  WM_COMMAND    - обработка меню приложения
//  WM_PAINT    -Закрасить главное окно
//  WM_DESTROY     - ввести сообщение о выходе и вернуться.
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
    HWND hRadio;
    switch (message)
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // Разобрать выбор в меню:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDE_LISTBOX_1:
            switch(wmEvent)
            {
                case LBN_SELCHANGE:
                        HWND hListBoxItem = GetDlgItem(hWnd, IDE_LISTBOX_1);
                        LRESULT nItem = SendMessage(hListBoxItem, LB_GETCURSEL, 0, 0);
                        switch (nItem) {
                        case 0:
                            hRadio = GetDlgItem(hWnd, IDE_RADIO_1);
                            SendMessage( hRadio, BM_CLICK, 0, 0 ); 
                            break;
                        case 1:
                            hRadio = GetDlgItem(hWnd, IDE_RADIO_2);
                            SendMessage( hRadio, BM_CLICK, 0, 0 ); 
                            break;
                        case 2:
                            hRadio = GetDlgItem(hWnd, IDE_RADIO_3);
                            SendMessage( hRadio, BM_CLICK, 0, 0 ); 
                            break;
                        case 3:
                            hRadio = GetDlgItem(hWnd, IDE_RADIO_4);
                            SendMessage( hRadio, BM_CLICK, 0, 0 ); 
                            break;
                        case 4:
                            hRadio = GetDlgItem(hWnd, IDE_RADIO_5);
                            SendMessage( hRadio, BM_CLICK, 0, 0 ); 
                            break;
                        }
                    break;
            }

            break;
        case IDE_RADIO_1:
            SendMessage(hWnd20,LB_SETCURSEL,0,0);
            break;
        case IDE_RADIO_2:
            SendMessage(hWnd20,LB_SETCURSEL,1,0);
            break;
        case IDE_RADIO_3:
            SendMessage(hWnd20,LB_SETCURSEL,2,0);
            break;
        case IDE_RADIO_4:
            SendMessage(hWnd20,LB_SETCURSEL,3,0);
            break;
        case IDE_RADIO_5:
            SendMessage(hWnd20,LB_SETCURSEL,4,0);
            break;
        case IDM_EXIT:
            DestroyWindow(hWnd);
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break; 
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Обработчик сообщений для окна "О программе".
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}


Автор: BorisVorontsov 29.10.2011, 17:16
Цитата(Earnest @  25.10.2011,  06:58 Найти цитируемый пост)
А нужно создать кнопки с родителем = главное окно (hWnd)

Нет, нужно главное окно -- диалог-контейнер, расположенный на главном окне.
Цитата(gabin @  28.10.2011,  10:53 Найти цитируемый пост)
SendMessage( hRadio, BM_CLICK, 0, 0 );

Цитата(gabin @  28.10.2011,  10:53 Найти цитируемый пост)
SendMessage(hWnd20,LB_SETCURSEL,1,0);

Используй Button_SetCheck и ListBox_SetCurSel

Автор: GremlinProg 31.10.2011, 06:16
Цитата(BorisVorontsov @  29.10.2011,  19:16 Найти цитируемый пост)
Нет, нужно главное окно -- диалог-контейнер, расположенный на главном окне.

это в идеальном случае, и для новичков это далеко не всегда удобно и понятно

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)