首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

MFC 編輯框回車輸入實現:PreTranslateMessage 與 Win32 SDK 兩種架構的正確姿勢

     編輯:程式設計綜合問答

關鍵發現:你的代碼是純 Win32 SDK,不是 MFC

你貼的 `WinMain` + `DialogBoxParam` + `CALLBACK _ProcDlgMain` 是**標準 Win32 SDK 對話框程序**,**完全沒有使用 MFC**(無 `CWinApp`、`CDialog`、消息映射宏)。因此,**不需要、也不能**重寫 `PreTranslateMessage`——那是 `CWnd` 的虛函數,屬於 MFC 架構。

方案一:Win32 SDK 原生處理(推薦,符合你現有代碼)

在對話框進程 `_ProcDlgMain` 中直接處理 `WM_KEYDOWN`:

LRESULT CALLBACK _ProcDlgMain(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_CLOSE:
            EndDialog(hwnd, NULL);
            break;
        case WM_COMMAND:
            // ... 你原有的按鈕處理邏輯 ...
            break;
        case WM_KEYDOWN:
            if (wParam == VK_RETURN) {
                // 模擬 Tab 鍵切換焦點,觸發下一個控件的 EN_KILLFOCUS 等驗證邏輯
                keybd_event(VK_TAB, 0, 0, 0);
                keybd_event(VK_TAB, 0, KEYEVENTF_KEYUP, 0);
                return TRUE; // 消息已處理
            }
            break;
    }
    return FALSE;
}

進階:獲取編輯框內容並清空

case WM_KEYDOWN:
    if (wParam == VK_RETURN) {
        HWND hEdit = GetDlgItem(hwnd, IDC_EDIT_SCORE); // 資源定義的編輯框 ID
        if (GetFocus() == hEdit) { // 確保焦點在編輯框
            char buf[32];
            GetWindowTextA(hEdit, buf, sizeof(buf));
            int score = atoi(buf);
            // 這裡處理 score:存入數組、統計、顯示等
            // ...
            SetWindowTextA(hEdit, ""); // 清空編輯框
            return TRUE;
        }
    }
    break;

方案二:改用 MFC 架構(若項目允許重構)

1. 創建 MFC 對話框類

class CGradeStatisticDlg : public CDialogEx {
    DECLARE_DYNAMIC(CGradeStatisticDlg)
public:
    CGradeStatisticDlg(CWnd* pParent = nullptr);
    enum { IDD = IDD_DIALOG_GRADE }; // 資源編輯器設計的對話框模板
    
    CString m_strScore; // DDX 綁定編輯框
    int m_scores[8];
    int m_count = 0;

protected:
    virtual void DoDataExchange(CDataExchange* pDX) override {
        CDialogEx::DoDataExchange(pDX);
        DDX_Text(pDX, IDC_EDIT_SCORE, m_strScore);
    }
    
    virtual BOOL PreTranslateMessage(MSG* pMsg) override {
        if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) {
            CWnd* pFocus = GetFocus();
            if (pFocus && pFocus->GetDlgCtrlID() == IDC_EDIT_SCORE) {
                UpdateData(TRUE); // 從控件取數據到 m_strScore
                int score = _ttoi(m_strScore);
                if (m_count < 8) m_scores[m_count++] = score;
                m_strScore = ""; // 清空
                UpdateData(FALSE); // 更新到控件
                return TRUE;
            }
        }
        return CDialogEx::PreTranslateMessage(pMsg);
    }
};

2. 入口點改為 MFC 模式

class CMyApp : public CWinApp {
    virtual BOOL InitInstance() override {
        CGradeStatisticDlg dlg;
        m_pMainWnd = &dlg;
        dlg.DoModal();
        return FALSE;
    }
};
CMyApp theApp;

兩種架構對比與選型建議

維度Win32 SDK (你現狀)MFC
學習曲線陡峭(需懂消息循環、資源腳本、手動內存)平緩(封裝好、向導生成樣板代碼)
代碼量大(全手寫)少(框架代碼+向導)
彈性極高(完全控制)中(受框架約束)
適合場景極小工具、嵌入式、學習底層原理企業級桌面應用、課程設計、快速交付

課程設計趕工期建議

  1. **堅持 Win32 SDK**:直接在 `_ProcDlgMain` 的 `WM_KEYDOWN` 處理邏輯,最快見效
  2. **資源編輯器設計對話框**:Visual Studio → Resource View → 右鍵 Add Resource → Dialog,拖放 Edit Control、Button、Static,自動生成 `IDD_...`、`IDC_...`
  3. **數據結構簡化**:用 `int scores[8]` + `int count` 替換彙編統計,可讀性強 100 倍
  4. **統計邏輯用 C++**:
    int distribution[6] = {}; // 0-59, 60-69, 70-79, 80-89, 90-99, 100
    for (int s : scores) {
        if (s < 60) distribution[0]++;
        else if (s < 70) distribution[1]++;
        else if (s < 80) distribution[2]++;
        else if (s < 90) distribution[3]++;
        else if (s < 100) distribution[4]++;
        else distribution[5]++;
    }
    SetDlgItemInt(hwnd, IDC_STATIC_60, distribution[0], TRUE); // 依次設置
    

總結

**不要在 Win32 SDK 代碼裡寫 `PreTranslateMessage`**——它屬於 MFC。在你的 `_ProcDlgMain` 處理 `WM_KEYDOWN` + `VK_RETURN` 即可實現「回車錄入、清空、準備下一條」。課程設計核心是**演示數據處理邏輯**,而非炫技框架;用最熟悉、最可控的方式把功能寫穩、界面做美、邏輯講清,分數才不會丟。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved