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( |