WinForm应用程序中的ComboBox实现ReadOnly功能

今天在做软件时遇到了一个问题,记录下来,以后备用,呵呵:

在ComboBox控件的DropDownStyle有三种属性:
1.Simple 类似TextBox的外观,文本部分可以编辑,控件的Text值可显示,Items中的项要靠键盘“↑”、“↓”来选择。
2.DropDown 文本部分可以编辑,控件的Text值可显示,Items中的项通过点击控件的“▼”出现的下拉选择框来选择。
3.DropDownList 文本部分不可编辑,不能设置控件的Text值,Items中的项通过点击控件的“▼”出现的下拉选择框来选择。

本来是要用类似DropDown 的样式,开始时设置控件的Text值作为提示,但在用户选择选项时,不能让他编辑选项的内容,本来以为会有个ReadOnly属性
然后设置一下就可以了,可没想到把属性列表挨个看了好几遍就是没找到,真不知道MS当时设计控件时怎么想的,只好查资料看能不能实现那样的功能,

找了半天发现用windows API来实现比较简单(又是windows API看来windows API真的很好很强大)
引用命名空间:
using System.Runtime.InteropServices;
用到的API声明:
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);
        int GW_CHILD = 5;
       
[DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
        public const int EM_SETREADONLY = 0xcf;

1.用GetWindow API取得要设置的ComboBox控件的句柄。
2.用SendMessage API给取得的句柄设置只读属性。


示例代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);
        int GW_CHILD = 5;
       
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
        public const int EM_SETREADONLY = 0xcf;

 

        public Form1()
        {
            InitializeComponent();
            IntPtr editHandle = GetWindow(comboBox1.Handle , GW_CHILD);
            SendMessage(editHandle,EM_SETREADONLY,1,0);
        }        
    }
}


别人解释的用到的原理:
1.comboBox其实是一个嵌套控件(复合控件)在DropDownList状态时;他由下拉列表,和ComboBox本身组成
  DropDown状态时ComboBox中多了一个edit就是.net下的TextBox那个输入状态是由edit控制的;
  不过这个edit是无法在.net下取得的this.comboBox1.Controls.Count 返回 0.
2.用AIP取得控件句柄。
3.给控件设置只读状态。
  这个就是发个消息基本可以搞定(不过忘记是那个消息了),看看msdn找em_ 开头的消息,找到EM_SETREADONLY看名字就是他了;
  根据SDK规则,em_ 开头的消息都是对应edit的.

转载于:https://my.oschina.net/secyaher/blog/274470

以下是WinForm实现串口通信的步骤: 1.在窗体上添加控件:Label、ComboBox、Button、TextBox等。 2.在代码定义串口对象SerialPort,以及串口参数:串口号、波特率、数据位、停止位、校验位等。 3.在代码编写串口打开、关闭、发送数据、接收数据等相关操作。 4.在代码编写串口接收数据的回调函数,将接收到的数据显示在文本框。 5.在代码编写保存串口参数设置的函数,以便下次打开程序时能够自动加载上次的设置。 以下是一个WinForm实现串口通信的示例代码: ```csharp using System; using System.IO.Ports; using System.Windows.Forms; namespace SerialPortDemo { public partial class Form1 : Form { private SerialPort _serialPort = new SerialPort(); private Tuple<Label, ComboBox>[] _portSetting = new Tuple<Label, ComboBox>[5]; private Button _btnSwitch = new Button(); private Button _btnSaveSetting = new Button(); private TextBox _txtTrans = new TextBox(); public Form1() { InitializeComponent(); // 初始化串口参数设置控件 _portSetting[0] = new Tuple<Label, ComboBox>(label1, comboBox1); _portSetting[1] = new Tuple<Label, ComboBox>(label2, comboBox2); _portSetting[2] = new Tuple<Label, ComboBox>(label3, comboBox3); _portSetting[3] = new Tuple<Label, ComboBox>(label4, comboBox4); _portSetting[4] = new Tuple<Label, ComboBox>(label5, comboBox5); // 初始化串口开关按钮 _btnSwitch.Text = "打开串口"; _btnSwitch.Click += new EventHandler(btnSwitch_Click); // 初始化保存设置按钮 _btnSaveSetting.Text = "保存设置"; _btnSaveSetting.Click += new EventHandler(btnSaveSetting_Click); // 初始化文本框 _txtTrans.Multiline = true; _txtTrans.ScrollBars = ScrollBars.Vertical; _txtTrans.ReadOnly = true; // 将控件添加到窗体上 this.Controls.Add(_btnSwitch); this.Controls.Add(_btnSaveSetting); this.Controls.Add(_txtTrans); foreach (var item in _portSetting) { this.Controls.Add(item.Item1); this.Controls.Add(item.Item2); } // 加载串口参数设置 LoadSerialPortSetting(); } private void btnSwitch_Click(object sender, EventArgs e) { if (_serialPort.IsOpen) { // 关闭串口 _serialPort.Close(); _btnSwitch.Text = "打开串口"; } else { // 打开串口 try { _serialPort.PortName = _portSetting[0].Item2.Text; _serialPort.BaudRate = int.Parse(_portSetting[1].Item2.Text); _serialPort.DataBits = int.Parse(_portSetting[2].Item2.Text); _serialPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), _portSetting[3].Item2.Text); _serialPort.Parity = (Parity)Enum.Parse(typeof(Parity), _portSetting[4].Item2.Text); _serialPort.Open(); _serialPort.DataReceived += new SerialDataReceivedEventHandler(_serialPort_DataReceived); _btnSwitch.Text = "关闭串口"; } catch (Exception ex) { MessageBox.Show(ex.Message); } } } private void btnSaveSetting_Click(object sender, EventArgs e) { // 保存串口参数设置 Properties.Settings.Default.PortName = _portSetting[0].Item2.Text; Properties.Settings.Default.BaudRate = _portSetting[1].Item2.Text; Properties.Settings.Default.DataBits = _portSetting[2].Item2.Text; Properties.Settings.Default.StopBits = _portSetting[3].Item2.Text; Properties.Settings.Default.Parity = _portSetting[4].Item2.Text; Properties.Settings.Default.Save(); } private void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { // 接收数据回调函数 string recv = _serialPort.ReadExisting(); _txtTrans.Invoke(new Action(() => _txtTrans.Text += recv)); } private void LoadSerialPortSetting() { // 加载串口参数设置 _portSetting[0].Item2.Text = Properties.Settings.Default.PortName; _portSetting[1].Item2.Text = Properties.Settings.Default.BaudRate; _portSetting[2].Item2.Text = Properties.Settings.Default.DataBits; _portSetting[3].Item2.Text = Properties.Settings.Default.StopBits; _portSetting[4].Item2.Text = Properties.Settings.Default.Parity; } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值