1

Is there a way to create a shadow for a borderless form that doesn't flicker when the form is resized? Right now I'm using CreateParams.

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

But when the form is resized, the shadow part turns white, then back to a shadow, flickering. The rest of the form doesn't because I used this.DoubleBuffered = true;
Any help is appreciated, thanks!

Edit:
I resize the form by using SendMessage

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

dir is an int that varies depending on the direction I want to resize the form.

Blue0500
  • 715
  • 8
  • 16
  • 1
    `Is there a way to create a shadow for a borderless form that doesn't flicker when the form is resized?` - yes, it's called WPF. – Federico Berasategui Nov 27 '13 at 01:34
  • looks like your form is borderless and you customize the resizing behavior, that may matter and cause your problem. – King King Nov 27 '13 at 01:39
  • Could you clarify on `the shadow part turns white, then back to a shadow`? When does that happen? I mean does it happen whenever you resize any borders (left, top, right, bottom) or just top and left (then the flickering edge is bottom and right respectively). I've tried some custom resizing code and looks like that's the only problem (resizing top and left edge may cause a little flicker on the opposite edge) – King King Nov 27 '13 at 04:28
  • Yes, the shadow flickers when I resize from any border. – Blue0500 Nov 27 '13 at 05:55
  • @Blue0500: I answered it here:https://stackoverflow.com/questions/60913399/border-less-winform-form-shadow/60916421#60916421 Pls check if it helps you – D J Apr 01 '20 at 08:43

1 Answers1

1

I think your problem is caused by your implementation to support custom resizing using SendMessage as posted in your question. I've tried implementing the resizing using WndProc catching the message WM_NCHITTEST and returns according result to the mouse position. It looks like there is not any much flicker when you resize the top and left edge and no flicker at all for other edges. So I think you can try this code, it works for me:

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);
    }
}

Note that don't use your custom resizing with SendMessage, just the code above.

King King
  • 61,710
  • 16
  • 105
  • 130
  • Wow! Thanks, I wouldn't have thought to use WinProc. – Blue0500 Nov 27 '13 at 17:36
  • Hey, just realized that if I add a default statatement to the end of the switch, I could resize the form using m.Result = (IntPtr)0x2 – Blue0500 Nov 27 '13 at 17:40
  • @Blue0500 what happens with that? we don't process the default case, the default case corresponds to the case when your mouse is not over any edges or corners (it's just inside the client area). BTW, you may want to search more on `WM_NCHITTEST`, when a window receives this message, the DefWndProc will process and return some result called hittest code, this is used to determine some behaviors of mouse such as resizing, capturing, ... – King King Nov 27 '13 at 17:46
  • When I add this, I can move the form if the mouse on one of the edges. I can see how this would be a problem though when I start to add more controls. I'll learn more about messages and window procedures, its all very interesting – Blue0500 Nov 27 '13 at 17:57
  • Sorry there's a typo, I can move the form if the mouse is **not** on one of the edges – Blue0500 Nov 27 '13 at 18:04
  • @Blue0500 anyway that's not intention of my code, don't add that default case and it works OK for you. – King King Nov 27 '13 at 18:17