Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/26: Рейтинг темы: голосов - 26, средняя оценка - 5.00
20 / 20 / 7
Регистрация: 27.10.2012
Сообщений: 156

Удаление кнопки при нажатии на нее

08.01.2013, 15:11. Показов 6131. Ответов 35
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
В блоке WM_CREATE создаю кнопку:
C++
1
2
hwnd_buttonEndInput = CreateWindow(TEXT("button"), L"Готово", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            190, 10, 120, 30, hwnd, (HMENU)00001, hInst, NULL);
При нажатии по ней она должна уничтожиться, почему этого не присходит?

C++
1
2
3
4
5
case WM_COMMAND:
{
     if(LOWORD(wParam)==00001)
           SendMessage(hwnd_buttonEndInput, WM_DESTROY, 0, 0);
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
08.01.2013, 15:11
Ответы с готовыми решениями:

При нажатии правой кнопки мыши на форме с нее удаляются все кнопки
Написать программу, динамически порождающую на окне кнопки или метки. Левый верхний угол элемента управления определяется местоположением...

При нажатии правой кнопки мыши на форме с нее удаляются все кнопки
Написать программу, динамически порождающую на окне кнопки или метки. Левый верхний угол элемента управления определяется местоположением...

Анимация кнопки при нажатии на нее
Доброго времени суток. У меня возникла проблема: мне нужно, чтобы при нажатии на кнопку (может быть и не кнопка) она меняла свой вид, т.е....

35
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,112
06.10.2020, 13:58
Студворк — интернет-сервис помощи студентам
Не достаточно кода для анализа.
Иногда гораздо проще найти проблему с помощью отладчика, чем пытаться вычислить её аналитически глядя в код, тем более в псевдо код лишь части программы. А что есть в стеке вызовов на момент краша? Возможно вы позже пытаетесь что-то сделать со своим комбобоксом, который уже удалили. Попробуйте обнулить хендл окна сразу после его удаления, это не исправит ошибки, но возможно результат выполнения измениться и появится больше информации для размышления.

Добавлено через 31 минуту
Мне удалось повторить падение у себя. Возможно, я понял в чём дело.
Нельзя удалить контрол внутри обработчика его сообщения.
Следом за CBN_SELCHANGE, контрол посылает ещё ряд сообщений.
Уничтожая окно мы рушим его внутренности и при попытке отправки очередных сообщений происходит развал.
Можно обойти это отложенным удалением контрола. Например, отправить самому себе с помощью post сообщение. Сообщение помещается в конец очереди и будет выполнено после всех оставшихся операций контрола.
Кусочек кода, который иллюстрирует предложенный механизм отложенного удаления:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
        case WM_USER:
            if (lParam == (LPARAM)hCombo)
            {
                DestroyWindow(hCombo);
                hCombo = 0;
            }
            break;
 
        case WM_COMMAND:
            if (lParam == (LPARAM)hCombo)
            {
                WORD notifyCode = HIWORD(wParam);
                if (notifyCode == CBN_SELCHANGE)
                {
                    PostMessage(hWnd, WM_USER, 0, lParam);
                    // краш
                    //DestroyWindow(hCombo);
                    //hCombo = 0;
                }
            }
            break;
 
        case WM_RBUTTONUP:
            if (hCombo)
            {
                DestroyWindow(hCombo);
                hCombo = 0;
            }
            else
            {
                hCombo = CreateWindow(L"COMBOBOX", L"test", WS_VISIBLE | WS_CHILD | CBS_DROPDOWNLIST, 40, 40, 200, 200, hWnd, 0, hInst, 0);
                SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)L"string1");
                SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)L"string2");
                SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM)L"string3");
            }
            break;
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
06.10.2020, 15:06
Цитата Сообщение от Ygg Посмотреть сообщение
Можно обойти это отложенным удалением контрола. Например, отправить самому себе с помощью post сообщение.
Спасибо!! PostMessage() с WM_CLOSE - сработало!
1
фрилансер
 Аватар для Алексей1153
6465 / 5678 / 1131
Регистрация: 11.10.2019
Сообщений: 15,118
06.10.2020, 15:10
как говорится - вместо тысячи слов

C
1
ShowWindow(handle,SW_HIDE);
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
06.10.2020, 15:18
Цитата Сообщение от Алексей1153 Посмотреть сообщение
как говорится - вместо тысячи слов

C
1
ShowWindow(handle,SW_HIDE);
Хотелось именно уничтожит окно, а не свернуть его.
0
Эксперт CЭксперт С++
 Аватар для liv
5120 / 4574 / 855
Регистрация: 07.10.2015
Сообщений: 9,462
06.10.2020, 18:00
Не
Цитата Сообщение от Optimus11 Посмотреть сообщение
свернуть его
а сделать невидимым! После этой команды контрола не будет видно. Зачем его "убивать"? Спрятал и всех делов!

