Мигрированное приложение MFC из VC6 в VS2010, теперь OnInitDialog () не вызывается для подкласса CPropertyPage - PullRequest
3 голосов
/ 30 августа 2011

Мне было поручено перенести пользовательский интерфейс нашего продукта на VS2010.Это приложение MFC, изначально написанное на VC6.Я выполнил следующие шаги:

  • Преобразовал VDS-файл .dsp, используя VS2010
  • Исправлены ошибки компиляции из-за более строгого компилятора VS2010
  • Удалены все ссылки проекта на VC6MFC библиотеки и каталоги

Моя проблема в том, что для объекта диалога (на самом деле это объект CPropertyPage) OnInitDialog () не вызывается раньше других методов.Это вызывает исключение, так как OnInitDialog () должен настроить переменные-члены.

Класс диалога (CPAGEViewDefRecordFields) разделен на подклассы из нашего собственного CValidatedPropertyPage, который, в свою очередь, является производным от класса MFC CPropertyPage.Виртуальный метод OnInitDialog () присутствует во всех подклассах.

В версии VS2010, когда DoModal () вызывается на содержащем листе свойств, метод OnInitDialog () класса CPAGEViewDefRecordFields не вызывается.В версии VC6 он вызывается и все работает нормально.

В VC6 я вижу, что сообщение WM_INITDIALOG отправляется и обрабатывается в AfxDlgProc (), который, в свою очередь, затем вызывает OnInitDialog ()объект диалога.

В версии VS2010 первое обрабатываемое сообщение - WM_NOTIFY, а не WM_INITDIALOG.

К сожалению, у меня нет опыта работы с MFC.Что я предполагаю, что что-то изменилось в поведении MFC между версией VC6 и версией VS2010.Однако я не смог найти в сети ничего похожего на это.

Есть еще один шаг миграции, который я пропустил?Должен ли я что-то делать с ресурсами в проекте при выполнении миграции?

Я проверил, что ресурс привязан к правильному файлу cpp, так как я могу дважды щелкнуть страницу свойств и IDE.приводит меня к правильному файлу для класса CPAGEViewDefRecordFields.

Если у кого-либо из вас есть какие-либо идеи, я был бы очень признателен.

Спасибо!Крис.

class CPAGEViewDefRecordFields : public CValidatedPropertyPage
{
public:

   // Construction

   CPAGEViewDefRecordFields(CWnd*         pParent,
                           CXpViewProp*  pViewProp,
                           CFont*        pFont      = NULL,
                           UINT          nIDCaption = 0,
                           BOOL          bSumOpRequired = TRUE,
                           BOOL          bMinMaxRequired = TRUE,
                           BOOL          bAllRecords = TRUE,
                           BOOL          bShowInitSel = TRUE,
                           XLong         lLimits = 0,
                           BOOL          bSortSelTree = TRUE,
                           CXpThreshBaseLogProp* pThreshLogProp = NULL);

  ~CPAGEViewDefRecordFields();

  // Dialog Data
  //{{AFX_DATA(CPAGEViewDefRecordFields)
  enum { IDD = IDD_VIEW_DEF_RECORD_FIELDS };
  //}}AFX_DATA

  // Overrides
  // ClassWizard generate virtual function overrides
  //{{AFX_VIRTUAL(CPAGEViewDefRecordFields)
  virtual BOOL OnInitDialog();
  //}}AFX_VIRTUAL

 virtual BOOL OnSetActive();
 virtual BOOL OnKillActive();
 virtual void OnOK();

protected:

  ... 

  // Generated message map functions
  //{{AFX_MSG(CPAGEViewDefRecordFields)
  afx_msg void OnPbRemove();
  afx_msg void OnPbAdd();
  afx_msg void OnDblclkAvailableFields(NMHDR* pNMHDR, LRESULT* pResult);
  afx_msg void OnDblclkSelectedFields(NMHDR* pNMHDR, LRESULT* pResult);
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()

private:
  ...

ОБНОВЛЕНИЕ:

После некоторой отладки я вижу, в чем проблема.Однако, не будучи программистом MFC, я этого не понимаю.

Я вижу, что OnInitDialog () вызывается для листа свойств и что WM_INITDIALOG затем отправляется из листа свойств в свойство.страницы.однако в какой-то момент во внутреннем устройстве Windows отправляется сообщение WM_NOTIFY, так что это первое полученное сообщение, а не ожидаемое WM_INITDIALOG

Я выделил точки на трассировке стека, прикрепленные -Кто-нибудь может объяснить, почему это происходит?Является ли это нормальным поведением - должен ли я учесть это в будущем?

Я действительно нашел обходной путь, и у него должен быть инициализированный флаг, так что никакой код не выполняется, пока OnInitDialog () не был вызван,Это не лучшее решение, и я боюсь, что это скорее взлом, поэтому я все равно буду признателен за понимание этих сообщений.(По профессии я не программист MFC!)

спасибо!

stack trace showing WM messages

Ответы [ 2 ]

0 голосов
/ 20 июля 2012

Думаю, мне лучше на это ответить.

Ответ пришел из комментария пользователя SO:

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

«Обходной путь» - единственный способ гарантировать, что диалог готов.

0 голосов
/ 26 октября 2011

OnInitDialog вызывается после создания всех элементов управления диалогового окна и непосредственно перед отображением диалогового окна.

...