【问题标题】:Custom ListBox with transparent backcolor issue具有透明背景色问题的自定义 ListBox
【发布时间】:2013-03-05 01:28:35
【问题描述】:

我创建了一个继承自 ListBox 的自定义多行 ListBox 控件。在表单中,ListBox 位置位于 ElementHost 中托管的 WPF 圆形透明面板上方。现在,我想要的是 ListBox 背景色是透明的。显然,这在 Winforms 中是不允许的,ListBox 不能是透明的。然后,我尝试了一些东西,但总是有问题。

我想要实现的是:

如您所见,这非常有效,但实际上我遇到了两个问题。

我首先得到的是当我选择一个项目时。字母变得非常难看。只需将下一张图片与第一张图片进行比较。你可以看到它们看起来都很丑,因为它们都被选中了。

我遇到的第二个问题是当我向下/向上滚动 ListBox 时。透明的颜色消失了,我得到了黑色。

我记得在表单中使用可滚动面板时遇到了这个问题。面板是透明的,解决方法是在面板滚动事件中调用 Invalidate() 方法。但我在 ListBox 中没有那个事件。

另外,我想隐藏滚动条但可以滚动。

我附上了 CustomListBox 代码,这样你就可以看到我做了什么。如果你也想要一个简单的多行 ListBox,你可以随意使用它。

以防万一,我将 ListBox 设置为透明的方式是重写 CreateParams。

公共类 MultiLineListBox : System.Windows.Forms.ListBox { 公共多线列表框() { this.DrawMode = DrawMode.OwnerDrawVariable; this.ScrollAlwaysVisible = true; }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x20; // WS_EX_TRANSPARENT
            return cp;
        }
    }

    protected override void OnMeasureItem(MeasureItemEventArgs e)
    {
        if(Site!=null)
            return;
        if(e.Index > -1)
        {
            string s = Items[e.Index].ToString();
            SizeF sf = e.Graphics.MeasureString(s,Font,Width);
            int htex = (e.Index==0) ? 15 : 10;
            e.ItemHeight = (int)sf.Height + htex;           
            e.ItemWidth = Width;
        }
    }

    protected override void OnDrawItem(DrawItemEventArgs e)
    {
        if(Site!=null)
            return;
        if(e.Index > -1)
        {
            string s = Items[e.Index].ToString();                           

            if((e.State & DrawItemState.Focus)==0)
            {
                e.Graphics.DrawString(s,Font,new SolidBrush(Color.White),e.Bounds);             
                e.Graphics.DrawRectangle(new Pen(Color.FromArgb(255, 26, 36, 41)),e.Bounds);                
            }
            else
            {
                e.Graphics.DrawRectangle(new Pen(Color.FromArgb(255, 0, 185, 57)), e.Bounds);
                //e.Graphics.DrawString(s,Font,new SolidBrush(Color.FromArgb(255, 0, 161, 47)),e.Bounds);
            }
        }
    }
}   

哦,我差点忘了。我尝试覆盖 OnPaintBackGround(),它通过将 SetStyle 设置为 userPaint 来工作。但是更不可取,因为我不仅遇到了与其他解决方案相同的问题,而且没有显示文本,所以我坚持第一个解决方案。

希望有人能帮帮我!

【问题讨论】:

  • winforms 不支持这些。您已经在使用ElementHost,为什么不直接创建一个带有适当ItemTemplate 和带有透明胶片的漂亮Style 的WPF ListBox?...您需要0 行C# 代码和大约10 到20 行XAML为了在 WPF 中做到这一点。
  • @HighCore 是否可以在 Winforms 中做很多事情。只是更复杂。我知道我可以在 WPF 上更轻松地做到这一点,但我对此知之甚少。列表框将为每个项目提供一个上下文菜单。所有这些要求都让我远离 WPF。
  • ContextMenu 只是List<ICommand> 的图形表示。我不明白这有多复杂。 WPF 中的一切都更容易,而且性能也更好。当你完成这个 winforms 应用程序时,你会意识到它由于性能不佳而无法使用,并且无论如何都必须完全在 WPF 中重新做。
  • 另外,我对"technology or framework ABC supports XYZ" 的想法是,您可以在正常时间内使用 ABC 实现 XYZ,而无需求助于一堆 HACKS(例如必须调用非托管代码只是为了做一些事情UI相关的东西)。因此,winforms 不支持任何这些东西。国际海事组织。
  • @HighCore Winform 很慢,它与 Interop with WPF 无关。正如我告诉你的,我对 WPF 知之甚少。这就是我使用 Winforms 的原因。因为我知道。该应用程序几乎完成。我无法将所有这些都迁移到我不掌握的技术中。

标签: c# winforms listbox custom-controls transparent


【解决方案1】:

你可以试试这个……

protected override void OnPaintBackground(PaintEventArgs pevent)
{
    IntPtr hdc = pevent.Graphics.GetHdc();
    Rectangle rect = this.ClientRectangle;
    NativeMethods.DrawThemeParentBackground(this.Handle, hdc, ref rect);
    pevent.Graphics.ReleaseHdc(hdc);
}


internal static class NativeMethods
{
    [DllImport("uxtheme", ExactSpelling = true)]
    public extern static Int32 DrawThemeParentBackground(IntPtr hWnd, IntPtr hdc, ref Rectangle pRect);
}

当我需要为不支持它的控件绘制透明背景颜色时,它对我有用。我将它与 TabControl 一起使用。

【讨论】:

  • 很好.. 必须求助于 WinAPI 来做相当于 WPF 中的<ListBox Background="Transparent"/> 的事情。
  • 我会在几分钟内试试这个。以防万一,这在滚动时是否正常工作?
  • @Andres 你还想要 WPF 解决方案吗?我可以帮助您创建 ItemTemplateViewModel 及其 Commands 以​​用作 ContextMenuListBox 样式(如果需要)。
  • @HighCore 谢谢,但我认为如果我坚持使用一种技术,该应用程序将更容易维护。我只是将 WPF 用于美观的控件,因为几个月前我才知道该技术。如果这不能在 wiforms 中实现,我只会让背景保持黑色。
  • @Andres UserPaint、AllPaintInWmPaint、ResizeRedraw 和 OptimizedDoubleBuffer 是 ControlStyles 枚举的成员。在开始绘制任何东西之前,通常在构造函数/初始化方法中使用 SetStyle() 设置它们。至于 Invalidate(this.ClientRectangle);更新();
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多