20 / 20 / 7
Регистрация: 27.10.2012
Сообщений: 156

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

08.01.2013, 15:11. Показов 6228. Ответов 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
2736 / 891 / 331
Регистрация: 10.02.2018
Сообщений: 2,123
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
6479 / 5702 / 1132
Регистрация: 11.10.2019
Сообщений: 15,188
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
6479 / 5702 / 1132
Регистрация: 11.10.2019
Сообщений: 15,188
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
6479 / 5702 / 1132
Регистрация: 11.10.2019
Сообщений: 15,188
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
6479 / 5702 / 1132
Регистрация: 11.10.2019
Сообщений: 15,188
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
6479 / 5702 / 1132
Регистрация: 11.10.2019
Сообщений: 15,188
06.10.2020, 21:43
Optimus11, а, после WM_CLOSE то? Ну таки да, окно ещё живое, его просто "закрыли". После WM_DESTROY будут возвращаться ошибки

Добавлено через 34 секунды
Spy++ в помощь, он покажет текущую иерархию окон
1
2736 / 891 / 331
Регистрация: 10.02.2018
Сообщений: 2,123
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
Ответ Создать тему
Опции темы

Новые блоги и статьи
Асинхронный приём данных из COM-порта
Argus19 01.05.2026
Асинхронный приём данных из COM-порта Купил на aliexpress термопринтер QR701. Он оказался странным. Поключил к Arduino Nano. Был очень удивлён. Наотрез отказывается печатать русские буквы. Чтобы. . .
попытка написать игровой сервер на C++
pyirrlicht 29.04.2026
попытка написать игровой сервер на плюсах с открытым бесконечным миром. возможно получится прикрутить интерпретатор питон для кастомизации игровой логики. что есть на текущий момент:. . .
Контроль уникальности выбранного документа-основания при изменении реквизита
Maks 28.04.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРемонтСпецтехники", разработанного в КА2. Задача: уведомлять пользователя, если указанная заявка (документ-основание). . .
Благородство как наказание
Maks 24.04.2026
У хорошего человека отношения с женщинами всегда складываются трудно. А я человек хороший. Заявляю без тени смущения, потому что гордиться тут нечем. От хорошего человека ждут соответствующего. . .
Валидация и контроль данных табличной части документа перед записью
Maks 22.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в КА2. Задача: контроль и валидация данных табличной части документа перед записью с учетом регламента компании. . .
Отчёт о затраченных материалах за определенный период с макетом печатной формы
Maks 21.04.2026
Отчёт из решения ниже размещён в конфигурации КА2. Задача: разработка отчёта по затраченным материалам за определённый период, с возможностью вывода печатной формы отчёта с шапкой и подвалом. В. . .
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2. Задача: отобразить спецтехнику, которая на данный момент находится в ремонте. Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
Памятка для бота и "визитка" для читателей "Semantic Universe Layer (Слой семантической вселенной)"
Hrethgir 19.04.2026
Сгенерировано для краткого описания по случаю сборки и компиляции скелета серверного приложения. И пусть после этого скажут, что статьи сгенерированные AI - туфта и не интересно. И это не реклама -. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru