tjsmith tjsmith - 3 months ago 15
C# Question

Turn off 'Show window contents while dragging' setting while displaying my C# windows forms

There is a window display setting called 'Show window contents while dragging'.

http://www.thewindowsclub.com/disable-show-windows-contents-while-dragging

When this setting is turned on, if you drag a window the window will immediately repaint at the new position. If you resize a window, it will repaint the window for each new window size immediately, even if you are still holding down the mouse button.

When the setting is turned off, dragging or resizing the window simply shows an outline of the new window position or size until you release the mouse button and then it will paint the window at the new position or size.

I would like to display my forms in my C# WinForms application with 'Show window contents while dragging' setting turned off. However as this is an operating setting, I would only like this to be effective for when my forms are displayed regardless of what the setting is set to in the OS.

Is there a way to achieve this using some WinAPI calls to change the behavior specifically for my winforms?

If not, is there a way that I can change the setting programatically before my form is displayed and reset it after my form has closed? Would performing this change require admin rights (because I don't want that)?

Answer

The following code below will use the system setting of 'Show window content while dragging' for window re-positioning, while it will temporarily set it to off, while resizing the window and then set it back to the system setting.

This gives you flicker free form resizing in windows forms.

Since this property is a user setting that modifies the HKEY_CURRENT_USER\Control Panel\Desktop\DragFullWindows registry key, it should not require admin rights.

    [DllImport("user32.dll", EntryPoint = "SystemParametersInfo", CharSet = CharSet.Auto)]
    public static extern int GetSystemParametersInfo(int uAction, int uParam, out int lpvParam, int fuWinIni);

    [DllImport("user32.dll", EntryPoint = "SystemParametersInfo", CharSet = CharSet.Auto)]
    public static extern int SetSystemParametersInfo(int uAction, int uParam, int lpvParam, int fuWinIni);

    private const int SPI_GETDRAGFULLWINDOWS = 38;
    private const int SPI_SETDRAGFULLWINDOWS = 37;

    private const int WM_SYSCOMMAND = 0x0112;
    private const int SC_SIZE = 0xF000; 

    //change 'Show window content while dragging' to false while resizing
    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_SYSCOMMAND && (m.WParam.ToInt32() & 0xfff0) == SC_SIZE)
        {
            int isDragFullWindow;
            GetSystemParametersInfo(SPI_GETDRAGFULLWINDOWS, 0, out isDragFullWindow, 0);

            if (isDragFullWindow != 0)
                SetSystemParametersInfo(SPI_SETDRAGFULLWINDOWS, 0, 0, 0);

            base.WndProc(ref m);

            if (isDragFullWindow != 0)
                SetSystemParametersInfo(SPI_SETDRAGFULLWINDOWS, 1, 0, 0);
        }
        else
        {
            base.WndProc(ref m);
        }
    } 

    //reduce control flickering and black stripes when window is resized
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x02000000;  // Turn on WS_EX_COMPOSITED
            return cp;
        }
    }