[Scummvm-git-logs] scummvm branch-3-0 -> 7a94d82be14991f56249f95c5e670983efe20df8

dreammaster noreply at scummvm.org
Fri Dec 26 20:34:26 UTC 2025


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
7a94d82be1 BAGEL: MFC: Fix Enter/Escape triggering default dialog actions


Commit: 7a94d82be14991f56249f95c5e670983efe20df8
    https://github.com/scummvm/scummvm/commit/7a94d82be14991f56249f95c5e670983efe20df8
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2025-12-27T07:34:16+11:00

Commit Message:
BAGEL: MFC: Fix Enter/Escape triggering default dialog actions

Changed paths:
    engines/bagel/mfc/afxwin.h
    engines/bagel/mfc/dialog.cpp
    engines/bagel/mfc/edit.cpp
    engines/bagel/mfc/libs/event_loop.cpp
    engines/bagel/mfc/libs/event_loop.h
    engines/bagel/mfc/win_app.cpp
    engines/bagel/mfc/winnt.h


diff --git a/engines/bagel/mfc/afxwin.h b/engines/bagel/mfc/afxwin.h
index ab08bd289fb..242c2fee9d7 100644
--- a/engines/bagel/mfc/afxwin.h
+++ b/engines/bagel/mfc/afxwin.h
@@ -50,6 +50,7 @@ namespace MFC {
 constexpr uint32 DEFAULT_MODAL_RESULT = MKTAG('S', 'C', 'V', 'M');
 
 class CBitmap;
+class CButton;
 class CCmdTarget;
 class CCmdUI;
 class CDC;
@@ -1430,6 +1431,10 @@ public:
 	}
 	void DestroyWindow();
 	void Invalidate(bool bErase = true);
+
+	// Message processing for modeless dialog-like windows
+	virtual bool IsDialogMessage(LPMSG lpMsg) { return false; }
+
 	int GetWindowText(CString &rString) const;
 	int GetWindowText(char *lpszStringBuf, int nMaxCount) const;
 	bool SetWindowText(const char *lpszString);
@@ -1610,7 +1615,11 @@ private:
 		HINSTANCE hInst);
 	bool CreateDlgIndirect(LPCDLGTEMPLATE lpDialogTemplate,
 		CWnd *pParentWnd, HINSTANCE hInst);
-	CWnd *GetDefaultPushButton() const;
+	CButton *GetDefaultPushButton() const;
+
+	bool handleEnterKey(LPMSG lpMsg);
+	bool handleEscapeKey(LPMSG lpMsg);
+	void sendButtonClicked(CButton *btn);
 
 protected:
 	DECLARE_MESSAGE_MAP()
@@ -1640,7 +1649,7 @@ public:
 	virtual bool OnInitDialog() {
 		return true;
 	}
-	bool PreTranslateMessage(MSG *pMsg) override;
+	bool IsDialogMessage(LPMSG lpMsg) override;
 
 	uint32 GetDefID() const;
 	void SetDefID(unsigned int nID);
@@ -1750,6 +1759,7 @@ public:
 	afx_msg void OnSetFocus(CWnd *pOldWnd);
 	afx_msg void OnKillFocus(CWnd *pNewWnd);
 	afx_msg void OnTimer(uintptr nTimerId);
