C++Builder提供了兩個顯示輸入對話框的函數:InputBox和InputQuery(其中InputBox也是通過調用InputQuery實現),這個輸入對話框有很多缺點,在以前的文章中我曾提到過利用修改VCL源碼來實現自定義輸入對話框,後來在Torry.net看到一篇文章是利用自定義消息的方法來實現,原文是Delphi代碼,ccrun(老妖)用C++改寫,並適當修改讓顯示效果更好一些:
基本思路:在輸入對話框顯示出來以前,Post一條消息給主窗體,由主窗體負責修改輸入對話框窗體的屬性和輸入文字編輯框的屬性,在主窗體中通過重載WndProc函數來響應自定義消息。
代碼及效果圖如下:
.h文件中:
public:
void __fastcall WndProc(TMessage &Msg);
.cpp文件中:
// 自定義一個消息,通知主窗體進行輸入框的設置
#define MY_INPUT_BOX WM_USER + 101
//---------------------------------------------------------------------------
// 重載主窗體的WndProc實現自定義消息的處理
void __fastcall TfrmMain::WndProc(TMessage &Msg)
{
if(Msg.Msg == MY_INPUT_BOX)
{
// Msg.WParam
// 0: 普通模式, 1: 密碼框模式
// Msg.LParam
// 0: 普通模式, 1: 帶圖片的模式
TForm *frm = Screen->Forms[0];
if(frm != this) // 輸入框窗體
{
// 將輸入對話框的字體設為和主窗體一樣,建議將主窗體字體設為宋體9號
frm->Font->Assign(Font);
// 改變OK和Cancel按鈕的標題
HANDLE hBtnOK = FindWindowEx(frm->Handle, NULL, "TButton", "OK");
HANDLE hBtnCancel = FindWindowEx(frm->Handle, NULL, "TButton", "Cancel");
if(hBtnOK)
SetWindowText(hBtnOK, "確定(&O)");
if(hBtnCancel)
SetWindowText(hBtnCancel, "取消(&C)");
// 是否需要顯示一個圖片
if(Msg.LParam == 1)
{
// 新增一個圖片在窗體左下角,指定其Owner為輸入框窗體,
// 這樣當輸入框窗體關閉時自動釋放TImage的資源
TImage *img = new TImage(frm);
img->Picture->Assign(Application->Icon);
img->Left = 11;
img->Top = 60;
img->Parent = frm;
img->Show();
}
// 是否為密碼框式 // 63 63 72 75 6E 2E 63 6F 6D
if(Msg.WParam == 1)
{
HANDLE hEdit = FindWindowEx(frm->Handle, NULL, "TEdit", NULL);
if(hEdit)
SendMessage(hEdit, EM_SETPASSWORDCHAR, WPARAM('*'), 0);
}
}
}
TForm::WndProc(Msg);
}
原先的InputBox(圖1)void __fastcall TfrmMain::btnOldStyleClick(TObject *Sender)
{
String strText = InputBox("原先的輸入對話框", "請輸入一些字符: ", "");
if(strText.Trim().Length() > 0)
ShowMessage(strText);
}
(圖1) 可以看到窗體上字符顯示不全,並且兩個按鈕的標題也是英文的。
改良後的效果(圖2)
void __fastcall TfrmMain::btnNewStyleClick(TObject *Sender)
{
PostMessage(Handle, MY_INPUT_BOX, 0, 0); // 重點是這一句
String strText = InputBox("新的輸入對話框", "請輸入一些字符: ", "");
if(strText.Trim().Length() > 0)
ShowMessage(strText);
}
(圖2) 經過改良後,字符顯示就比較漂亮了,按鈕標題也是中文的。
帶圖片的效果 (圖3)
void __fastcall TfrmMain::btnWithImageClick(TObject *Sender)
{
// Msg.LParam = 1: 帶圖片的模式
PostMessage(Handle, MY_INPUT_BOX, 0, 1);
String strText = InputBox("帶圖片效果的輸入框", "請輸入一些字符: ", "呵呵,帶圖片的");
if(strText.Trim().Length() > 0)
ShowMessage(strText);
}
(圖3)帶圖片效果的輸入框
密碼輸入框效果(圖4)
void __fastcall TfrmMain::btnPwdStyleClick(TObject *Sender)
{
// Msg.WParam = 1: 密碼框模式
PostMessage(Handle, MY_INPUT_BOX, 1, 0);
String strText = InputBox("密碼輸入框", "請輸入您的密碼: ", "123");
if(strText.Trim().Length() > 0)
ShowMessage(strText);
}
(圖4) 密碼輸入框的效果