<style></style>
SunnyUI.Net, 基于 C# .Net WinForm 開源控制元件庫、工具類別庫、擴展類別庫、多頁面開發框架

- Blog: https://www.cnblogs.com/yhuse
- Gitee: https://gitee.com/yhuse/SunnyUI
- GitHub: https://github.com/yhuse/SunnyUI
- 幫助檔案目錄: https://www.cnblogs.com/yhuse/p/SunnyUI_Menu.html
- 歡迎交流,QQ群:56829229 (SunnyUI技術交流群)
SunnyUI.Net 開發日志:ListBox 增加跟隨滑鼠滑過高亮
QQ群里,寸木說,ListBox滑鼠移動時,當前行需要焦點,我想了想,不難實作啊

不就是在滑鼠移動時重繪Item嘛,何況選中的Item已經改了顏色了,
見UIListBox代碼:
protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e);
BeforeDrawItem?.Invoke(this, Items, e);
if (Items.Count == 0)
{
return;
}
e.DrawBackground();
if (e.Index < 0 || e.Index >= Items.Count)
{
return;
}
StringFormat sStringFormat = new StringFormat();
sStringFormat.LineAlignment = StringAlignment.Center;
Color backColor = (e.State & DrawItemState.Selected) == DrawItemState.Selected ? ItemSelectBackColor : BackColor;
Color foreColor = (e.State & DrawItemState.Selected) == DrawItemState.Selected ? ItemSelectForeColor : ForeColor;
Rectangle rect = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width - 1, e.Bounds.Height - 1);
e.Graphics.FillRectangle(BackColor, e.Bounds);
e.Graphics.FillRoundRectangle(backColor, rect, 5);
e.Graphics.DrawString(Items[e.Index].ToString(), e.Font, foreColor, e.Bounds, sStringFormat);
}
看:(e.State & DrawItemState.Selected) == DrawItemState.Selected 選中行狀態嘛
看了e.State有e.State == DrawItemState.HotLight,不就是高亮的么,于是開始擼代碼,加狀態判斷
Run
暈,,,沒變,這HotLight不起作用,好吧,問度娘,,,
翻山越嶺,跋山涉水,,,
找到這篇:https://www.jb51.cc/csharp/101121.html
其中提到:
我在我的WinForms應用程式中使用OwnerDrawFixed作為DrawMode用于自定義ListBox控制元件.當用戶將滑鼠懸停在串列框專案上時,我希望重新繪制ListBoxItem的背景(或執行其他操作),即在MouseMove …DrawItemState.HotLight永遠不適用于ListBox,所以我想知道如何模擬它,如何解決這個問題.
DrawItemState.HotLight永遠不適用于ListBox,是永遠,,,怎么這么遠,,,
繼續往下看:
解決方法
我花了兩年時間為你找到答案,但這里是:DrawItemState.HotLight僅適用于所有者繪制的選單,而不適用于串列框.對于ListBox,您必須自己跟蹤專案:
public partial class Form1 : Form
{
private int _MouseIndex = -1;
public Form1()
{ InitializeComponent(); }
private void listBox1_DrawItem(object sender,DrawItemEventArgs e)
{
Brush textBrush = SystemBrushes.WindowText;
if (e.Index > -1)
{
if (e.Index == _MouseIndex)
{
e.Graphics.FillRectangle(SystemBrushes.HotTrack,e.Bounds);
textBrush = SystemBrushes.HighlightText;
}
else
{
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
e.Graphics.FillRectangle(SystemBrushes.Highlight,e.Bounds);
textBrush = SystemBrushes.HighlightText;
}
else
e.Graphics.FillRectangle(SystemBrushes.Window,e.Bounds);
}
e.Graphics.DrawString(listBox1.Items[e.Index].ToString(),e.Font,textBrush,e.Bounds.Left + 2,e.Bounds.Top);
}
}
private void listBox1_MouseMove(object sender,MouseEventArgs e)
{
int index = listBox1.IndexFromPoint(e.Location);
if (index != _MouseIndex)
{
_MouseIndex = index;
listBox1.Invalidate();
}
}
private void listBox1_MouseLeave(object sender,EventArgs e)
{
if (_MouseIndex > -1)
{
_MouseIndex = -1;
listBox1.Invalidate();
}
}
}
兄弟們,人家這花兩年時間解決的,應該有用,繼續再找找,又找到一篇洋文的:
https://stackoverflow.com/questions/1316027/listbox-drawitem-hotlight-state-in-the-ownerdraw-mode
It took me only two years to find the answer for you, but here it is:
The DrawItemState.HotLight only applies to owner drawn menus, not the listbox.
For the ListBox, you have to keep track of the item yourself:
看看,也是兩年,估計上面中文的從這個翻譯過來,
除了這倆,還真沒找到,
繼續擼代碼,果真管用,不過還是有問題,滑鼠滑快了,ListBox閃爍的厲害,
分析代碼 listBox1.Invalidate(); 這是重繪全部的,滑鼠滑過也就和本次選中和上次選中的有關系,
就刷這兩個Item就行,有了思路,擼代碼三連發:
private int lastIndex = -1;
private int mouseIndex = -1;
[Browsable(false)]
public int MouseIndex
{
get => mouseIndex;
set
{
if (mouseIndex != value)
{
if (lastIndex >= 0 && lastIndex != SelectedIndex)
{
OnDrawItem(new DrawItemEventArgs(this.CreateGraphics(), Font, GetItemRectangle(lastIndex), lastIndex, DrawItemState.Grayed));
}
mouseIndex = value;
if (mouseIndex >= 0 && mouseIndex != SelectedIndex)
{
OnDrawItem(new DrawItemEventArgs(this.CreateGraphics(), Font, GetItemRectangle(value), value, DrawItemState.HotLight));
}
lastIndex = mouseIndex;
}
}
}
protected override void onm ouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
MouseIndex = IndexFromPoint(e.Location);
}
protected override void onm ouseLeave(EventArgs e)
{
base.OnMouseLeave(e);
MouseIndex = -1;
}
其中 new DrawItemEventArgs(this.CreateGraphics(), Font, GetItemRectangle(value), value, DrawItemState.HotLight)
第一個引數Graphics,也找了一會兒,后來看這篇:
https://www.cnblogs.com/yuanyeguhong/archive/2013/09/20/3330606.html
其實就是Graphics物件的DrawString方法,而引數e中的Graphics是如何來的呢,
我們接著分析DrawItemEventArgs這個類,他既然是對listBox1某一項的屬性的打包,
那么我估計其中的Graphics物件就是由listBox1.creatgraphics而來的,
好了,到此我們就可以自定義重繪listbox某項的函式了,可任意呼叫的哦!
好了,至此,問題都已找到答案,再捋一下思路,把邏輯理順,擼代碼,除錯,OK!!!
主要代碼如下:
protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e);
BeforeDrawItem?.Invoke(this, Items, e);
if (Items.Count == 0)
{
return;
}
bool otherState = e.State == DrawItemState.Grayed || e.State == DrawItemState.HotLight;
if (!otherState)
{
e.DrawBackground();
}
if (e.Index < 0 || e.Index >= Items.Count)
{
return;
}
StringFormat sStringFormat = new StringFormat();
sStringFormat.LineAlignment = StringAlignment.Center;
bool isSelected = (e.State & DrawItemState.Selected) == DrawItemState.Selected;
Color backColor = isSelected ? ItemSelectBackColor : BackColor;
Color foreColor = isSelected ? ItemSelectForeColor : ForeColor;
Rectangle rect = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width - 1, e.Bounds.Height - 1);
if (!otherState)
{
e.Graphics.FillRectangle(BackColor, e.Bounds);
e.Graphics.FillRoundRectangle(backColor, rect, 5);
e.Graphics.DrawString(Items[e.Index].ToString(), e.Font, foreColor, e.Bounds, sStringFormat);
}
else
{
if (e.State == DrawItemState.Grayed)
{
backColor = BackColor;
foreColor = ForeColor;
}
if (e.State == DrawItemState.HotLight)
{
backColor = HoverColor;
foreColor = ForeColor;
}
e.Graphics.FillRectangle(BackColor, e.Bounds);
e.Graphics.FillRoundRectangle(backColor, rect, 5);
e.Graphics.DrawString(Items[e.Index].ToString(), e.Font, foreColor, e.Bounds, sStringFormat);
}
AfterDrawItem?.Invoke(this, Items, e);
}
看,DrawItemState.HotLight咱也給實作了,DrawItemState.Grayed 我是隨便選的狀態,區別于其他,
想看全部代碼,看我的開源專案吧,https://gitee.com/yhuse/SunnyUI ,哎,客官別走嘛,點個Star先,
原創文章,轉載請保留鏈接 Sunny's blog
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/33184.html
標籤:C#
上一篇:C#設計模式之訂閱發布模式
