21

コントロールにドロップシャドウを追加する方法はありますか?

この機能を備えたコントロールはありますか?

4

5 に答える 5

33

CreateParams次のようにプロパティを上書きする必要があります。

private const int CS_DROPSHADOW = 0x00020000;
protected override CreateParams CreateParams
{
    get
    {
        // add the drop shadow flag for automatically drawing
        // a drop shadow around the form
        CreateParams cp = base.CreateParams;
        cp.ClassStyle |= CS_DROPSHADOW;
        return cp;
    }
}
于 2010-03-17T15:31:49.760 に答える
14

この質問は6年前からあり、答えが必要です。これを行う必要がある人は誰でも、私のソリューションから任意のコントロールセットの答えを推定できることを願っています。私はパネルを持っていて、すべての子コントロールの下にドロップシャドウを描きたいと思っていました-この場合は1つ以上のパネルです(ただし、このソリューションは、コードを少し変更するだけで、他のコントロールタイプにも適しています)。

コントロールのドロップシャドウは、そのコントロールのコンテナーの表面に描画する必要があるため、コンテナーのPaint()イベントに関数を追加することから始めます。

Container.Paint += dropShadow;

dropShadow()は次のようになります。

    private void dropShadow(object sender, PaintEventArgs e)
    {
        Panel panel = (Panel)sender;
        Color[] shadow = new Color[3];
        shadow[0] = Color.FromArgb(181, 181, 181);
        shadow[1] = Color.FromArgb(195, 195, 195);
        shadow[2] = Color.FromArgb(211, 211, 211);
        Pen pen = new Pen(shadow[0]);
        using (pen)
        {
            foreach (Panel p in panel.Controls.OfType<Panel>())
            {
                Point pt = p.Location;
                pt.Y += p.Height;
                for (var sp = 0; sp < 3; sp++)
                {
                    pen.Color = shadow[sp];
                    e.Graphics.DrawLine(pen, pt.X, pt.Y, pt.X + p.Width - 1, pt.Y);
                    pt.Y++;
                }
            }
        }
    }

明らかに、コンテナのコレクションから別のコントロールタイプを選択でき、いくつかの小さな調整で影の色と深さを変えることができます。

于 2016-03-22T10:42:42.397 に答える
3

一番上の答えは実際には影を生成しますが、私はいくつかの理由で個人的にそれに満足していませんでした:

  • 長方形に対してのみ機能します(もちろん、WinFormsコントロールはすべて長方形ですが、他の場合にこれを使用することもできます)
  • さらに重要なのは、スムーズではないということです。他のプログラムの他の影ほど自然には見えません。
  • 最後に、構成するのは少し面倒です。

それで、これらすべてのことのために、私は自分のプロジェクトのために自分自身を書くことになり、ここでそれを共有したいと思いました:

public partial class Form1 : Form
{
    List<Control> shadowControls = new List<Control>();
    Bitmap shadowBmp = null;
    public Form1()
    {
        InitializeComponent();
        shadowControls.Add(panel1);
        this.Refresh();
    }

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        if (shadowBmp == null || shadowBmp.Size != this.Size)
        {
            shadowBmp?.Dispose();
            shadowBmp = new Bitmap(this.Width, this.Height, PixelFormat.Format32bppArgb);
        }
        foreach (Control control in shadowControls)
        {
            using (GraphicsPath gp = new GraphicsPath())
            {
                gp.AddRectangle(new Rectangle(control.Location.X, control.Location.Y, control.Size.Width, control.Size.Height));
                DrawShadowSmooth(gp, 100, 60, shadowBmp);
            }
            e.Graphics.DrawImage(shadowBmp, new Point(0, 0));
        }
    }
    private static void DrawShadowSmooth(GraphicsPath gp, int intensity, int radius, Bitmap dest)
    {
        using (Graphics g = Graphics.FromImage(dest))
        {
            g.Clear(Color.Transparent);
            g.CompositingMode = CompositingMode.SourceCopy;
            double alpha = 0;
            double astep = 0;
            double astepstep = (double)intensity / radius / (radius / 2D);
            for (int thickness = radius; thickness > 0; thickness--)
            {
                using (Pen p = new Pen(Color.FromArgb((int)alpha, 0, 0, 0), thickness))
                {
                    p.LineJoin = LineJoin.Round;
                    g.DrawPath(p, gp);
                }
                alpha += astep;
                astep += astepstep;
            }
        }
    }
}

この実装では、に追加されたすべてのコントロールshadowControlsが滑らかな影でペイントされます。シャドウを生成する主な関数は。を使用するため、非長方形の形状に対してこれを実装できるはずですGraphicsPath。フォームに描画する前に、シャドウを別のビットマップに描画することが重要であることに注意してください。これは、メイン関数が機能するための合成モードを必要とするためSourceCopyです。つまり、最初に別のサーフェスに描画しない場合、シャドウの背後にあるものは完全になります。置き換えられ、透明度の側面は役に立たない。私は10歳の質問に答えようとしていますが、うまくいけば、これは誰かを助けるでしょう!

于 2020-06-16T02:16:08.213 に答える
2

WPFには、代わりにそれを使用するように拡張できる場合がありますが、GDI +の機能が制限されているため、Windowsフォームに代替手段があるとは思いません。

于 2010-03-17T15:27:22.717 に答える
0

これは物議を醸す意見です、あなたはコードなしでそれをします。メインパネルの境界線スタイルを固定シングルに設定します。その下に3つのパネルを作成し、各パネルをすべての方向に1ピクセル大きくします。3つのパネルはそれぞれ明るい灰色の色合いです。完璧ではありませんが、安くて簡単です。

疑似シャドウ付きパネル

于 2021-11-10T03:11:52.087 に答える