+	afx_msg unsigned int OnGetDlgCode();
 };
 
 class CScrollBar : public CWnd {
diff --git a/engines/bagel/mfc/dialog.cpp b/engines/bagel/mfc/dialog.cpp
index 131c9f2c938..8969309c5d9 100644
--- a/engines/bagel/mfc/dialog.cpp
+++ b/engines/bagel/mfc/dialog.cpp
@@ -28,13 +28,13 @@ namespace MFC {
 
 IMPLEMENT_DYNAMIC(CDialog, CWnd)
 BEGIN_MESSAGE_MAP(CDialog, CWnd)
-ON_COMMAND(IDOK, CDialog::OnOK)
-ON_COMMAND(IDCANCEL, CDialog::OnCancel)
-ON_MESSAGE(WM_INITDIALOG, CDialog::HandleInitDialog)
-ON_MESSAGE(WM_SETFONT, CDialog::HandleSetFont)
-ON_WM_SYSCHAR()
-ON_WM_CLOSE()
-ON_WM_ACTIVATE()
+	ON_COMMAND(IDOK, CDialog::OnOK)
+	ON_COMMAND(IDCANCEL, CDialog::OnCancel)
+	ON_MESSAGE(WM_INITDIALOG, CDialog::HandleInitDialog)
+	ON_MESSAGE(WM_SETFONT, CDialog::HandleSetFont)
+	ON_WM_SYSCHAR()
+	ON_WM_CLOSE()
+	ON_WM_ACTIVATE()
 END_MESSAGE_MAP()
 
 CDialog::CDialog(const char *lpszTemplateName, CWnd *pParentWnd) {
@@ -52,7 +52,7 @@ CDialog::CDialog(unsigned int nIDTemplate, CWnd *pParentWnd) {
 }
 
 bool CDialog::Create(const char *lpszTemplateName,
-        CWnd *pParentWnd) {
+	CWnd *pParentWnd) {
 	m_lpszTemplateName = lpszTemplateName;  // used for help
 	SetParent(pParentWnd);
 
@@ -109,7 +109,7 @@ int CDialog::DoModal() {
 		m_pParentWnd = AfxGetApp()->m_pMainWnd;
 
 	if (CreateDlgIndirect(lpDialogTemplate,
-			this /*m_pParentWnd*/, hInst)) {
+		this /*m_pParentWnd*/, hInst)) {
 		AfxGetApp()->doModal(this);
 	}
 
@@ -221,42 +221,16 @@ LRESULT CDialog::HandleSetFont(WPARAM wParam, LPARAM) {
 	return 0;
 }
 
-bool CDialog::PreTranslateMessage(MSG *pMsg) {
-	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) {
-		CWnd *pFocus = GetFocus();
-
-		// Special case: prevent multi-line edit controls from handling Enter
-		if (pFocus && pFocus->IsKindOf(RUNTIME_CLASS(CEdit))) {
-			uint32 style = pFocus->GetStyle();
-			if ((style & ES_MULTILINE) == 0) {
-				// Not a multi-line edit box - simulate default pushbutton
-				CWnd *pDefault = GetDefaultPushButton();
-				if (pDefault) {
-					pDefault->SendMessage(WM_COMMAND, MAKEWPARAM(IDOK, BN_CLICKED), (LPARAM)pDefault->m_hWnd);
-
-				} else {
-					// No button - just call OnOK directly
-					OnOK();
-				}
+CButton *CDialog::GetDefaultPushButton() const {
+	for (auto &child : _children) {
+		CButton *pChild = dynamic_cast<CButton *>(child._value);
 
-				return true;
+		if (pChild) {
+			uint32 style = pChild->GetStyle();
+			if ((style & BS_DEFPUSHBUTTON) && pChild->GetDlgCtrlID() == IDOK) {
+				return pChild;
 			}
 		}
-	} else if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) {
-		OnCancel();
-		return true;
-	}
-
-	return CWnd::PreTranslateMessage(pMsg);
-}
-
-CWnd *CDialog::GetDefaultPushButton() const {
-	for (auto &child : _children) {
-		CWnd *pChild = child._value;
-		uint32 style = pChild->GetStyle();
-		if ((style & BS_DEFPUSHBUTTON) && pChild->GetDlgCtrlID() == IDOK) {
-			return pChild;
-		}
 	}
 
 	return nullptr;
@@ -267,7 +241,7 @@ void CDialog::DDX_Control(CDataExchange *pDX, int nIDC, CWnd &rControl) {
 }
 
 void CDialog::DDX_Radio(CDataExchange *pDX,
-                        int nIDCButton1, int &value) {
+	int nIDCButton1, int &value) {
 	error("TODO: CDialog::DDX_Radio");
 }
 
@@ -297,12 +271,12 @@ void CDialog::DDX_Text(CDataExchange *pDX, int nIDC, double &value) {
 }
 
 void CDialog::DDX_Check(CDataExchange *pDX,
-                        int nIDC, bool value) {
+	int nIDC, bool value) {
 	error("CDialog::DDX_Check");
 }
 
 void CDialog::DDV_MinMaxInt(CDataExchange *pDX,
-                            int value, int nMin, int nMax) {
+	int value, int nMin, int nMax) {
 	error("TODO: CDialog::DDV_MinMaxInt");
 }
 
@@ -331,12 +305,12 @@ void CDialog::OnCancel() {
 }
 
 bool CDialog::CreateIndirect(LPCDLGTEMPLATE lpDialogTemplate,
-		CWnd *pParentWnd, void *lpDialogInit, HINSTANCE hInst) {
+	CWnd *pParentWnd, void *lpDialogInit, HINSTANCE hInst) {
 	error("TODO: CDialog::CreateIndirect");
 }
 
 bool CDialog::CreateIndirect(HGLOBAL hDialogTemplate,
-		CWnd *pParentWnd, HINSTANCE hInst) {
+	CWnd *pParentWnd, HINSTANCE hInst) {
 	error("TODO: CDialog::CreateIndirect");
 }
 
@@ -374,5 +348,68 @@ void CDialog::OnActivate(unsigned int nState, CWnd *pWndOther, bool bMinimized)
 	CWnd::OnActivate(nState, pWndOther, bMinimized);
 }
 
+bool CDialog::IsDialogMessage(LPMSG lpMsg) {
+	if (lpMsg->message != WM_KEYDOWN)
+		return false;
+
+	switch (lpMsg->wParam) {
+	case VK_RETURN:
+		return handleEnterKey(lpMsg);
+
+	case VK_ESCAPE:
+		return handleEscapeKey(lpMsg);
+
+	default:
+		break;
+	}
+
+	return false;
+}
+
+bool CDialog::handleEnterKey(LPMSG lpMsg) {
+	HWND hFocus = GetFocus();
+	if (!hFocus)
+		return false;
+
+	// Ask control what it wants
+	LRESULT dlgCode = MFC::SendMessage(hFocus, WM_GETDLGCODE,
+		lpMsg->wParam, (LPARAM)lpMsg);
+
+	// If control wants Enter, do nothing
+	if (dlgCode & DLGC_WANTMESSAGE)
+		return false;
+
+	// Multiline edits implicitly want Enter
+	if (dlgCode & DLGC_HASSETSEL)
+		return false;
+
+	// Find default push button
+	CButton *pDefault = GetDefaultPushButton();
+	if (!pDefault)
+		return false;
+
+	if (!pDefault->IsWindowEnabled())
+		// consume Enter, do nothing
+		return true;
+
+	// Simulate button click
+	sendButtonClicked(pDefault);
+	return true;
+}
+
+bool CDialog::handleEscapeKey(LPMSG lpMsg) {
+	CButton *pCancel = dynamic_cast<CButton *>(GetDlgItem(IDCANCEL));
+	if (!pCancel || !pCancel->IsWindowEnabled())
+		return true;
+
+	sendButtonClicked(pCancel);
+	return true;
+}
+
+void CDialog::sendButtonClicked(CButton *btn) {
+	int id = btn->GetDlgCtrlID();
+	SendMessage(WM_COMMAND, MAKEWPARAM(id, BN_CLICKED), (LPARAM)btn->m_hWnd);
+}
+
 } // namespace MFC
 } // namespace Bagel
diff --git a/engines/bagel/mfc/edit.cpp b/engines/bagel/mfc/edit.cpp
index e65db37faf8..1c124849785 100644
--- a/engines/bagel/mfc/edit.cpp
+++ b/engines/bagel/mfc/edit.cpp
@@ -35,6 +35,7 @@ ON_WM_CHAR()
 ON_WM_SETFOCUS()
 ON_WM_KILLFOCUS()
 ON_WM_TIMER()
+ON_WM_GETDLGCODE()
 END_MESSAGE_MAP()
 
 bool CEdit::Create(uint32 dwStyle, const RECT &rect, CWnd *pParentWnd, unsigned int nID) {
@@ -141,5 +142,14 @@ void CEdit::OnTimer(uintptr nTimerId) {
 	Invalidate();
 }
 
+unsigned int CEdit::OnGetDlgCode() {
+	uint style = GetStyle();
+
+	if (style & ES_MULTILINE)
+		return DLGC_WANTMESSAGE | DLGC_HASSETSEL;
+
+	return 0;
+}
+
 } // namespace MFC
 } // namespace Bagel
diff --git a/engines/bagel/mfc/libs/event_loop.cpp b/engines/bagel/mfc/libs/event_loop.cpp
index a8965fa6e63..088950f4e04 100644
--- a/engines/bagel/mfc/libs/event_loop.cpp
+++ b/engines/bagel/mfc/libs/event_loop.cpp
@@ -31,7 +31,7 @@ namespace Libs {
 
 #define FRAME_RATE 50
 
-void EventLoop::runEventLoop() {
+void EventLoop::runEventLoop(bool isModalDialog) {
 	MSG msg;
 
 	while (!shouldQuit() && !_activeWindows.empty()) {
@@ -43,7 +43,8 @@ void EventLoop::runEventLoop() {
 			break;
 
 		CWnd *mainWnd = GetActiveWindow();
-		if (msg.message != WM_NULL && mainWnd && !mainWnd->PreTranslateMessage(&msg)) {
+		if (msg.message != WM_NULL && mainWnd && !mainWnd->PreTranslateMessage(&msg) &&
+				(!isModalDialog || !mainWnd->IsDialogMessage(&msg))) {
 			TranslateMessage(&msg);
 			DispatchMessage(&msg);
 		}
@@ -90,7 +91,7 @@ void EventLoop::PopActiveWindow() {
 
 void EventLoop::doModal(CWnd *wnd) {
 	SetActiveWindow(wnd);
-	runEventLoop();
+	runEventLoop(true);
 	if (GetActiveWindow() == wnd)
 		wnd->DestroyWindow();
 }
diff --git a/engines/bagel/mfc/libs/event_loop.h b/engines/bagel/mfc/libs/event_loop.h
index a58f1fb700b..68a154c1965 100644
--- a/engines/bagel/mfc/libs/event_loop.h
+++ b/engines/bagel/mfc/libs/event_loop.h
@@ -167,7 +167,7 @@ public:
 	EventLoop() {}
 	virtual ~EventLoop() {}
 
-	void runEventLoop();
+	void runEventLoop(bool isModalDialog);
 	void SetActiveWindow(CWnd *wnd);
 	void PopActiveWindow();
 	CWnd *GetActiveWindow() const {
diff --git a/engines/bagel/mfc/win_app.cpp b/engines/bagel/mfc/win_app.cpp
index 6d7e82c6c37..6a2a51c2525 100644
--- a/engines/bagel/mfc/win_app.cpp
+++ b/engines/bagel/mfc/win_app.cpp
@@ -168,7 +168,7 @@ int CWinApp::Run() {
 		SetActiveWindow(m_pMainWnd);
 	}
 
-	runEventLoop();
+	runEventLoop(false);
 
 	SaveAllModified();
 	ExitInstance();
diff --git a/engines/bagel/mfc/winnt.h b/engines/bagel/mfc/winnt.h
index 5d18320be6f..2fd045aa471 100644
--- a/engines/bagel/mfc/winnt.h
+++ b/engines/bagel/mfc/winnt.h
@@ -652,6 +652,23 @@ typedef struct _GUID {
 #define AFX_IDW_PANE_SAVE               0xEA21  // to shift AFX_IDW_PANE_FIRST
 #define AFX_WS_DEFAULT_VIEW		(WS_CHILD | WS_VISIBLE)
 
+
+/*
+ * Dialog Codes
+ */
+#define DLGC_WANTARROWS     0x0001      /* Control wants arrow keys         */
+#define DLGC_WANTTAB        0x0002      /* Control wants tab keys           */
+#define DLGC_WANTALLKEYS    0x0004      /* Control wants all keys           */
+#define DLGC_WANTMESSAGE    0x0004      /* Pass message to control          */
+#define DLGC_HASSETSEL      0x0008      /* Understands EM_SETSEL message    */
+#define DLGC_DEFPUSHBUTTON  0x0010      /* Default pushbutton               */
+#define DLGC_UNDEFPUSHBUTTON 0x0020     /* Non-default pushbutton           */
+#define DLGC_RADIOBUTTON    0x0040      /* Radio button                     */
+#define DLGC_WANTCHARS      0x0080      /* Want WM_CHAR messages            */
+#define DLGC_STATIC         0x0100      /* Static item: don't include       */
+#define DLGC_BUTTON         0x2000      /* Button item: can be checked      */
+
+
 typedef struct tagTEXTMETRICA {
 	long        tmHeight = 0;
 	long        tmAscent = 0;




More information about the Scummvm-git-logs mailing list