Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Visual C++/MFC/WTL > как правильно пересоздавать контролы/диалоги |
Автор: _hunter 29.6.2006, 10:36 | ||
Добрый день. Понадобилось пересоздать диалог. Делаю это так:
но при этом на строке newTopPanel->Create() бросается assertion "Error: no data exchange control with ID " из CDataExchange::PrepareCtrl() |
Автор: Earnest 29.6.2006, 12:58 |
Не совсем понятно: что значит "пересоздавать"? Ты ведь просто создаешь динамически панель. Но в любом случае, ошибка о которой ты пишешь, возникает, когда не находится контрол по ID. Проверь предложения DDX_ в DoDataExchange, там упоминается какой-то ид-р, не сущетвующий в диалоговом ресурсе. А зачем делать SetParent(this)? Ты и так передаешь в Create this в качестве парента. |
Автор: _hunter 29.6.2006, 13:14 |
у меня на диалоге лежит панель. я ее хочу удалить и создать заново. (в VCL это проще было...) так в первый раз она создается нормально... P.S. перед пересозданием я вызываю AfxSetResourceHandle, но все ID в ресурсах совпадают... |
Автор: Earnest 29.6.2006, 14:32 |
Из другого ресурса? Иначе зачем удалять и снова создавать то же самое. Зачем? Ресурсы в разных модулях лежат? Значит, не все. Исключение, о котором ты писал, возбуждается, если GetDlgItem (ID) возвращает 0, что бывает тогда, когда такого поля нет. Чтобы проверить, закомментируй соответствующее предложение DDX_ в DoDataExchange, а потом посмотри Спаем, совпадают ли ид-ры полей с ожидаемыми. |
Автор: _hunter 29.6.2006, 17:05 |
от Assertion' а избавился (там, оказывается невидимая панель с кучей контролов на панели лежала). но теперь из OnCmdMsg (CWnd::OnCommand()) Unhandled exception бросается. причем по стеку одни .dll а в Output' e предпоследняя строка "Access violation reading location 0x0000001f" |
Автор: Earnest 30.6.2006, 07:27 |
Debug->Exceptions: поставь опцию "When exception is thrown" в позицию "Break into debugger". Скорее всего, для Win32Exceptions. По-крайней мере должен увидеть где возникает исключение. |
Автор: _hunter 30.6.2006, 11:44 |
поставил. помогло мало ![]() исключение кидается из comctl32.dll по стеку последняя функция CWnd::OnCommand (из wincore.h) и потом одни .dll а отладчик останавливается на закрывающей } OnCommand (после OnCmdMsg) |
Автор: Earnest 30.6.2006, 13:01 |
У тебя это происходит после какой-то пользовательской команды (т.е. ты что-то делаешь - на кнопку жмешь или текст меняешь) или на IdleUpdate (это если ничего не делаешь, а оно вылетает сразу после отображения)? В первом случае проще: ставим точку прерывания на обработчик этой команды, и прослеживаем. Во втором случае, после вылета вернись по стеку назад до OnCommand и посмотри параметры сообщения: нужно выяснить чей это Update. Потом тоже самое: ставим точку прерывания на этот обработчик, и идем от него вглубь. Если обработчика нет, то можно поставить условную точку прерывания прямо в OnCommand. Если хочешь, кинь проект, попробую найти вечером. А то по телефону сложно лечить. ![]() Добавлено @ 13:03 Еще, если ты работаешь в 6й студии, проверь обработчики команд на соответствие ожидаемым сигнатурам: очень частая ошибка. |
Автор: _hunter 3.7.2006, 13:45 |
был бы очень благодарен. http://www.i.com.ua/~hunter_/Test.rar |
Автор: _hunter 3.7.2006, 14:10 |
причем в тестовом проекте глок проявляетяс только при переключении мышью. причем не всегда (т.е. при запуске одного и того же .exe-шника может как проявиться так и нет). причем если переключать колесиком -- глюк проявляется чаще... |
Автор: Earnest 3.7.2006, 15:52 |
У меня не получилось свалить. Правда, мне пришлось переключиться на Использование Shared MFC DLL и, соответственно, Runtime DLL (я никогда не использую статические библиотеки, поэтому не ставлю их). И доставить не смогла - то ли дистрибутив не тот, то ли еще что... в общем, не получилось. Возможно разное поведение связано с этим. Но у тебя там есть нехороший код, который, теоретически, может иногда приводить к неприятностям: из CTopPanel::OnCbnSelchangeLanguages посылается синхронное сообщение, в результате которого панель может быть уничтожена. Т.е. в момент выхода из этой функции панели уже нет, а эта функция не последняя в стеке... а там есть и виртуальные функции... Посылай сообщение PostMessage, тогда уничтожение панели будет происходить уже после выхода из обработчика OnCommand. И еще, не очень здорово, что ты выделяешь память в одном месте (в вышеупомянутой функции), а освобождаешь - совсем в другом месте. Если бы проходило SendMessage, то вообще нет необходимости выделять память и что-то копировать: локальные переменные будут жить до выхода из SendMessage, так что их вполне можно использовать. Но, конечно, не при переходе к PostMessage. Я бы привязала язык не к строкам, а к стандартным LANGID, которые являются целыми и спокойно передаются в WPARAM или LPARAM. Т.е. в списке языков к строкам привязать соответствующие LANGID как ItemData, и дальше работать уже с ними. Через LANGID от системы можно получить массу полезной информации... Кроме того, это даст возможность заполнять список языков на разных языках. |
Автор: _hunter 3.7.2006, 16:08 |
блин. таки в SendMessage была проблема (почему-то в голове отложилось что это асинхронный вызов). спасибо. насчет LANGID подумаю... |