Добавлено через 3 минуты
C++
1
        ShowWindow(GetDlgItem(hWnd, IDC_CONTROL), SW_HIDE);
где hWnd - handle основного окна, IDC_CONTROL - ID нужного контрола

Добавлено через 44 секунды
И все!

Добавлено через 56 секунд
Аналогично можно и "воскресить" нужный контрол:
C++
1
ShowWindow(GetDlgItem(hWnd, IDC_CONTROL), SW_SHOW);
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
06.10.2020, 18:38
Цитата Сообщение от liv Посмотреть сообщение
Неа сделать невидимым! После этой команды контрола не будет видно. Зачем его "убивать"? Спрятал и всех делов!
Но, зачем прятать, если можно убить, в итоге таким же простым способом в одну функцию ?

Более того, когда кнопку нужно удалить, то те кнопки, которые созданы после этой удаленной кнопки - их положение нужно сместить на то место откуда удалилась кнопка. Может конфликтов не будет в случае с сворачиванием, а вдруг и будет ? Зачем проверить, если можно уничтожить ?
0
фрилансер
 Аватар для Алексей1153
6465 / 5678 / 1131
Регистрация: 11.10.2019
Сообщений: 15,118
06.10.2020, 18:43
Цитата Сообщение от Optimus11 Посмотреть сообщение
их положение нужно сместить на то место откуда удалилась кнопка
я ещё понимаю в Qt такую акробатику - там это делается в одно движение.
я ещё с натяжкой понимаю это в MFC, если вдруг захотелось магии, чёрт с ним, бывает такое.
но добровольный мазохизм - это я не понимаю!

Цитата Сообщение от Optimus11 Посмотреть сообщение
Может конфликтов не будет
про какие конфликты речь ?
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
06.10.2020, 18:45
Цитата Сообщение от Алексей1153 Посмотреть сообщение
я ещё понимаю в Qt такую акробатику - там это делается в одно движение.
я ещё с натяжкой понимаю это в MFC, если вдруг захотелось магии, чёрт с ним, бывает такое.
но добровольный мазохизм - это я не понимаю!
А как по другому это можно сделать ?


Цитата Сообщение от Алексей1153 Посмотреть сообщение
про какие конфликты речь ?
На самом деле я не знаю, просто подумал, что вдруг как то наложатся друг на друга и артефакты может какие будут. Так я не проверял.
0
фрилансер
 Аватар для Алексей1153
6465 / 5678 / 1131
Регистрация: 11.10.2019
Сообщений: 15,118
06.10.2020, 18:53
Цитата Сообщение от Optimus11 Посмотреть сообщение
А как по другому это можно сделать
написать свой компоновщик наподобие кутешного )) Но стОит ли оно затраченных усилий?

Цитата Сообщение от Optimus11 Посмотреть сообщение
артефакты может какие будут
InvalidateRect родительского окна всё исправит
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
06.10.2020, 21:23
Цитата Сообщение от Optimus11 Посмотреть сообщение
Спасибо!! PostMessage() с WM_CLOSE - сработало!
Однако есть один непонятный момент: после успешного завершения PostMessage() и уничтожения, в том числе визуального - окна-комбобокса, я ради проверки вызвал функцию:

C++
1
2
3
RECT my_RECT;
 
GetWindowRect(hwnd_combo,&my_RECT);
И GetWindowRect - завершился успешно. Если окно уничтожено, как это может быть.
0
фрилансер
 Аватар для Алексей1153
6465 / 5678 / 1131
Регистрация: 11.10.2019
Сообщений: 15,118
06.10.2020, 21:27
Optimus11, GetLastError после вызова GetWindowRect вернёт ошибку. Да и сам GetWindowRect вернёт 0, наверное
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
06.10.2020, 21:29
Цитата Сообщение от Алексей1153 Посмотреть сообщение
Optimus11, GetLastError после вызова GetWindowRect вернёт ошибку. Да и сам GetWindowRect вернёт 0, наверное
Нет, в этом то и дело, что GetWindowRect возвращает 1 и заполненную структуру RECT.
0
фрилансер
 Аватар для Алексей1153
6465 / 5678 / 1131
Регистрация: 11.10.2019
Сообщений: 15,118
06.10.2020, 21:43
Optimus11, а, после WM_CLOSE то? Ну таки да, окно ещё живое, его просто "закрыли". После WM_DESTROY будут возвращаться ошибки

