通过消息实现自定义输入框(InputBox)

C++Builder提供了两个显示输入对话框的函数:InputBoxInputQuery(其中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);

           
// 改变OKCancel按钮的标题
            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);
}
//---------------------------------------------------------------------------

//
抱歉,这个提示又来了,为了防止不负责任的转载者,只好在此留些信息。
// by ccrun(
老妖) info@ccrun.com
//
欢迎访问 C++Builder研究 - http://www.ccrun.com
//---------------------------------------------------------------------------

原先的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) 密码输入框的效果

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现一个自定义的IP地址输入框,可以借助WPF的自定义控件来实现。以下是一个简单的实现步骤: 1. 创建一个新的WPF自定义控件,并命名为"IPAddressInputBox"。 2. 在控件的XAML文件中,添加四个文本框用于输入IP地址的四个部分,以及用于分隔符的文本标签。 3. 在控件的代码文件中,添加四个依赖属性,分别对应IP地址的四个部分,以及一个绑定整个IP地址的依赖属性。 4. 在控件的代码文件中,添加一个IP地址验证方法,用于检查输入的IP地址是否合法。 5. 在控件的代码文件中,添加一个值改变事件,当任何一个IP地址部分的值发生改变时,验证IP地址的合法性,并更新绑定整个IP地址的依赖属性。 下面是一份示例代码,实现了一个简单的自定义IP地址输入框: IPAddressInputBox.xaml: ```xaml <UserControl x:Class="WpfCustomControls.IPAddressInputBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid> <TextBox x:Name="txtBox1" Width="40" MaxLength="3" TextChanged="txtBox_TextChanged"/> <TextBlock Text="." Margin="5,0,5,0"/> <TextBox x:Name="txtBox2" Width="40" MaxLength="3" TextChanged="txtBox_TextChanged"/> <TextBlock Text="." Margin="5,0,5,0"/> <TextBox x:Name="txtBox3" Width="40" MaxLength="3" TextChanged="txtBox_TextChanged"/> <TextBlock Text="." Margin="5,0,5,0"/> <TextBox x:Name="txtBox4" Width="40" MaxLength="3" TextChanged="txtBox_TextChanged"/> </Grid> </UserControl> ``` IPAddressInputBox.xaml.cs: ```csharp using System.Windows; using System.Windows.Controls; namespace WpfCustomControls { public partial class IPAddressInputBox : UserControl { public static readonly DependencyProperty IP1Property = DependencyProperty.Register("IP1", typeof(string), typeof(IPAddressInputBox), new PropertyMetadata("", OnIPChanged)); public static readonly DependencyProperty IP2Property = DependencyProperty.Register("IP2", typeof(string), typeof(IPAddressInputBox), new PropertyMetadata("", OnIPChanged)); public static readonly DependencyProperty IP3Property = DependencyProperty.Register("IP3", typeof(string), typeof(IPAddressInputBox), new PropertyMetadata("", OnIPChanged)); public static readonly DependencyProperty IP4Property = DependencyProperty.Register("IP4", typeof(string), typeof(IPAddressInputBox), new PropertyMetadata("", OnIPChanged)); public static readonly DependencyProperty IPAddressProperty = DependencyProperty.Register("IPAddress", typeof(string), typeof(IPAddressInputBox), new PropertyMetadata("", OnIPAddressChanged)); public string IP1 { get { return (string)GetValue(IP1Property); } set { SetValue(IP1Property, value); } } public string IP2 { get { return (string)GetValue(IP2Property); } set { SetValue(IP2Property, value); } } public string IP3 { get { return (string)GetValue(IP3Property); } set { SetValue(IP3Property, value); } } public string IP4 { get { return (string)GetValue(IP4Property); } set { SetValue(IP4Property, value); } } public string IPAddress { get { return (string)GetValue(IPAddressProperty); } set { SetValue(IPAddressProperty, value); } } public IPAddressInputBox() { InitializeComponent(); } private static void OnIPChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var inputBox = (IPAddressInputBox)d; inputBox.IPAddress = string.Format("{0}.{1}.{2}.{3}", inputBox.IP1, inputBox.IP2, inputBox.IP3, inputBox.IP4); } private static void OnIPAddressChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var inputBox = (IPAddressInputBox)d; var parts = inputBox.IPAddress.Split('.'); if (parts.Length == 4) { inputBox.IP1 = parts[0]; inputBox.IP2 = parts[1]; inputBox.IP3 = parts[2]; inputBox.IP4 = parts[3]; } } private void txtBox_TextChanged(object sender, TextChangedEventArgs e) { var tb = sender as TextBox; if (tb != null) { var value = tb.Text; if (string.IsNullOrEmpty(value) || int.TryParse(value, out int result) && result >= 0 && result <= 255) { // Value is valid tb.Foreground = SystemColors.WindowTextBrush; OnIPChanged(this, null); } else { // Value is invalid tb.Foreground = Brushes.Red; } } } } } ``` 使用自定义控件时,可以在XAML中引用,并绑定其依赖属性: ```xaml <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:custom="clr-namespace:WpfCustomControls;assembly=WpfCustomControls" Title="MainWindow" Height="450" Width="800"> <Grid> <custom:IPAddressInputBox IPAddress="{Binding MyIPAddress}" /> </Grid> </Window> ``` 其中,"MyIPAddress"是一个ViewModel中的属性,用于绑定整个IP地址的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值