2009-07-24 66 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