Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: две неожиданные грабли в MFC  (Прочитано 13484 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« : 24-05-2013 08:57 » 

это не вопросы, а наблюдения, но если кто прокомментирует - ещё лучше )



1) редактор форм не позволяет задать двум кнопкам одинаковый ID. Зато, если создавать кнопки вручную через Create, то это позволяется. Прекрасно получаются две кнопки с одним ID, от них приходит сообщение WM_COMMAND с одинаковым значением LOWORD(wParam)



2) временный указатель на заданный в редакторе контрол, как известно, можно получить через GetDlgItem(). И хендлы в полученных CWnd действительно не вечные - проверено однажды )
 Однако, полученный таким образом  CWnd* не удаётся кастить к дочернему классу!
Код:
	CSliderCtrl* pSl=dynamic_cast<CSliderCtrl*>(GetDlgItem(IDC_SLIDER1));
//pSl==0
Вот это уже не совсем понятно.

Если же через визард или вручную связать член-переменную класса, то есть при этом кроме объявления в классе самого объекта
Код:
CSliderCtrl m_Slider1;

добавляется вызов DDX_Control

Код:
void MYDIALOG::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SLIDER1, m_Slider1);
}

, то после этого каст начинает работать
« Последнее редактирование: 24-05-2013 08:59 от Алексей++ » Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 24-05-2013 09:24 » 

Почему-почему... Макросов понакручено, и никакой внятной объектной модели - вот почему. MFC должно помереть как архаизм 90-х.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 24-05-2013 09:30 » 

не принимается )
Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #3 : 24-05-2013 10:44 » 

1. Совсем непонятно зачем это нужно. Ведь можно вызывать одну и ту же ф-цию для кнопок с разными ID. Эт раз. Два, проблема заключается не в редакторе форм, а в сути организации ресурсов - каждый элемент должен быть однозначно идентифицирован в пределах области видимости (в контейнере). А редактор форм просто предостерегает тебя. Кстати, если хочется, то просто измени значение мнемонического обозначения ID в resource.h и ты сможешь скомпилировать, получая лишь предупреждение, а не ошибку. Создавая же объект с помощью ф-ции Create, ты заведомо отказываешься от использования шаблона в ресурсах (ты можешь вобще от них отказаться), поэтому там можешь указывать всё что угодно, хоть -1, всю ответственность за использование объекта в дальнейшем несёшь ты.

Кстати, эта "гарблЯ" никакого отношения непосредственно к MFC не имеет. Эт, так к слову. Ага

2. Нууу тут ты сам себе чего-йнто понапридумывал. Улыбаюсь Как работает dynamic_cast, забыл? Ага Кто тебе сказал, что GetDlgItem() вернёт тебе new CSliderCtrl? А не new CWnd, или даже скажем new CObject? Не забывай, что MFC - это только обёртка над WinAPI, и для подобных "объёктов" ей достаточно запомнить хэндл на окошко, всё остальное осуществляется через SendMessage, и ему по-барабану, какому окошку его посылать - слайдеру, кнопке или ещё кому.  Так что используй обычный кастинг и будет тебе щастье. Ага

Добавлено через 5 минут и 57 секунд:
оффтоп

Почему-почему... Макросов понакручено, и никакой внятной объектной модели - вот почему. MFC должно помереть как архаизм 90-х.

Опять Димка с его MFC-фобией. Улыбаюсь Пока же MFC цветёт и пахнет, ну а ежели кто в нём не совсем разобрался и/или не хочет этого делать, например, за ненадобностью, так это сплошь и рядом... Или есть достойная альтернатива? Ага Так надо озвучить, чтобы народу "не было мучительно больно за бесцельно прожитые годы" (с).

А если серьёзно, то когда появился .NET, MFC тоже пророчили быструю и мучительную смерть. А на сегодняшний день имеем MFC 11 и С++ 11, а вот что будет дальше после .NET 4.5? Туманно...

« Последнее редактирование: 24-05-2013 10:52 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 24-05-2013 10:52 » 

1 - это я по невнимательности сделал одинаковый ID . Так то я знаю, что они разные должны быть ) Это не MFC-шная фича, кстати, ИМХО, а АПИшная

2 - тут тоже, похоже, не MFC виноватая , а именно тот факт, что форма создана из ресурса. Наверное, именно HWND берётся, аттачится к CWnd - естественно, без виртуальной таблицы слайдера. Но я сразу об этом не подумал ))

"обычный" кастинг не катил, я передаю указатель именно на CWnd , а там объект сам разбирается, как оттуда данные доставать - из слайдера так, из едита - по другому
« Последнее редактирование: 24-05-2013 10:56 от Алексей++ » Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #5 : 24-05-2013 10:58 » 

1 я уже тоже приписал

2. Виноват ты, потому что без понятия (в данном случае) используешь dynamic_cast Ага Поиграйся с ним немного. А в данном случае используй CSliderCtrl* pSl=(CSliderCtrl*)(GetDlgItem(IDC_SLIDER1));

Никакие проверки приведения тебе не помогут.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 24-05-2013 11:05 » 

Джон, да я знаю, как он работает. Просто забыл, что из ресурса диалог составлен из фуфельных элементов Отлично

проверки очень даже помогут - в данном случае прекрасно помогли )
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 24-05-2013 11:31 » 

Цитата: Джон
Кто тебе сказал, что GetDlgItem() вернёт тебе new CSliderCtrl? А не new CWnd, или даже скажем new CObject? Не забывай, что MFC - это только обёртка над WinAPI, и для подобных "объёктов" ей достаточно запомнить хэндл на окошко, всё остальное осуществляется через SendMessage, и ему по-барабану, какому окошку его посылать - слайдеру, кнопке или ещё кому.
Вот это и есть "никакой внятной объектной модели". В основе архитектуры - handle'ы окон и прочих системных объектов. Но их можно либо прятать в обёртки, как в .NET делается, и тогда объект-обёртка живёт всё время существования handle, либо на каждый чих создавать и удалять вспомогательные объекты - тогда ни концов ни найдёшь, ни истории не отследишь, ни собственных данных к handle не привяжешь иначе, чем через map. Убогий подход - ничем не отличается от чистого WinAPI, рассчитанного на C, и выглядевшего "прорывом" в 80-е - в эпоху до массового распространения ООП.

Цитата: Джон
А на сегодняшний день имеем MFC 11 и С++ 11
Конечно, бороду эту тянуть придётся - столько понаписано. "Отягощённые злом".
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #8 : 24-05-2013 13:56 » 

Ок, открываем прения по данному вопросу. Улыбаюсь

Вот это и есть "никакой внятной объектной модели". В основе архитектуры - handle'ы окон и прочих системных объектов. Но их можно либо прятать в обёртки, как в .NET делается, и тогда объект-обёртка живёт всё время существования handle, либо на каждый чих создавать и удалять вспомогательные объекты - тогда ни концов ни найдёшь, ни истории не отследишь, ни собственных данных к handle не привяжешь иначе, чем через map.

Я не понял - в основе чьей архитектуры? Так вся винда на хэндлах только и работает? А как иначе? Ну да, MFC тоже их прячет, только не в платформе некой, а в объекте, время жизни, которого ограничено данной ситуацией. Но самое главное, что тема высосана из пальца. Подход через GetDlgItem - да, это я ещё учил в своём первом учебничке по MFC 4, тут согласен - архаизм, но кто в этом виноватЪ? (см. высказывание Трея Нэша в подписи) Если пользоваться ф-ми, предназначенными для создания кратковременно живущих объектов, то как можно ожидать от них "долголетия"? Тебе предлагается "меню" выбирай что хочешь, только не жалуйся на то, что сам выбрал. Создай объект-член класса и радуйся, как в C#. А если тебе разочек надо поменять текст в каком-нить текстовом поле, то можно коротенько получить к нему доступ и всё, в C# же тебе для подобной операции придётся ВСЮ ЖИЗНЬ таскать такой объект. И шо? Кто выиграл? Так при чём здесь MFC?

Цитата
Убогий подход - ничем не отличается от чистого WinAPI, рассчитанного на C, и выглядевшего "прорывом" в 80-е - в эпоху до массового распространения ООП.

Так а почему он должен отличаться? Это и есть WinAPI в чистейшем виде. Только немного удобней с т.з. программера. Да, не на 100% ООП, а они действительно нужны эти 100%? Для чего? Сама винда не ООП, а на гнилом фундаменте дворец не построишь, даже из золота. Так чего копья ломать? Ради честолюбия? Нет другого Бога под виндой кроме WinAPI, а уж как и чем в нём ковыряться, каждый выбирает для себя по степени своей испорченности. Во всяком случае до тех пор, пока не будет предложена достойная альтернатива.

Цитата
Конечно, бороду эту тянуть придётся - столько понаписано. "Отягощённые злом".

При чём здесь "понаписано"? Перестали бы писать, сам бы умер. Ан нет. Борода длинная, да крепкая и совсем не седая, и на сегодняшний момент только гуще и здоровей становится. Даром что в ногу с WinAPI шагает. Ага

Теперь про кастинг.

пусть дано:

Код: (C++)
  1. class A
  2. {
  3. protected:
  4.         virtual void Foo() {}
  5. };
  6.  
  7. class B : public A
  8. {
  9. protected:
  10.         virtual void Foo() {}
  11. };

тогда
Код: (C++)
  1. A *pA = new A();
  2. A* p = dynamic_cast<A*>(pA);
  3. p = dynamic_cast<B*>(pA);

что получится в строчке 3? Неужели NULL? Но, мы помним, это всё MFC! Гад такой, от него все беды. Не то что, например, C# уж он-то - ДА.

