0

ListBox から継承されたカスタムの複数行 ListBox コントロールを作成しました。フォームでは、ListBox の位置は、ElementHost でホストされている WPF の丸みを帯びた透明なパネルの上にあります。今、私が欲しいのは、ListBox の背景色を透明にすることです。明らかに、これは Winforms では許可されていません。ListBox を透明にすることはできません。それから、私はいくつかのことを試しましたが、常に問題があります。

私が達成したいのはこれです:

ここに画像の説明を入力

ご覧のとおり、これは完全に機能しますが、実際には 2 つの問題があります。

最初に取得するのは、アイテムを選択したときです。文字がかなり醜くなりました。次の画像と最初の画像を見比べてみてください。それらのすべてが選択されているため、それらのすべてが醜いように見えることがわかります。

ここに画像の説明を入力

私が抱えている2番目の問題は、ListBoxを上下にスクロールするときです。透明な色が消えて、黒い色になります。

ここに画像の説明を入力

フォームのスクロール可能なパネルでこの問題が発生したことを覚えています。パネルは透明で、それを解決する方法は、パネルの Scroll イベントで Invalidate() メソッドを呼び出すことでした。しかし、ListBox にはそのイベントがありません。

また、スクロールバーを非表示にしたいが、スクロール可能にしたい。

私が行ったことを確認できるように、CustomListBox コードを添付します。単純な複数行の ListBox も必要な場合は、自由に使用できます。

念のため、ListBox を透明に設定するために使用した方法は、CreateParams をオーバーライドすることでした。

public class MultiLineListBox : System.Windows.Forms.ListBox { public MultiLineListBox() { 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 に設定することで機能しました。しかし、他の解決策と同じ問題を抱えているだけでなく、テキストが表示されなかったため、さらに望ましくなかったので、最初の解決策に固執しました。

誰かが私を助けてくれることを願っています!

4

1 に答える 1

2

あなたはこれを試すことができます...

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 で使用しました。

于 2013-03-04T17:28:35.483 に答える