Добавлено через 34 секунды
Spy++ в помощь, он покажет текущую иерархию окон
1
2735 / 890 / 331
Регистрация: 10.02.2018
Сообщений: 2,112
06.10.2020, 21:57
Цитата Сообщение от Optimus11 Посмотреть сообщение
после успешного завершения PostMessage...
После успешного завершения PostMessage окно ещё не уничтожено.
PostMessage поставил сообщение в очередь и вернул управление обратно.
Обработка будет позже, на то оно и отложенное удаление.
Или я не понимаю, что именно вы делаете и где проверяете.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
wchar_t _wcMsg1[512];
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_USER:
            if (lParam == (LPARAM)hCombo)
            {
                BOOL isWindow = IsWindow(hCombo);
                RECT rcCombo = {};
                BOOL getRect = GetWindowRect(hCombo, &rcCombo);
                wchar_t wcMsg[1024];
                wsprintf(wcMsg, L"post:\n%s\n\nuser:\nhwnd=%p\nisWindow(combo)=%s\nGetWindowRect(combo, {%d,%d,%d,%d})=%s",
                    _wcMsg1,
                    hCombo,
                    isWindow ? L"true" : L"false",
                    rcCombo.left, rcCombo.top, rcCombo.right, rcCombo.bottom, getRect ? L"true" : L"false");
                MessageBox(0, wcMsg, L"combo closed", MB_OK);
 
                hCombo = 0;
            }
            break;
 
        case WM_COMMAND:
            if (lParam == (LPARAM)hCombo)
            {
                WORD notifyCode = HIWORD(wParam);
                if (notifyCode == CBN_SELCHANGE)
                {
                    PostMessage(hCombo, WM_CLOSE, 0, 0);
 
                    BOOL isWindow = IsWindow(hCombo);
                    RECT rcCombo = {};
                    BOOL getRect = GetWindowRect(hCombo, &rcCombo);
                    wsprintf(_wcMsg1, L"hwnd=%p\nisWindow(combo)=%s\nGetWindowRect(combo, {%d,%d,%d,%d})=%s",
                        hCombo,
                        isWindow ? L"true" : L"false",
                        rcCombo.left, rcCombo.top, rcCombo.right, rcCombo.bottom, getRect ? L"true" : L"false");
 
                    PostMessage(hWnd, WM_USER, 0, lParam);
                }
            }
            break;
//...
У меня появляется сообщение с таким текстом:
Code
1
2
3
4
5
6
7
8
9
post:
hwnd=001605DC
isWindow(combo)=true
GetWindowRect(combo, {100,123,300,147})=true
 
user:
hwnd=001605DC
isWindow(combo)=false
GetWindowRect(combo, {0,0,0,0})=false
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
06.10.2020, 22:24
Цитата Сообщение от Ygg Посмотреть сообщение
После успешного завершения PostMessage окно ещё не уничтожено.
PostMessage поставил сообщение в очередь и вернул управление обратно.
Обработка будет позже, на то оно и отложенное удаление.
Или я не понимаю, что именно вы делаете и где проверяете.
Спасибо, да, я проверял сразу после вызова PostMessage, если сделать проверку в другом отловленном сообщении WM_COMMAND, то IsWindow и GetWindowRect - завершаются ошибкой.
1
Эксперт CЭксперт С++
 Аватар для liv
5120 / 4574 / 855
Регистрация: 07.10.2015
Сообщений: 9,462
07.10.2020, 11:04
Цитата Сообщение от Optimus11 Посмотреть сообщение
просто подумал, что вдруг как то наложатся друг на друга и артефакты может какие будут. Так я не проверял.
Никаких артефактов! Я только так и делаю. Причем создаю сразу ВСЕ органы управления, одни видимые, другие невидимые. У меня их обычно под сотню. Потом, по необходимости, тасую контролы, как надо. Два плюса от этого: быстрее и проще.
Короче, это альтернатива удалению. Делайте, как Вам хочется...

Добавлено через 6 минут
Цитата Сообщение от Optimus11 Посмотреть сообщение
простым способом в одну функцию
Еще и WM_USER надо отработать...
А, возможно, еще и проанализировать о каком контроле(ах) идет речь... Оно вроде и несложно, но все же.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
07.10.2020, 11:04
Помогаю со студенческими работами здесь

Перемещение кнопки при нажатии на неё
Всем привет! Я только учусь. По самоучителю. Поэтому вопросы очень простые. В книге есть такое задание: при нажатии на кнопку, она должна...

Изменение координат кнопки при нажатии на нее
Есть кнопка, которая находиться в верху окна. Нажав на нее, она должна опуститься ниже на определенное число пунктов. Как это реализовать?

Смена цвета кнопки при нажатии на нее
Помгогите пожалуйста, возник такой вопрос: как сделать что бы при нажатии на кнопку она меняла цвет, а при двойном клике (или клике правой...

Изменение теста кнопки при нажатии на нее в DataTable
Опять вопрос про DataTable. Есть своя кнопка: { text: '<i class="roll" style="font-style:...

Как изменить цвет кнопки при нажатии на нее?
в процедуре procedure Form1.button2_Click(sender: Object; e: EventArgs); Пишу button2.backcolor:=red; и мне выдает ошибку...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
36
Ответ Создать тему
Новые блоги и статьи
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru