C#WPF登录界面-自定义控件

效果

登录界面效果

实现

说明:
①账号、密码、验证码的每一行都是一个用户控件(UserControl);
②水印”账号“、”密码“、”验证码“是直接写在用户控件中最底层的label,在文本框的焦点获取和丢失事件中操作水印的可见性。

用户控件:账号

1.准备图片

用户
2.新建用户控件”UserTextBox.xaml“
3.调整位置和大小,CornerRadius是调整文本框的圆角👇

<Label x:Name="labelUser" Content="账号" HorizontalAlignment="Left" Margin="30,0,0,0" VerticalAlignment="Center" Foreground="#FFACAAAA" />
<Image HorizontalAlignment="Left" Height="20" Margin="0,0,0,0" VerticalAlignment="Center" Width="20" Source="/Image/user.png"/>
<TextBox x:Name="textBoxUser" HorizontalAlignment="Left" Margin="30,0,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Center" Width="170" Height="25" FontSize="13" Background="{x:Null}" Foreground="Black" VerticalContentAlignment="Center" GotFocus="textBoxUser_GotFocus" LostFocus="textBoxUser_LostFocus">
    <TextBox.Resources>
        <Style TargetType="{x:Type Border}">
            <Setter Property="CornerRadius" Value="5" />
        </Style>
    </TextBox.Resources>
</TextBox>

4.逻辑编写”UserTextBox.xaml.cs“

/// <summary>
/// 判断文本框是否有输入
/// </summary>
private bool bHadInput = false;

/// <summary>
/// 文本框获取焦点
/// </summary>
private void textBoxUser_GotFocus(object sender, RoutedEventArgs e)
{
    //如果文本框没有输入,则清空文本框(即清除label“账号”)
    if (!bHadInput)
    {
        labelUser.Visibility = Visibility.Collapsed;
    }
}

/// <summary>
/// 文本框失去焦点
/// </summary>
private void textBoxUser_LostFocus(object sender, RoutedEventArgs e)
{
    //如果文本框为空,则显示默认的内容(即灰色的label“账号”),同时将bHadInput置为false;否则,将bHadInput置为true
    if (textBoxUser.Text.Equals(string.Empty))
    {
        labelUser.Visibility = Visibility.Visible;
        bHadInput = false;
    }
    else
    {
        bHadInput = true;
    }
}

用户控件:密码

1.准备图片
密码

2.新建用户控件”PasswordTextBox.xaml“
3.调整位置和大小,CornerRadius是调整文本框的圆角👇

<Label x:Name="labelPassword" Content="密码" HorizontalAlignment="Left" Margin="30,0,0,0" VerticalAlignment="Center" Foreground="#FFACAAAA" />
<Image HorizontalAlignment="Left" Height="20" Margin="0,0,0,0" VerticalAlignment="Center" Width="20" Source="/Image/password.png"/>
<PasswordBox x:Name="passwordBox" HorizontalAlignment="Left" Margin="30,0,0,0" VerticalAlignment="Center" VerticalContentAlignment="Center" Background="{x:Null}" Width="170" Height="25" FontSize="13" GotFocus="passwordBox_GotFocus" LostFocus="passwordBox_LostFocus">
    <PasswordBox.Resources>
        <Style TargetType="{x:Type PasswordBox}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type PasswordBox}">
                        <Border x:Name="Border"
                        Background="{TemplateBinding Background}"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        CornerRadius="5">
                            <ScrollViewer x:Name="PART_ContentHost" Focusable="True" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </PasswordBox.Resources>
</PasswordBox>

4.逻辑编写”PasswordTextBox.xaml.cs“

/// <summary>
/// 判断文本框是否有输入
/// </summary>
private bool bHadInput = false;

/// <summary>
/// 文本框获取焦点
/// </summary>
private void passwordBox_GotFocus(object sender, RoutedEventArgs e)
{
    //如果文本框没有输入,则清空文本框(即清除label“密码”)
    if (!bHadInput)
    {
        labelPassword.Visibility = Visibility.Collapsed;
    }
}

/// <summary>
/// 文本框失去焦点
/// </summary>
private void passwordBox_LostFocus(object sender, RoutedEventArgs e)
{
    //如果文本框为空,则显示默认的内容(即label“密码”),同时将bHadInput置为false;否则,将bHadInput置为true
    if (passwordBox.Password.Equals(string.Empty))
    {
        labelPassword.Visibility = Visibility.Visible;
        bHadInput = false;
    }
    else
    {
        bHadInput = true;
    }
}

用户控件:验证码

1新建用户控件”ValidcodeTextBox.xaml“,调整位置和大小👇

<Label x:Name="labelValidcode" Content="验证码" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Center" Foreground="#FFACAAAA" />
<TextBox x:Name="textBoxValidcode" HorizontalAlignment="Left" Margin="0,0,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Center" Width="90" Height="25" FontSize="13" Background="{x:Null}" VerticalContentAlignment="Center" GotFocus="textBoxValidcode_GotFocus" LostFocus="textBoxValidcode_LostFocus">
    <TextBox.Resources>
        <Style TargetType="{x:Type Border}">
            <Setter Property="CornerRadius" Value="5" />
        </Style>
    </TextBox.Resources>
</TextBox>
<Image x:Name="imgValidcode" Margin="100,0,0,0" Height="25" Loaded="imgValidcode_Loaded" Stretch="UniformToFill" StretchDirection="DownOnly" MouseLeftButtonUp="imgValidcode_MouseLeftButtonUp" />

2.新建类ValidCode.cs,比较重要的再此段代码的最下面的方法”CreateCheckCodeImage()“👇,可以在此方法中修改字体样式等等

using System;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace HMIS.PublicClass
{
    public class ValidCode
    {
        #region Private Fields
        private const double PI = 3.1415926535897932384626433832795;
        private const double PI2 = 6.283185307179586476925286766559;
        //private readonly int _wordsLen = 4; 
        private int _len;
        private CodeType _codetype;
        private readonly Single _jianju = (float)20.0;
        private readonly Single _height = (float)25.0;
        private string _checkCode;
        #endregion

        #region Public Property
        public string CheckCode
        {
            get
            {
                return _checkCode;
            }
        }
        #endregion

        #region Constructors
        public ValidCode(int len, CodeType ctype)
        {
            this._len = len;
            this._codetype = ctype;
        }
        #endregion

        #region Public Field
        public enum CodeType { Words, Numbers, Characters, Alphas }
        #endregion

        #region Private Methods
        private string GenerateNumbers()
        {
            string strOut = "";
            System.Random random = new Random();
            for (int i = 0; i < _len; i++)
            {
                string num = Convert.ToString(random.Next(10000) % 10);
                strOut += num;
            }
            return strOut.Trim();
        }

        private string GenerateCharacters()
        {
            string strOut = "";
            System.Random random = new Random();
            for (int i = 0; i < _len; i++)
            {
                string num = Convert.ToString((char)(65 + random.Next(10000) % 26));
                strOut += num;
            }
            return strOut.Trim();
        }

        private string GenerateAlphas()
        {
            string strOut = "";
            string num = "";
            System.Random random = new Random();
            for (int i = 0; i < _len; i++)
            {
                if (random.Next(500) % 2 == 0)
                {
                    num = Convert.ToString(random.Next(10000) % 10);
                }
                else
                {
                    num = Convert.ToString((char)(65 + random.Next(10000) % 26));
                }
                strOut += num;
            }
            return strOut.Trim();
        }

        private System.Drawing.Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
        {
            System.Drawing.Bitmap destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);
            // 将位图背景填充为白色 
            System.Drawing.Graphics graph = System.Drawing.Graphics.FromImage(destBmp);

            graph.FillRectangle(new SolidBrush(System.Drawing.Color.Transparent), 0, 0, destBmp.Width, destBmp.Height);
            graph.Dispose();
            double dBaseAxisLen = bXDir ? (double)destBmp.Height : (double)destBmp.Width;

            for (int i = 0; i < destBmp.Width; i++)
            {
                for (int j = 0; j < destBmp.Height; j++)
                {
                    double dx = 0;
                    dx = bXDir ? (PI2 * (double)j) / dBaseAxisLen : (PI2 * (double)i) / dBaseAxisLen;
                    dx += dPhase;
                    double dy = Math.Sin(dx);
                    // 取得当前点的颜色 
                    int nOldX = 0, nOldY = 0;
                    nOldX = bXDir ? i + (int)(dy * dMultValue) : i;
                    nOldY = bXDir ? j : j + (int)(dy * dMultValue);
                    System.Drawing.Color color = srcBmp.GetPixel(i, j);

                    if (nOldX >= 0 && nOldX < destBmp.Width && nOldY >= 0 && nOldY < destBmp.Height)
                    {
                        destBmp.SetPixel(nOldX, nOldY, color);
                    }
                }
            }
            return destBmp;
        }
        #endregion

        #region Public Methods
        public Bitmap CreateCheckCodeImage()
        {
            string checkCode;
            switch (_codetype)
            {
                case CodeType.Alphas:
                    checkCode = GenerateAlphas();
                    break;
                case CodeType.Numbers:
                    checkCode = GenerateNumbers();
                    break;
                case CodeType.Characters:
                    checkCode = GenerateCharacters();
                    break;
                default:
                    checkCode = GenerateAlphas();
                    break;
            }
            this._checkCode = checkCode;
            MemoryStream ms = null;
            if (checkCode == null || checkCode.Trim() == String.Empty)
                return null;
            Bitmap image = new System.Drawing.Bitmap((int)Math.Ceiling((checkCode.Length * _jianju)), (int)_height);
            Graphics g = Graphics.FromImage(image);
            try
            {
                Random random = new Random();
                g.Clear(System.Drawing.Color.White);
                // 画图片的背景噪音线 
                for (int i = 0; i < 18; i++)
                {
                    int x1 = random.Next(image.Width);
                    int x2 = random.Next(image.Width);
                    int y1 = random.Next(image.Height);
                    int y2 = random.Next(image.Height);
                    g.DrawLine(new System.Drawing.Pen(Color.FromArgb(random.Next()), 1), x1, y1, x2, y2);
                }
                Font font = new System.Drawing.Font("Times New Roman", 8, System.Drawing.FontStyle.Bold);//字体调整
                LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.Blue, Color.DarkRed, 1.2f, true);
                if (_codetype != CodeType.Words)
                {
                    for (int i = 0; i < checkCode.Length; i++)
                    {
                        g.DrawString(checkCode.Substring(i, 1), font, brush, 2 + i * _jianju, 4);
                    }
                }
                else
                {
                    g.DrawString(checkCode, font, brush, 2, 2);
                }
                // 画图片的前景噪音点 
                for (int i = 0; i < 150; i++)
                {
                    int x = random.Next(image.Width);
                    int y = random.Next(image.Height);
                    image.SetPixel(x, y, Color.FromArgb(random.Next()));
                }
                 画图片的波形滤镜效果 
                //if (_codetype != CodeType.Words)
                //{
                //    image = TwistImage(image, true, 3, 1);
                //}
                // 画图片的边框线 
                g.DrawRectangle(new Pen(Color.Silver), 0, 0, image.Width - 1, image.Height - 1);

                ms = new System.IO.MemoryStream();
                image.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
            }
            finally
            {
                g.Dispose();
                //image.Dispose();
            }
            return image;
        }
        #endregion
    }
}

3.在ValidcodeTextBox.xaml.cs类中,创建方法BitmapToImageSource,用来将Bitmap转为ImageSource,用于Image.Source👇

/// <summary>
/// Bitmap转ImageSource
/// </summary>
/// <param name="image">提供的Bitmap</param>
/// <returns>返回的ImageSource</returns>
public ImageSource BitmapToImageSource(Bitmap image)
{
    BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
        image.GetHbitmap(),
        IntPtr.Zero,
        Int32Rect.Empty,
        BitmapSizeOptions.FromEmptyOptions()
    );
    return bitmapSource;
}

4.创建刷新验证码的方法,在需要刷新验证码的地方调用此方法即可👇,比如在窗体刚加载时或者Image的点击事件中(即点击切换验证码);5代表5位验证码,具体的使用可参考C#登录界面验证码

public static ValidCode validCode = new ValidCode(5, ValidCode.CodeType.Alphas);//实例化这个对象
private void RefreshVaildcode()
{
    imgValidcode.Source = BitmapToImageSource(validCode.CreateCheckCodeImage());//刷新验证码
}

5.编写水印显示与否的相关内容

/// <summary>
/// 判断文本框是否有输入
/// </summary>
private bool bHadInput = false;

/// <summary>
/// 文本框获取焦点
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void textBoxValidcode_GotFocus(object sender, RoutedEventArgs e)
{
    //如果文本框没有输入,则清空文本框(即清除label“验证码”)
    if (!bHadInput)
    {
        labelValidcode.Visibility = Visibility.Collapsed;
    }
}

/// <summary>
/// 文本框失去焦点
/// </summary>
private void textBoxValidcode_LostFocus(object sender, RoutedEventArgs e)
{
    //如果文本框为空,则显示默认的内容(即label“验证码”),同时将bHadInput置为false;否则,将bHadInput置为true
    if (textBoxValidcode.Text.Equals(string.Empty))
    {
        labelValidcode.Visibility = Visibility.Visible;
        bHadInput = false;
    }
    else
    {
        bHadInput = true;
    }
}

在主界面中引用用户控件

xmlns:userControlItems="clr-namespace:HMIS.UserControlItems"

<userControlItems:UserTextBox x:Name="userTextBox" Margin="0,20,0,150" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" />
<userControlItems:PasswordTextBox x:Name="passwordTextBox" Margin="0,70,0,100" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" />
<userControlItems:ValidcodeTextBox x:Name="validcodeTextBox" Margin="0,120,0,50" VerticalContentAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" />
  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF工控软件自定义控件是指在基于.NET6框架下使用WPF MVVM进行UI设计时,开发者可以自定义控件来满足特定的功能需求。这些自定义控件可以根据项目的需求进行设计和修改,以提供更好的用户体验和功能支持。 如果你对WPF工控软件自定义控件感兴趣,我建议你可以下载并编译相关的示例代码,并尝试修改它们以适应你的项目需求。你可以在这个链接上找到相关界面的示例代码:https://blog.csdn.net/u010186391/article/details/125601226。通过实际操作和修改示例代码,你可以更好地理解和应用WPF自定义控件、样式、MVVM和异步线程等方面的知识。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [NET6+WPF+MVVM ](https://download.csdn.net/download/u010186391/85926327)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [C# WPF 自定义控件 滑块控件 开关控件 ToggleButton Switcher](https://blog.csdn.net/shizu11zz/article/details/120459009)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值