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; }
}
}