Сделать предыдущую кнопку не нажатой (не выпуклой)

314
06 ноября 2017, 22:40

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

Не получаются две вещи:

1) не могу найти функции, чтобы сделать кнопку вдавленной (нажатой), поэтому заменила пока на EnableWindow;

2) не могу отжать ту кнопку которая была нажата ранее (т.к. если например делать циклом, то получается нецелесообразно из-за времени, т.к. кнопок может быть 80000). И глобалить нельзя.

#include <Windows.h> 
#define sizemas 4
#define ID_CUR 3 
#define ID_BUTTON 125 
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MSG msg;
    WNDCLASS wclass = { 0 };
    POINT p = { 0 };
    wclass.hInstance = hInstance;
    wclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wclass.lpfnWndProc = WindowProc;
    wclass.lpszClassName = "WinName";
    wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    if (!RegisterClass(&wclass))
        return 0;
    int x = GetSystemMetrics(SM_CXSCREEN);
    int y = GetSystemMetrics(SM_CYSCREEN);
    HWND hwnd = CreateWindow(
        wclass.lpszClassName,
        "Main",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        0.6*x,
        0.6*y,
        NULL,
        NULL,
        hInstance,
        NULL);
    ShowWindow(hwnd, nCmdShow);
    char buff[1024] = { 0 };
    HWND hButton[sizemas + 1], hRadioButton[sizemas + 1];
    for (int i = 1; i <= sizemas; i++) {
        wsprintf(buff, "Кнопка %d", i);
        hButton[i] = CreateWindow("BUTTON", buff, BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD, 30, 60 * i, 240, 50, hwnd, (HMENU)(ID_BUTTON + i), hInstance, NULL);
    }
    for (int i = 1; i <= sizemas; i++) {
        hRadioButton[i] = CreateWindow("BUTTON", "RadioButton ", BS_AUTORADIOBUTTON | WS_VISIBLE | WS_CHILD, 630, 60 * i, 240, 50, hwnd, (HMENU)(ID_BUTTON + i + sizemas), hInstance, NULL);
    }
    CheckDlgButton(hwnd, ID_CUR + ID_BUTTON + sizemas, 1);
    EnableWindow(GetDlgItem(hwnd, ID_CUR + ID_BUTTON), false);
    SetWindowLong(hwnd, GWL_USERDATA, (LONG)&p);

    while (GetMessage(&msg, NULL, 0, 0))
        DispatchMessage(&msg);
    return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg)
    {
    case WM_COMMAND: {
        POINT *p = (POINT *)GetWindowLong(hwnd, GWL_USERDATA);
        if (LOWORD(wParam) > ID_BUTTON && LOWORD(wParam) <= (sizemas + ID_BUTTON)) {
            if ((LOWORD(wParam) + ID_CUR - 1) != (ID_CUR + ID_BUTTON)) {
                CheckDlgButton(hwnd, p->x + sizemas, 0);
                EnableWindow(GetDlgItem(hwnd, p->x), true);
            }
            CheckDlgButton(hwnd, LOWORD(wParam) + sizemas, BST_CHECKED);
            EnableWindow(GetDlgItem(hwnd, LOWORD(wParam)), false);
            p->x = LOWORD(wParam);
            SetWindowLong(hwnd, GWL_USERDATA, (LONG)&p);

        }
        /*if (LOWORD(wParam) > (ID_BUTTON + sizemas)) {
            for (int i = 1; i <= sizemas; i++) {
                EnableWindow(GetDlgItem(hwnd, ID_BUTTON + i), true);
            }
            CheckDlgButton(hwnd, LOWORD(wParam), BST_CHECKED);
            EnableWindow(GetDlgItem(hwnd, LOWORD(wParam) - sizemas), false);
        }*/
        return 0;
    }
    case WM_SIZE:
        InvalidateRect(hwnd, NULL, TRUE);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Answer 1

Это достаточно просто, кнопки можно сгруппировать для автоматического переключения внутри группы используя стиль WS_GROUP и BS_AUTORADIOBUTTON. Так как тут группы две (кнопки и радио кнопки) то переключить кнопку в противоположной группе нужно руками

// глобальные
const int buttons_count = 4;
const int buttons_id_delta = 1000;
const int buttons_id_first = 100;
int checked_button_id = 0;
int checked_radio_button_id = 0;

// создаем окна
DWORD window_style;
int button_index;
// создаем кнопки, первая будет иметь доп стиль WS_GROUP
window_style = WS_GROUP | BS_PUSHLIKE | BS_AUTORADIOBUTTON | WS_VISIBLE | WS_CHILD;
button_index = 0;
do
{
    CreateWindowW(L"BUTTON", L"Test", window_style, 30, 60 * button_index, 240, 50, hWnd
        , (HMENU) (buttons_id_first + button_index), NULL, NULL);
    window_style = BS_PUSHLIKE | BS_AUTORADIOBUTTON | WS_VISIBLE | WS_CHILD;
    ++button_index;
}
while(buttons_count != button_index);
// создаем радиокнопки, первая будет иметь доп стиль WS_GROUP
window_style = WS_GROUP | BS_AUTORADIOBUTTON | WS_VISIBLE | WS_CHILD;
button_index = 0;
do
{
    CreateWindowW(L"BUTTON", L"Test", window_style, 300, 60 * button_index, 240, 50, hWnd
        , (HMENU) (buttons_id_first + buttons_id_delta + button_index), NULL, NULL);
    window_style = BS_AUTORADIOBUTTON | WS_VISIBLE | WS_CHILD;
    ++button_index;
}
while(buttons_count != button_index);
// обработчик сообщений
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_COMMAND:
        {
            const int control_id = LOWORD(wParam);
            if
            (
                (buttons_id_first <= control_id)
                &&
                (control_id < (buttons_id_first + buttons_count))
            )
            {
                // пользователь нажал на кнопку
                checked_button_id = control_id;
                // выключаем ранее нажатую радио кнопку
                if(0 != checked_radio_button_id)
                {
                    SendMessage(GetDlgItem(hWnd, checked_radio_button_id), BM_SETCHECK, BST_UNCHECKED, 0);
                }
                // включаем новую радио кнопку
                checked_radio_button_id = control_id + buttons_id_delta;
                SendMessage(GetDlgItem(hWnd, checked_radio_button_id), BM_SETCHECK, BST_CHECKED, 0);
            }
            else if
            (
                ((buttons_id_first + buttons_id_delta) <= control_id)
                &&
                (control_id < (buttons_id_first + buttons_id_delta + buttons_count))
            )
            {
                // пользователь нажал на радио кнопку
                checked_radio_button_id = control_id;
                // выключаем ранее нажатую кнопку
                if(0 != checked_button_id)
                {
                    SendMessage(GetDlgItem(hWnd, checked_button_id), BM_SETCHECK, BST_UNCHECKED, 0);
                }
                // включаем новую кнопку
                checked_button_id = control_id - buttons_id_delta;
                SendMessage(GetDlgItem(hWnd, checked_button_id), BM_SETCHECK, BST_CHECKED, 0);
            }
            else
            {
                // прочее...
                break;
            }
            // обязятельно вызываем
            DefWindowProc(hWnd, message, wParam, lParam);
            break;
        }

результат:

READ ALSO
Как сделать так, чтобы в шаблонно бинарном дереве содержались объекты пользовательского класса не разрушались,после инициализации?

Как сделать так, чтобы в шаблонно бинарном дереве содержались объекты пользовательского класса не разрушались,после инициализации?

Нужно сделать так, чтобы в шаблонном бинарном дереве содержались объекты пользовательского класса T и не разрушались после инициализацииДобавление...

299
DirectX - не удается открыть файл

DirectX - не удается открыть файл

При компиляции проекта в конфигурации Release и платформе Win32(да, во вех остальных случаях работает) получаю следующую ошибку:

356
Qt + Tesseract как исправить проблемы

Qt + Tesseract как исправить проблемы

Подскажите пожалуйста как правильно прописать в про файле путь к либам

252