代码之家  ›  专栏  ›  技术社区  ›  lincolnk

展开时重新绘制组合框项

  •  1
  • lincolnk  · 技术社区  · 15 年前

    我有一个带有绑定组合框的.NET3.5Windows应用程序。我已重写DrawItem事件,根据特定条件为单个项目的背景着色。我有一些异步线程正在运行,它们更新条件值并调用Invalidate()来重新绘制组合框。

    这一切都很好,除了当组合框被展开时-DrawItem仅为列表中突出显示的项调用。其他项仅在用户执行某些操作时刷新,例如将鼠标悬停在列表中的另一项上或单击其他控件。我想在列表打开时自动重新绘制其他项目。我该如何做到这一点?可能吗?

    谢谢

    编辑:我确定在扩展列表中突出显示的任何项目都会在主组合框显示中重新绘制。列表中的任何项都不会在控件的展开部分中重新绘制。

    要重现该行为,请单击“检测”按钮,然后打开组合框并将鼠标悬停在COM1上。测试结果将按1,3,2的顺序结束。您可以看到,当组合框打开时,COM3将保持黄色,直到您将高亮显示移到其上,然后关闭。

    using System;
    using System.Windows.Forms;
    using System.Collections.Generic;
    using System.IO.Ports;
    using System.Diagnostics;
    using System.Drawing;
    
    namespace combocolor
    {
    public partial class Demo2 : Form
    {
    private System.ComponentModel.IContainer components = null;
    private System.Windows.Forms.Label ComPortLabel;
    private System.Windows.Forms.ComboBox ComPortComboBox;
    private System.Windows.Forms.ErrorProvider MainErrorProvider;
    private System.Windows.Forms.Button autoQueryButton;
    
    delegate PortTestResult TestPortDelegate(string portName);
    delegate void UpdateTestResultsDelegate(PortTestResult portTestResult);
    
    string[] _ports = new string[] { "COM1", "COM2", "COM3" };
    Dictionary<string, int> _autoDetectResults = null;
    
    public Demo2()
    {
        InitializeComponent();
    }
    
    private void Settings_Load(object sender, EventArgs e)
    {
        this.ComPortComboBox.Items.AddRange(this._ports);
        this.ComPortComboBox.SelectedIndex = 0;
    }
    
    private void autoQueryButton_Click(object sender, EventArgs e)
    {
        // start port testing
        this._autoDetectResults = new Dictionary<string, int>(this._ports.Length);
        foreach (string portName in this._ports)
        {
            this._autoDetectResults.Add(portName, 0);
            this.ComPortComboBox.Invalidate();
    
            try
            {
                TestPortDelegate testDel = new TestPortDelegate(TestSerialPort);    // check port on a new thread
                testDel.BeginInvoke(portName, new AsyncCallback(TestFinishedCallback), testDel);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex);
            }
        }
    }
    
    private void ComPortComboBox_DrawItem(object sender, DrawItemEventArgs e)
    {
        SolidBrush backgroundBrush, foregroundBrush;
        Dictionary<int, Color> colormap = new Dictionary<int, Color>();
    
        colormap.Add(0, Color.Yellow);
        colormap.Add(-1, Color.Red);
        colormap.Add(1, Color.LimeGreen);
        string itemText = (string)ComPortComboBox.Items[e.Index];
    
        // select a background color based on autodetect status
        if (this._autoDetectResults == null)
        {
            backgroundBrush = new System.Drawing.SolidBrush(e.BackColor);
        }
        else
        {
            int key = this._autoDetectResults[itemText];
            backgroundBrush = new SolidBrush(colormap[key]);
        }
    
        if ((e.State & DrawItemState.Selected) > 0 && (e.State & DrawItemState.ComboBoxEdit) == 0)
        {
            e.DrawBackground(); // draws the blue highlight
            foregroundBrush = new SolidBrush(e.ForeColor); // text color
        }
        else
        {
            e.Graphics.FillRectangle(backgroundBrush, e.Bounds); // draws the color based on the autodetect results
            foregroundBrush = new SolidBrush(this.ComPortComboBox.ForeColor); // text color 
        }
    
        e.Graphics.DrawString(itemText, e.Font, foregroundBrush, e.Bounds); // draw the text
    }
    
    private PortTestResult TestSerialPort(string portName)
    {
        PortTestResult result = new PortTestResult();
        result.PortName = portName;
    
        // simulated results
        switch (portName)
        {
            case "COM1":
                System.Threading.Thread.Sleep(2000);
                result.UseThisPort = false;
                break;
            case "COM2":
                System.Threading.Thread.Sleep(6000);
                result.UseThisPort = true;
                break;
            case "COM3":
                System.Threading.Thread.Sleep(4000);
                result.UseThisPort = false;
                break;
        }
    
        return result;
    }
    
    private void TestFinishedCallback(IAsyncResult ar)
    {
        // get the results from the test function
        TestPortDelegate testPortDelegate = (TestPortDelegate)((System.Runtime.Remoting.Messaging.AsyncResult)ar).AsyncDelegate;
        PortTestResult portTestResult = testPortDelegate.EndInvoke(ar);
        UpdateTestResults(portTestResult); // pass the results along to update the UI
    }
    
    private void UpdateTestResults(PortTestResult portTestResult)
    {
        if (this.ComPortComboBox.InvokeRequired)
        {
            UpdateTestResultsDelegate updateTestResultsDelegate = new UpdateTestResultsDelegate(UpdateTestResults);
            this.Invoke(updateTestResultsDelegate, portTestResult);
        }
        else
        { // set status based on test result
            if (portTestResult.UseThisPort)
            {
                this._autoDetectResults[portTestResult.PortName] = 1;   // 1 for a good response
                this.ComPortComboBox.SelectedItem = portTestResult.PortName;
            }
            else
            {
                this._autoDetectResults[portTestResult.PortName] = -1; // -1 for a bad response
            }
            this.ComPortComboBox.Invalidate();  // force the combobox to redraw with new colors
        }
    }
    
    
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
    private void InitializeComponent()
    {
        this.components = new System.ComponentModel.Container();
        this.ComPortComboBox = new System.Windows.Forms.ComboBox();
        this.ComPortLabel = new System.Windows.Forms.Label();
        this.MainErrorProvider = new System.Windows.Forms.ErrorProvider(this.components);
        this.autoQueryButton = new System.Windows.Forms.Button();
        ((System.ComponentModel.ISupportInitialize)(this.MainErrorProvider)).BeginInit();
        this.SuspendLayout();
        this.ComPortComboBox.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
        this.ComPortComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
        this.ComPortComboBox.FormattingEnabled = true;
        this.ComPortComboBox.Location = new System.Drawing.Point(71, 12);
        this.ComPortComboBox.Name = "ComPortComboBox";
        this.ComPortComboBox.Size = new System.Drawing.Size(136, 21);
        this.ComPortComboBox.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.ComPortComboBox_DrawItem);
        this.ComPortLabel.Location = new System.Drawing.Point(12, 15);
        this.ComPortLabel.Name = "ComPortLabel";
        this.ComPortLabel.Size = new System.Drawing.Size(53, 13);
        this.ComPortLabel.Text = "&Com Port:";
        this.autoQueryButton.Location = new System.Drawing.Point(213, 11);
        this.autoQueryButton.Name = "autoQueryButton";
        this.autoQueryButton.Size = new System.Drawing.Size(49, 21);
        this.autoQueryButton.Text = "detect";
        this.autoQueryButton.UseVisualStyleBackColor = false;
        this.autoQueryButton.Click += new System.EventHandler(this.autoQueryButton_Click);
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(282, 47);
        this.Controls.Add(this.autoQueryButton);
        this.Controls.Add(this.ComPortLabel);
        this.Controls.Add(this.ComPortComboBox);
        this.Name = "Demo";
        this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
        this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
        this.Load += new System.EventHandler(this.Settings_Load);
        ((System.ComponentModel.ISupportInitialize)(this.MainErrorProvider)).EndInit();
        this.ResumeLayout(false);
        this.PerformLayout();
    }
    }
    
    public class PortTestResult
    {
        public string PortName { get; set; }
        public bool UseThisPort { get; set; }
    }
    }
    
    1 回复  |  直到 14 年前
        1
  •  2
  •   Stewbob    15 年前

    这篇CodeProject文章提供了有关自定义组合框的详细信息: Article