【问题标题】:Flickering Shadow on Borderless Form无边界表格上闪烁的阴影
【发布时间】:2013-11-27 01:32:01
【问题描述】:

有没有办法为无边框表单创建阴影,当表单调整大小时不会闪烁?现在我正在使用 CreateParams。

protected override CreateParams CreateParams
{
    get
    {
        const int CS_DROPSHADOW = 0x20000;
        CreateParams cp = base.CreateParams;
        cp.ClassStyle |= CS_DROPSHADOW;
        return cp;
    }
}

但是当窗体调整大小时,阴影部分变成白色,然后又变回阴影,闪烁。表格的其余部分不是因为我使用了this.DoubleBuffered = true;
感谢您提供任何帮助,谢谢!

编辑
我使用 SendMessage

调整表单大小

private const int WM_NCLBUTTONDOWN = 0xa1;
SendMessage(handle, WM_NCLBUTTONDOWN, dir, 0);

dir 是一个 int,取决于我要调整表单大小的方向。

【问题讨论】:

  • Is there a way to create a shadow for a borderless form that doesn't flicker when the form is resized? - 是的,它叫做 WPF。
  • 看起来您的表单是无边界的,并且您自定义了调整大小的行为,这可能很重要并会导致您的问题。
  • 你能澄清一下the shadow part turns white, then back to a shadow吗?什么时候发生?我的意思是,每当您调整任何边框(左、上、右、下)或只是上和左(然后闪烁的边缘分别是下和右)时,都会发生这种情况。我尝试了一些自定义调整大小的代码,看起来这是唯一的问题(调整顶部和左侧边缘的大小可能会导致对边有点闪烁)
  • 是的,当我从任何边框调整大小时,阴影都会闪烁。
  • @Blue0500:我在这里回答了:stackoverflow.com/questions/60913399/… 请检查它是否对您有帮助

标签: c# winforms shadow flicker


【解决方案1】:

我认为您的问题是由于您的实施支持使用 SendMessage 在您的问题中发布的自定义调整大小。我尝试使用WndProc 捕获消息WM_NCHITTEST 来实现调整大小,并根据鼠标位置返回结果。当您调整顶部和左侧边缘的大小时,看起来没有太多闪烁,而其他边缘则完全没有闪烁。所以我想你可以试试这个代码,它对我有用:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        DoubleBuffered = true;
        FormBorderStyle = FormBorderStyle.None;
    }
    protected override CreateParams CreateParams
    {
        get
        {
            const int CS_DROPSHADOW = 0x20000;
            CreateParams cp = base.CreateParams;
            cp.ClassStyle |= CS_DROPSHADOW;
            return cp;
        }
    }
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == 0x84) //WM_NCHITTEST = 0x84
        {
            int x = m.LParam.ToInt32() & 0xffff;
            int y = m.LParam.ToInt32() >> 16;
            int codex, codey;
            Point p = PointToClient(new Point(x, y));
            codey = p.Y < 5 ? 2 : p.Y > ClientSize.Height - 5 ? 1 : 0;
            codex = p.X < 5 ? 2 : p.X > ClientSize.Width - 5 ? 1 : 0;
            switch (codex + (codey<<2))
            {
                case 10://Top-Left
                    m.Result = (IntPtr)13;
                    return;
                case 8://Top
                    m.Result = (IntPtr)12;
                    return;
                case 9://Top-Right
                    m.Result = (IntPtr)14;
                    return;
                case 2://Left
                    m.Result = (IntPtr)10;
                    return;
                case 1://Right
                    m.Result = (IntPtr)11;
                    return;
                case 6://Bottom-Left
                    m.Result = (IntPtr)16;
                    return;
                case 4://Bottom
                    m.Result = (IntPtr)15;
                    return;
                case 5://Bottom-Right;
                    m.Result = (IntPtr)17;
                    return;
            }                
        }
        base.WndProc(ref m);
    }
}

请注意,不要使用 SendMessage 的自定义调整大小,只需使用上面的代码即可。

【讨论】:

  • 哇!谢谢,我没想过要使用 WinProc。
  • 嘿,刚刚意识到如果我在开关的末尾添加一个默认语句,我可以使用 m.Result = (IntPtr)0x2 调整表单的大小
  • @Blue0500 会发生什么?我们不处理默认情况,默认情况对应于您的鼠标不在任何边缘或角落(它只是在客户区域内)的情况。顺便说一句,您可能想在WM_NCHITTEST 上搜索更多内容,当窗口收到此消息时,DefWndProc 将处理并返回一些称为 hittest 代码的结果,用于确定鼠标的某些行为,例如调整大小,捕获,...
  • 当我添加这个时,如果鼠标在其中一个边缘上,我可以移动表单。当我开始添加更多控件时,我可以看到这将是一个问题。我会学习更多关于消息和窗口过程的知识,它们都很有趣
  • 抱歉打错了,如果鼠标不在在其中一条边上,我可以移动表单
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-03
  • 2018-04-20
  • 1970-01-01
  • 1970-01-01
  • 2014-04-30
  • 2018-11-06
  • 1970-01-01
相关资源
最近更新 更多