C# 无边框窗体边框阴影效果的简单实现

针对“C# 无边框窗体边框阴影效果的简单实现”,以下是完整攻略:

标题

在文章开头设置一个一级标题,表示文章的主要内容。

# C# 无边框窗体边框阴影效果的简单实现

需求

在介绍实现方法之前,需要确定要实现的需求,指明要实现的功能。

无边框窗体边框阴影效果可以提升软件的美观度和用户体验度,所以是实现目标之一。

实现步骤

  1. 自定义窗口样式

首先需要将窗口的边框去掉,然后再设置窗口样式和位置。其中,窗口样式使用 WS_POPUP,窗口位置使用 SetWindowPos 实现。

```csharp
int WS_POPUP = 0x800000;
int WS_VISIBLE = 0x10000000;
int SWP_NOSIZE = 0x0001;
int SWP_NOMOVE = 0x0002;
int SWP_NOZORDER = 0x0004;
int SWP_FRAMECHANGED = 0x0020;

protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.Style = WS_POPUP | WS_VISIBLE;
return cp;
}
}

public void SetShadowStyle()
{
SetWindowPos(this.Handle, HWND_TOPMOST, -20, -20, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER);
}

[DllImport("user32.dll")]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
```

  1. 绘制阴影

窗口样式设置完成后,需要绘制窗口的阴影效果。可以使用 DrawShadow 方法实现。

```csharp
protected override void OnPaint(PaintEventArgs e)
{
DrawShadow(e.Graphics);
}

public void DrawShadow(Graphics g)
{
g.SmoothingMode = SmoothingMode.AntiAlias;

   using (GraphicsPath graphicsPath = new GraphicsPath())
   {
       graphicsPath.AddLines(new Point[] { new Point(30, 0), new Point(Width - 35, 0), new Point(Width - 1, 30),
       new Point(Width - 1, Height - 35), new Point(Width - 35, Height - 1), new Point(30, Height - 1),
       new Point(0, Height - 35), new Point(0, 30), new Point(30, 0) });

       using (PathGradientBrush pathGradientBrush = new PathGradientBrush(graphicsPath))
       {
           pathGradientBrush.WrapMode = WrapMode.Clamp;
           pathGradientBrush.CenterPoint = new PointF(-20, -20);

           ColorBlend colorBlend = new ColorBlend(3);
           colorBlend.Positions[0] = 0.0f;
           colorBlend.Colors[0] = Color.FromArgb(0, 0, 0, 0);
           colorBlend.Positions[1] = 0.1f;
           colorBlend.Colors[1] = Color.FromArgb(80, 0, 0, 0);
           colorBlend.Positions[2] = 1.0f;
           colorBlend.Colors[2] = Color.FromArgb(80, 0, 0, 0);
           pathGradientBrush.InterpolationColors = colorBlend;

           Blend blend = new Blend
           {
               Factors = new float[] { 0f, 0.8f, 1f },
               Positions = new float[] { 0f, 0.1f, 1f }
           };
           pathGradientBrush.Blend = blend;

           g.FillPath(pathGradientBrush, graphicsPath);

       }
   }

}
```

  1. 事件处理

由于自定义的窗口不能进行拖动操作,需要通过事件处理进行实现。

```csharp
private Point offset;

private void TitleBar_MouseDown(object sender, MouseEventArgs e)
{
offset = new Point(e.X, e.Y);
}

private void TitleBar_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Point currentScreenPos = PointToScreen(e.Location);
Location = new Point(currentScreenPos.X - offset.X, currentScreenPos.Y - offset.Y);
}
}
```

  1. 完整代码

```csharp
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace CSharpShadowForm
{
public partial class ShadowForm : Form
{
int WS_POPUP = 0x800000;
int WS_VISIBLE = 0x10000000;
int SWP_NOSIZE = 0x0001;
int SWP_NOMOVE = 0x0002;
int SWP_NOZORDER = 0x0004;
int SWP_FRAMECHANGED = 0x0020;

       protected override CreateParams CreateParams
       {
           get
           {
               CreateParams cp = base.CreateParams;
               cp.Style = WS_POPUP | WS_VISIBLE;
               return cp;
           }
       }

       public void SetShadowStyle()
       {
           SetWindowPos(this.Handle, HWND_TOPMOST, -20, -20, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER);
       }

       [DllImport("user32.dll")]
       static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

       static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);

       public ShadowForm(Form targetForm)
       {
           InitializeComponent();
           Init(targetForm);
       }

       private void Init(Form targetForm)
       {
           Width = targetForm.Width + 60;
           Height = targetForm.Height + 60;

           TopLevel = true;
           TopMost = true;
           FormBorderStyle = FormBorderStyle.None;
           BackColor = Color.Black;
           Opacity = 0.24;

           SetShadowStyle();

           Location = new Point(targetForm.Location.X - 30, targetForm.Location.Y - 30);
           targetForm.LocationChanged += new System.EventHandler(TargetForm_LocationChanged);
           TitleBar.MouseDown += new MouseEventHandler(TitleBar_MouseDown);
           TitleBar.MouseMove += new MouseEventHandler(TitleBar_MouseMove);
       }

       private void TitleBar_MouseDown(object sender, MouseEventArgs e)
       {
           offset = new Point(e.X, e.Y);
       }

       private void TitleBar_MouseMove(object sender, MouseEventArgs e)
       {
           if (e.Button == MouseButtons.Left)
           {
               Point currentScreenPos = PointToScreen(e.Location);
               Location = new Point(currentScreenPos.X - offset.X, currentScreenPos.Y - offset.Y);
           }
       }

       private Point offset;

       private void TargetForm_LocationChanged(object sender, System.EventArgs e)
       {
           Location = new Point(Owner.Location.X - 30, Owner.Location.Y - 30);
       }

       protected override void OnPaint(PaintEventArgs e)
       {
           DrawShadow(e.Graphics);
       }

       public void DrawShadow(Graphics g)
       {
           g.SmoothingMode = SmoothingMode.AntiAlias;

           using (GraphicsPath graphicsPath = new GraphicsPath())
           {
               graphicsPath.AddLines(new Point[] { new Point(30, 0), new Point(Width - 35, 0), new Point(Width - 1, 30), new Point(Width - 1, Height - 35), 
               new Point(Width - 35, Height - 1), new Point(30, Height - 1), new Point(0, Height - 35), new Point(0, 30), new Point(30, 0) });

               using (PathGradientBrush pathGradientBrush = new PathGradientBrush(graphicsPath))
               {
                   pathGradientBrush.WrapMode = WrapMode.Clamp;
                   pathGradientBrush.CenterPoint = new PointF(-20, -20);

                   ColorBlend colorBlend = new ColorBlend(3);
                   colorBlend.Positions[0] = 0.0f;
                   colorBlend.Colors[0] = Color.FromArgb(0, 0, 0, 0);
                   colorBlend.Positions[1] = 0.1f;
                   colorBlend.Colors[1] = Color.FromArgb(80, 0, 0, 0);
                   colorBlend.Positions[2] = 1.0f;
                   colorBlend.Colors[2] = Color.FromArgb(80, 0, 0, 0);
                   pathGradientBrush.InterpolationColors = colorBlend;

                   Blend blend = new Blend
                   {
                       Factors = new float[] { 0f, 0.8f, 1f },
                       Positions = new float[] { 0f, 0.1f, 1f }
                   };
                   pathGradientBrush.Blend = blend;

                   g.FillPath(pathGradientBrush, graphicsPath);

               }
           }
       }
   }

}
```

示例说明

以下是两条示例说明:

示例一

如果想要在窗口加载完成后添加阴影效果,可以使用以下代码。

private void Form_Load(object sender, EventArgs e)
{
    ShadowForm shadowForm = new ShadowForm(this);
    shadowForm.Show();
}

示例二

如果需要在拖动窗口时同时拖动阴影效果,可以在 TitleBar_MouseMove 方法中添加以下代码。

private void TitleBar_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        Point currentScreenPos = PointToScreen(e.Location);
        ShadowForm.Location = new Point(currentScreenPos.X - offset.X - 30, currentScreenPos.Y - offset.Y - 30);
        Location = new Point(currentScreenPos.X - offset.X, currentScreenPos.Y - offset.Y);
    }
}

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# 无边框窗体边框阴影效果的简单实现 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • C# 常量 结构体 委托

    常量 const double PI = 3.1415926; 常量名命名一般使用大写字母 枚举类型 开发一个游戏,游戏角色有法师(Mage)、射手(Archer)、刺客(Assassin)、坦克(Tank)、铺助(Support)、战士(Warrior),等不同类型。 ❓如何存储游戏角色 使用int类型 :创建一套规则,提前为各个类型角色绑定一个数字标识 …

    C# 2023年5月2日
    00
  • C#中实现网段扫描的代码

    为了实现C#中的网段扫描,你需要使用Socket类以及System.Net.NetworkInformation命名空间中的一些类和方法。以下是完整的攻略: 首先导入所需的命名空间: using System; using System.Net; using System.Net.NetworkInformation; using System.Net.So…

    C# 2023年5月31日
    00
  • ASP.NET 多附件上传实现代码

    介绍ASP.NET多附件上传的完整攻略如下: 1. 需求分析与准备工作 首先我们需要明确自己的需求,了解自己要实现的是什么样的多附件上传操作。确定需求后,我们需要准备工作,主要包括: 确定上传文件大小:根据需求,确定上传文件的最大大小,避免上传过大的文件导致服务器崩溃。 创建上传文件夹:我们需要在服务器上创建一个专门存储上传文件的文件夹,以便于整理和管理上传…

    C# 2023年5月31日
    00
  • C#中Quartz的使用

    安装 NuGet 包:在 Visual Studio 中打开项目,右键单击项目名称,选择“管理 NuGet 包”,搜索“Quartz”并安装。 创建作业:创建一个实现了 IJob 接口的类,该接口包含一个 Execute 方法,该方法将在作业运行时调用。例如: public class MyJob : IJob { public Task Execute(I…

    C# 2023年4月17日
    00
  • 基于C# winform实现图片上传功能的方法

    下面是“基于C# Winform实现图片上传功能的方法”的完整攻略: 一、准备工作 首先,我们需要将Winform应用程序的工具箱中添加一个OpenFileDialog控件,用于选择要上传的图片;还需要添加一个PictureBox控件,用于展示已经选择好的图片。 二、上传图片的流程 获得待上传的图片的本地路径 使用OpenFileDialog控件的ShowD…

    C# 2023年6月2日
    00
  • C#资源释放方法实例分析

    C#资源释放方法实例分析 在使用C#编写程序时,资源释放问题是一个非常重要的问题。如果不恰当地处理资源释放,可能会导致内存泄漏等问题,影响程序性能和稳定性。本文将详细介绍C#中的资源释放方法,以及如何在代码中进行实际应用。 1. 资源释放的方法 C#中的资源释放主要分为两种方式:手动释放和自动释放。 1.1 手动释放 手动释放是指程序员在编写代码时,手动调用…

    C# 2023年5月15日
    00
  • C#从字符串中指定位置移除子字符串的方法

    请允许我给出一份详细的攻略来回答您的问题。 问题分析 在C#中,我们可以轻松地使用String类型的Remove方法来从字符串中删除指定的子字符串。但是有一些时候,我们需要从字符串的指定位置开始移除子字符串,这些子字符串可能会出现多次,或者不止一个。 这就需要我们使用Substring方法来截取字符串,并使用Replace方法来将需要移除的子字符串替换为空字…

    C# 2023年6月8日
    00
  • C#记一次http协议multipart/form-data的boundary问题

    下面是“C#记一次http协议multipart/form-data的boundary问题”的完整攻略。 1. 问题背景 在使用 C# 发送 HTTP 请求时,如果请求体采用 multipart/form-data 格式,则需要在请求头和请求体中添加对应 “Content-Type” 和 “Boundary”。其中 “Boundary” 是分割每个 form…

    C# 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部