首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

自訂 InputBox 對話框:透過訊息攔截實現中文化、密碼模式與圖示增強

     編輯:關於C++

問題背景

C++Builder 內建 InputBox/InputQuery 缺點明顯:按鈕標題為英文、字型顯示不全、無密碼模式、無圖示支援。修改 VCL 原始碼維護成本高,利用自訂訊息機制可在不修改 VCL 前提下優雅擴展功能。

核心思路

  1. InputBox 顯示前,主視窗 PostMessage 送出自訂訊息
  2. 主視窗重載 WndProc 攔截訊息
  3. 訊息處理中尋找輸入對話框視窗 (Screen->Forms[0]),修改其屬性與子控制項

實作程式碼

1. 定義自訂訊息


#define MY_INPUT_BOX WM_USER + 101

2. 表頭檔宣告 WndProc 覆寫


public:
    void __fastcall WndProc(TMessage &Msg);

3. 訊息處理完整邏輯


void __fastcall TfrmMain::WndProc(TMessage &Msg) {
    if (Msg.Msg == MY_INPUT_BOX) {
        // WParam: 0=一般模式, 1=密碼框模式
        // LParam: 0=一般模式, 1=帶圖片模式
        TForm *frm = Screen->Forms[0];
        if (frm != this) { // 確認是輸入框視窗
            // 統一字型 (建議主視窗設為新細明體 9pt)
            frm->Font->Assign(Font);
            
            // 中文化按鈕
            HWND hBtnOK = FindWindowEx(frm->Handle, NULL, "TButton", "OK");
            HWND hBtnCancel = FindWindowEx(frm->Handle, NULL, "TButton", "Cancel");
            if (hBtnOK) SetWindowText(hBtnOK, "確定(&O)");
            if (hBtnCancel) SetWindowText(hBtnCancel, "取消(&C)");
            
            // 加入圖片 (左下角)
            if (Msg.LParam == 1) {
                TImage *img = new TImage(frm); // Owner=frm, 自動釋放
                img->Picture->Assign(Application->Icon);
                img->Left = 11;
                img->Top = 60;
                img->Parent = frm;
                img->Show();
            }
            
            // 密碼模式
            if (Msg.WParam == 1) {
                HWND hEdit = FindWindowEx(frm->Handle, NULL, "TEdit", NULL);
                if (hEdit)
                    SendMessage(hEdit, EM_SETPASSWORDCHAR, WPARAM('*'), 0);
            }
        }
    }
    TForm::WndProc(Msg); // 傳遞給基類處理
}

四種使用模式展示

原始 InputBox (問題版)


void __fastcall TfrmMain::btnOldStyleClick(TObject *Sender) {
    String strText = InputBox("原先的輸入對話框", "請輸入一些字符:", "");
    if (strText.Trim().Length() > 0) ShowMessage(strText);
}

❌ 按鈕英文、字型醜陋、無密碼/圖片支援

改良版:中文化按鈕 + 字型統一


void __fastcall TfrmMain::btnNewStyleClick(TObject *Sender) {
    PostMessage(Handle, MY_INPUT_BOX, 0, 0); // 關鍵:發送自訂訊息
    String strText = InputBox("新的輸入對話框", "請輸入一些字符:", "");
    if (strText.Trim().Length() > 0) ShowMessage(strText);
}

✅ 中文按鈕、統一字型、顯示正常

帶圖片模式


void __fastcall TfrmMain::btnWithImageClick(TObject *Sender) {
    PostMessage(Handle, MY_INPUT_BOX, 0, 1); // LParam=1 表示帶圖片
    String strText = InputBox("帶圖片效果的輸入框", "請輸入一些字符:", "呵呵,帶圖片的");
    if (strText.Trim().Length() > 0) ShowMessage(strText);
}

✅ 左下角顯示應用程式圖示

密碼輸入模式


void __fastcall TfrmMain::btnPwdStyleClick(TObject *Sender) {
    PostMessage(Handle, MY_INPUT_BOX, 1, 0); // WParam=1 表示密碼模式
    String strText = InputBox("密碼輸入框", "請輸入您的密碼:", "123");
    if (strText.Trim().Length() > 0) ShowMessage(strText);
}

✅ 輸入字元顯示為 *

技術細節補充

  • FindWindowEx 依類別名/標題尋找子視窗,VCL 按鈕類別為 TButton,編輯框為 TEdit
  • EM_SETPASSWORDCHAR 編輯框訊息設定密碼遮罩字元
  • TImage 指定 Owner=frm 確保對話框關閉時自動釋放資源
  • 訊息參數設計:WParam 控制功能模式,LParam 控制視覺增強,可擴展更多組合

優缺點分析

優點缺點
零修改 VCL 原始碼依賴 VCL 內部視窗結構 (TButton/TEdit 類別名)
邏輯集中在主視窗,易維護僅適用於單執行緒 UI 應用
支援任意組合擴展若 VCL 版本大幅變更結構可能失效
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved