Мне не хватает понимания сообщений в Windows приложениях.
У меня есть обработчик кнопок:
void CChristianLifeMinistryEditorDlg::OnFilePublicTalk()
{
CWeekendMeetingDlg dlgPublicTalk(this);
if (m_pEntry != nullptr)
{
dlgPublicTalk.SetPublicTalkInfo(m_pEntry->GetPublicTalkInfo());
dlgPublicTalk.SetCircuitVisitMode(m_iIncludeMode == kIncludeServiceTalk); // AJT v17.0.7
// AJT v20.0.1
dlgPublicTalk.SetSongInfo(
CChristianLifeMinistryUtils::UseSingOutJoyfullyToJehovah(m_datFirstMonday), m_eForeignLang);
auto iResult = dlgPublicTalk.DoModal();
if (iResult == IDOK || iResult == to_underlying(CWeekendMeetingDlg::EndResult::PreviousDate) ||
iResult == to_underlying(CWeekendMeetingDlg::EndResult::NextDate))
{
m_pEntry->SetPublicTalkInfo(dlgPublicTalk.GetPublicTalkInfo());
SetModified(true);
UpdatePreview(m_iDateIndex);
m_pHtmlPreview->Refresh2(REFRESH_COMPLETELY); // Ensure it has refreshed
// Padlock
// Reminder
// Disable controls
if (iResult == to_underlying(CWeekendMeetingDlg::EndResult::PreviousDate))
{
AfxMessageBox(_T("Move to previous week."));
PostMessage(WM_COMMAND, ID_FILE_PUBLIC_TALK, 0);
// It can't process this message until the current instance one has finished
}
else if (iResult == to_underlying(CWeekendMeetingDlg::EndResult::NextDate))
{
AfxMessageBox(_T("Move to next week."));
PostMessage(WM_COMMAND, ID_FILE_PUBLIC_TALK, 0);
// It can't process this message until the current instance one has finished
}
}
}
}
Я удалил код (заменен двумя AfxMessageBox
calls), но в принципе я хочу перезапустить тот же обработчик событий, как если бы пользователь щелкнул его в меню «Файл». Можно ли использовать PostMessage
, когда текущий экземпляр сообщения еще не завершен?
Я еще не пробовал предоставленный ответ, но я столкнулся с проблемой при вводе двух PostMessage
звонки:
void CChristianLifeMinistryEditorDlg::OnFilePublicTalk()
{
CWeekendMeetingDlg dlgPublicTalk(this);
if (m_pEntry != nullptr)
{
dlgPublicTalk.SetPublicTalkInfo(m_pEntry->GetPublicTalkInfo());
dlgPublicTalk.SetCircuitVisitMode(m_iIncludeMode == kIncludeServiceTalk); // AJT v17.0.7
// AJT v20.0.1
dlgPublicTalk.SetSongInfo(
CChristianLifeMinistryUtils::UseSingOutJoyfullyToJehovah(m_datFirstMonday), m_eForeignLang);
// AJT v20.1.8
dlgPublicTalk.SetPreviousNextDateButtonStates(m_btnMovePrevious.IsWindowEnabled(),
m_btnMoveNext.IsWindowEnabled());
auto iResult = dlgPublicTalk.DoModal();
if (iResult == IDOK || iResult == to_underlying(CWeekendMeetingDlg::EndResult::PreviousDate) ||
iResult == to_underlying(CWeekendMeetingDlg::EndResult::NextDate))
{
m_pEntry->SetPublicTalkInfo(dlgPublicTalk.GetPublicTalkInfo());
SetModified(true);
UpdatePreview(m_iDateIndex);
m_pHtmlPreview->Refresh2(REFRESH_COMPLETELY); // Ensure it has refreshed
if (iResult == to_underlying(CWeekendMeetingDlg::EndResult::PreviousDate))
{
PostMessage(WM_COMMAND, MAKEWPARAM(IDC_MFCBUTTON_PREVIOUS_DATE, BN_CLICKED),
(LPARAM)m_btnMovePrevious.GetSafeHwnd());
PostMessage(WM_COMMAND, ID_FILE_PUBLIC_TALK, 0);
}
else if (iResult == to_underlying(CWeekendMeetingDlg::EndResult::NextDate))
{
PostMessage(WM_COMMAND, MAKEWPARAM(IDC_MFCBUTTON_NEXT_DATE, BN_CLICKED),
(LPARAM)m_btnMoveNext.GetSafeHwnd());
PostMessage(WM_COMMAND, ID_FILE_PUBLIC_TALK, 0);
}
}
}
}
После выполнения действий и повторного отображения окна, я нажимаю «Отмена» и получаю:
Если я изменю его и напрямую вызову обработчики кнопок, например:
void CChristianLifeMinistryEditorDlg::OnFilePublicTalk()
{
CWeekendMeetingDlg dlgPublicTalk(this);
if (m_pEntry != nullptr)
{
dlgPublicTalk.SetPublicTalkInfo(m_pEntry->GetPublicTalkInfo());
dlgPublicTalk.SetCircuitVisitMode(m_iIncludeMode == kIncludeServiceTalk); // AJT v17.0.7
// AJT v20.0.1
dlgPublicTalk.SetSongInfo(
CChristianLifeMinistryUtils::UseSingOutJoyfullyToJehovah(m_datFirstMonday), m_eForeignLang);
// AJT v20.1.8
dlgPublicTalk.SetPreviousNextDateButtonStates(m_btnMovePrevious.IsWindowEnabled(),
m_btnMoveNext.IsWindowEnabled());
auto iResult = dlgPublicTalk.DoModal();
if (iResult == IDOK || iResult == to_underlying(CWeekendMeetingDlg::EndResult::PreviousDate) ||
iResult == to_underlying(CWeekendMeetingDlg::EndResult::NextDate))
{
m_pEntry->SetPublicTalkInfo(dlgPublicTalk.GetPublicTalkInfo());
SetModified(true);
UpdatePreview(m_iDateIndex);
m_pHtmlPreview->Refresh2(REFRESH_COMPLETELY); // Ensure it has refreshed
if (iResult == to_underlying(CWeekendMeetingDlg::EndResult::PreviousDate))
{
//PostMessage(WM_COMMAND, MAKEWPARAM(IDC_MFCBUTTON_PREVIOUS_DATE, BN_CLICKED),
// (LPARAM)m_btnMovePrevious.GetSafeHwnd());
OnBnClickedMfcbuttonPreviousDate();
PostMessage(WM_COMMAND, ID_FILE_PUBLIC_TALK, 0);
}
else if (iResult == to_underlying(CWeekendMeetingDlg::EndResult::NextDate))
{
//PostMessage(WM_COMMAND, MAKEWPARAM(IDC_MFCBUTTON_NEXT_DATE, BN_CLICKED),
// (LPARAM)m_btnMoveNext.GetSafeHwnd());
OnBnClickedMfcbuttonNextDate();
PostMessage(WM_COMMAND, ID_FILE_PUBLIC_TALK, 0);
}
}
}
}
Последний подход работает. Я должен указать, что эти два обработчика кнопок обновляют файл HTML и перерисовывают его в элементе управления веб-браузера (который фактически находится в родительском диалоговом окне).
Допустимо ли напрямую вызывать такие обработчики кнопок, как этот ?
Используя предоставленный ответ (спасибо), это работает хорошо:
void CChristianLifeMinistryEditorDlg::OnFilePublicTalk()
{
delay_post_msg dpm{ this };
CWeekendMeetingDlg dlgPublicTalk(this);
if (m_pEntry != nullptr)
{
dlgPublicTalk.SetPublicTalkInfo(m_pEntry->GetPublicTalkInfo());
dlgPublicTalk.SetCircuitVisitMode(m_iIncludeMode == kIncludeServiceTalk); // AJT v17.0.7
// AJT v20.0.1
dlgPublicTalk.SetSongInfo(
CChristianLifeMinistryUtils::UseSingOutJoyfullyToJehovah(m_datFirstMonday), m_eForeignLang);
// AJT v20.1.8
dlgPublicTalk.SetPreviousNextDateButtonStates(m_btnMovePrevious.IsWindowEnabled(),
m_btnMoveNext.IsWindowEnabled());
auto iResult = dlgPublicTalk.DoModal();
if (iResult == IDOK || iResult == to_underlying(CWeekendMeetingDlg::EndResult::PreviousDate) ||
iResult == to_underlying(CWeekendMeetingDlg::EndResult::NextDate))
{
m_pEntry->SetPublicTalkInfo(dlgPublicTalk.GetPublicTalkInfo());
SetModified(true);
UpdatePreview(m_iDateIndex);
m_pHtmlPreview->Refresh2(REFRESH_COMPLETELY); // Ensure it has refreshed
if (iResult == to_underlying(CWeekendMeetingDlg::EndResult::PreviousDate))
{
//PostMessage(WM_COMMAND, MAKEWPARAM(IDC_MFCBUTTON_PREVIOUS_DATE, BN_CLICKED),
// (LPARAM)m_btnMovePrevious.GetSafeHwnd());
OnBnClickedMfcbuttonPreviousDate();
//PostMessage(WM_COMMAND, ID_FILE_PUBLIC_TALK, 0);
dpm.set_active();
}
else if (iResult == to_underlying(CWeekendMeetingDlg::EndResult::NextDate))
{
//PostMessage(WM_COMMAND, MAKEWPARAM(IDC_MFCBUTTON_NEXT_DATE, BN_CLICKED),
// (LPARAM)m_btnMoveNext.GetSafeHwnd());
OnBnClickedMfcbuttonNextDate();
//PostMessage(WM_COMMAND, ID_FILE_PUBLIC_TALK, 0);
dpm.set_active();
}
}
}
}
Мне пришлось использовать два обработчика кнопок OnBnClickedMfcbuttonPreviousDate
/ OnBnClickedMfcbuttonNextDate
напрямую, без использования PostMessage
для имитации нажатия кнопок. Полагаю, это приемлемо?