Мерцающая тень на форме без полей

Есть ли способ создать тень для формы без полей, которая не мерцает при изменении размера формы? Сейчас я использую 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 - это целое число, которое меняется в зависимости от направления, в котором я хочу изменить размер формы.


person Blue0500    schedule 27.11.2013    source источник
comment
Is there a way to create a shadow for a borderless form that doesn't flicker when the form is resized? - да, это называется WPF.   -  person Federico Berasategui    schedule 27.11.2013
comment
похоже, что ваша форма без полей, и вы настраиваете поведение изменения размера, что может иметь значение и вызывать вашу проблему.   -  person King King    schedule 27.11.2013
comment
Не могли бы вы пояснить the shadow part turns white, then back to a shadow? Когда это случится? Я имею в виду, происходит ли это всякий раз, когда вы изменяете размер каких-либо границ (слева, сверху, справа, снизу) или только сверху и слева (тогда мерцающий край внизу и справа соответственно). Я пробовал код изменения размера, и похоже, что это единственная проблема (изменение размера верхнего и левого края может вызвать небольшое мерцание на противоположном крае)   -  person King King    schedule 27.11.2013
comment
Да, тень мерцает при изменении размера любой границы.   -  person Blue0500    schedule 27.11.2013
comment
@ Blue0500: Я ответил здесь: stackoverflow .com / questions / 60913399 /. Пожалуйста, проверьте, поможет ли это вам.   -  person D J    schedule 01.04.2020


Ответы (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, только код выше.

person King King    schedule 27.11.2013
comment
Вау! Спасибо, я бы не подумал использовать WinProc. - person Blue0500; 27.11.2013
comment
Эй, только что понял, что если я добавлю статус по умолчанию в конец переключателя, я могу изменить размер формы, используя m.Result = (IntPtr) 0x2 - person Blue0500; 27.11.2013
comment
@ Blue0500 что с этим происходит? мы не обрабатываем случай по умолчанию, случай по умолчанию соответствует случаю, когда указатель мыши не находится над краями или углами (он находится внутри клиентской области). Кстати, вы можете захотеть поискать больше на WM_NCHITTEST, когда окно получает это сообщение, DefWndProc обработает и вернет некоторый результат, называемый тестовым кодом, он используется для определения некоторых действий мыши, таких как изменение размера, захват, ... - person King King; 27.11.2013
comment
Когда я добавляю это, я могу перемещать форму, если наведу указатель мыши на один из краев. Я понимаю, в чем проблема, когда начинаю добавлять элементы управления. Узнаю больше о сообщениях и оконных процедурах, все это очень интересно - person Blue0500; 27.11.2013
comment
Извините за опечатку, я могу переместить форму, если мышь не на одном из краев - person Blue0500; 27.11.2013
comment
@ Blue0500 в любом случае это не намерение моего кода, не добавляйте этот случай по умолчанию, и он работает нормально для вас. - person King King; 27.11.2013