Код: (C#)
  1.     class A
  2.     {
  3.     };
  4.  
  5.     class B : A
  6.     {
  7.     };
  8. ...
  9.      A pA = new A();
  10.      A p = pA as A;
  11.      p = pA as B;

Уж он-то нам null никогда не выдаст, он же с хэндлами не работает, у него всё супер-пупер ООП!!!

Казалось бы, при чём здесь MFC? Ага


Добавлено через 1 час, 11 минут и 33 секунды:
"обычный" кастинг не катил, я передаю указатель именно на CWnd , а там объект сам разбирается, как оттуда данные доставать - из слайдера так, из едита - по другому

Вот это я не понял. Почему обычный "не катил"? До тех пор, пока не будет конфликта с особенностями того или иного контрола, или их стилями всё будет прекрасно работать. CWnd* даёт тебе возможность посылать сообщения этому объекту, "не далее, не более" (с)

Добавлено через 13 минут и 27 секунд:
Блииин..., а я-то думаю, что за deja vu такое... Новые грабли - хорошо забытые старые. Улыбаюсь Один в один. Перечитай с этого поста:

https://forum.shelek.ru/index.php/topic,24137.msg233590.html#msg233590
« Последнее редактирование: 24-05-2013 15:21 от Джон » Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 24-05-2013 15:51 » 

Цитата: Джон
Тебе предлагается "меню" выбирай что хочешь, только не жалуйся на то, что сам выбрал. Создай объект-член класса и радуйся, как в C#. А если тебе разочек надо поменять текст в каком-нить текстовом поле, то можно коротенько получить к нему доступ и всё, в C# же тебе для подобной операции придётся ВСЮ ЖИЗНЬ таскать такой объект. И шо? Кто выиграл? Так при чём здесь MFC?
Безосновательно. В том же C# тоже можно создать Control из handle - есть соответствующий метод у класса. Однако как-то это так сделано, что я вот об этом узнал только в прошлом году - именно на задаче связки с MFC. А до этого за 10 лет ни разу этим не пользовался, бо без надобности.

"Меню" это назвать сложно: система заточена под одну единственную идеологию. И это правильно. Потому как если в системе разброд и шатания, разработчики устраивают бардак, сами себе создают грабли, а потом на них наступают, что и демонстрирует эта тема. В этом системном свойстве - наличии определённой идеологии всех производных архитектур - заключена разница между понятиями framework и какими-то foundation classes.

Проблема и в том, что поверх MFC собственный framework для GUI построить, скажем так, сложно, поскольку все потроха торчат наружу, слегка задекорированные макросами. В хорошей объектной модели построить полную обёртку без "дырявых абстракций" - задача гораздо более простая. Потому всегда можно разделить "песочницы" разных производителей прикладного софта. И даже визарды и всякие графические редакторы и средства проектирования работают так, что потом сгенерированный код "обрабатывать напильником" не нужно. В случае MFC проще создать собственный язык с трансляцией в MFC-код, чем пытаться сделать адекватный редактор с анализатором непосредственно кода MFC (что, кстати, та же 1С и соорудила, к примеру).
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 24-05-2013 15:56 » 


Вот это я не понял. Почему обычный "не катил"? До тех пор, пока не будет конфликта с особенностями того или иного контрола, или их стилями всё будет прекрасно работать.

Джон, я это помню. Дело не в этом же! Ну вот как-то нету у того же едита range )))  А у слайдера - текста. Но мне лень писать отправку сообщений и анализ, почему они не сработали. Мне проще было добавить мембер в диалог и передать указатель в виде CWnd. Кастом определяю класс источника - и вперёд
Записан

Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #11 : 24-05-2013 15:59 » 

Dimka, когда дело касается GUI, я всё чаще обращаюсь к Qt , там очень всё хорошо на этот счёт сделано )  Исследовал окно программы - хендл имеет главное окно/диалог, а все накиданные на него виджеты - тупо нарисованные

То есть, там всё написано с нуля, считай. Взяли только самую необходимую основу - подложку HWND

Добавлено через 6 минут и 19 секунд:
скрин прицепил - главное окно программы и окно настроек. У них нет дочерних окон вообще ))

(click to show)

* Безымянный.png (68.91 Кб - загружено 1535 раз.)
« Последнее редактирование: 24-05-2013 16:06 от Алексей1153 » Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 24-05-2013 19:27 » 

Цитата: Алексей++
я всё чаще обращаюсь к Qt , там очень всё хорошо на этот счёт сделано
Неудивительно.

Цитата: Алексей++
хендл имеет главное окно/диалог, а все накиданные на него виджеты - тупо нарисованные
Что позволяет проще кастомизировать всякие рюшечки и строить более гибкие и разнообразные варианты GUI. Кстати WPF.NET в эту сторону сдвинут.

А не как у некоторых: любая козявка - окно, и то квадратное Улыбаюсь Опять же, наследие C-программистов, проигнорировавших уже тогда существовавшие наработки GUI в Smalltalk, поскольку развивать архитектуру было некогда - надо было Apple догонять и перегонять.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #13 : 25-05-2013 16:36 » 

Dimka, при всём при этом винда не перестаёт быть построена на том корявом WinAPI Улыбаюсь Пока её не возьмёт и не перепишут с нуля по свежему (если это вообще возможно в плане поддержки всего старого), хотя, мне кажется, при наличии таких библиотек, как Qt, в этом смысла нет
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines