2009-07-24 58 views
1

我有一个.net 3.5窗口应用程序与绑定组合框。我已经重写了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; } 
} 
} 

回答

2

这CodeProject上的文章对自定义ComboBox伟大的信息:Article