최대화 한번에 그리고, 최소화 했다가 창 활성화때 다시 그려지는 현상 제거 방법

아무리 검색해도 정확한 키워드를 몰라서 찾지 못하는 것 같습니다.

WindowsState가 Nomal에서 Maximized가 될 때, 다시 그려지는데 모든 컨트롤이 한번씩 그려지게 되서, 이걸 한번에 그리고 싶은데 방법이 있을까요?
suspendLayout, ResumeLayout 사용도 해봤으나 호출 시점 문제인지 개선이 안됩니다.

그리고 창을 최소화 했다가, 다시 열때 모든 컨트롤이 깜빡이면서 다시 그려지는데 깜빡임을 제거하는 방법이 있을까요?

protected override CreateParams CreateParams {
  get {
    var parms = base.CreateParams;
    parms.Style &= ~0x02000000;  // Turn off WS_CLIPCHILDREN
    return parms;
  }
}

이 코드를 사용하면 깜빡임이 줄어드는 것처럼 보이지만 창 크기 변경 시 깜빡이고 그려지지 않는 경우가 발생합니다.

Winform 근본적인 문제로 개선 할 수 없는것인지? 아니면 개선을 할 수 있으나 일부를 감수해야하는 것이 있는지 알고싶습니다.

며칠째 찾아보고 적용해서 해보는데 해결 방법이 보이지 않네요…

깜빡임을 해결하는 방법 중의 하나가 이중 버퍼링을 활성화 하는 거에요.

좀 더 적극적인 도움이 필요하면 실행되는 샘플을 공유해주세요.

1개의 좋아요

더블버퍼링은 이미 적용되어 있으나 창 전환에선 여전히 발생합니다

FormBorderStyle = FormBorderStyle.None;

사용의 경우 aero 효과가 제거되면서 문제가 발생하는 것으로 보입니다.
방법을 더 찾아보고 있습니다.

GitHub - mganss/BorderlessForm: 사용자 지정 창 데코레이션 컨트롤이 있는 Windows Forms의 테두리 없는 창

소스를 참고하여 해결하였습니다.

1개의 좋아요

해결 하신 코드 부분이 어디인지 혹시 알 수 있을까요?

100% 해결된 것은 아닙니다. 다만 기존 보다는 좋아졌어요

스타일을 사이즈 변경이 가능하도록 적용 하고

this.FormBorderStyle = FormBorderStyle.Sizable;

아래의 코드를 적용 했습니다.
확인된 코드 이외에 크기 조정 가능한 코드도 추가했습니다.

#region Override

    protected override void WndProc(ref Message m)
    {
        const int RESIZE_HANDLE_SIZE = 10;

        switch (m.Msg)
        {
            case (int)WindowMessages.WM_NCCALCSIZE:
                    var r = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
                    var max = MinMaxState == FormWindowState.Maximized;

                    if (max)
                    {
                        var x = NativeMethods.GetSystemMetrics(NativeConstants.SM_CXSIZEFRAME);
                        var y = NativeMethods.GetSystemMetrics(NativeConstants.SM_CYSIZEFRAME);
                        var p = NativeMethods.GetSystemMetrics(NativeConstants.SM_CXPADDEDBORDER);
                        var w = x + p;
                        var h = y + p;

                        r.left += w;
                        r.top += h;
                        r.right -= w;
                        r.bottom -= h;

                        var appBarData = new APPBARDATA();
                        appBarData.cbSize = Marshal.SizeOf(typeof(APPBARDATA));
                        var autohide = (NativeMethods.SHAppBarMessage(NativeConstants.ABM_GETSTATE, ref appBarData) & NativeConstants.ABS_AUTOHIDE) != 0;
                        if (autohide) r.bottom -= 1;

                        Marshal.StructureToPtr(r, m.LParam, true);
                    }
                    m.Result = IntPtr.Zero;
                break;
            case 0x0084/*NCHITTEST*/ :
                base.WndProc(ref m);

                if (this.WindowState == FormWindowState.Normal && this.isResizable)     //only normal state
                {
                    if ((int)m.Result == 0x01/*HTCLIENT*/)
                    {
                        Point screenPoint = new Point(m.LParam.ToInt32());
                        Point clientPoint = this.PointToClient(screenPoint);
                        if (clientPoint.Y <= RESIZE_HANDLE_SIZE)
                        {
                            if (clientPoint.X <= RESIZE_HANDLE_SIZE)
                                m.Result = (IntPtr)13/*HTTOPLEFT*/ ;
                            else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE))
                                m.Result = (IntPtr)12/*HTTOP*/ ;
                            else
                                m.Result = (IntPtr)14/*HTTOPRIGHT*/ ;
                        }
                        else if (clientPoint.Y <= (Size.Height - RESIZE_HANDLE_SIZE))
                        {
                            if (clientPoint.X <= RESIZE_HANDLE_SIZE)
                                m.Result = (IntPtr)10/*HTLEFT*/ ;
                            else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE))
                                m.Result = (IntPtr)2/*HTCAPTION*/ ;
                            else
                                m.Result = (IntPtr)11/*HTRIGHT*/ ;
                        }
                        else
                        {
                            if (clientPoint.X <= RESIZE_HANDLE_SIZE)
                                m.Result = (IntPtr)16/*HTBOTTOMLEFT*/ ;
                            else if (clientPoint.X < (Size.Width - RESIZE_HANDLE_SIZE))
                                m.Result = (IntPtr)15/*HTBOTTOM*/ ;
                            else
                                m.Result = (IntPtr)17/*HTBOTTOMRIGHT*/ ;
                        }
                    }
                }
                return;
            case (int)WindowMessages.WM_NCPAINT:
                    m.Result = NativeConstants.TRUE;
                    break;
            case (int)WindowMessages.WM_NCACTIVATE:
                {
                    bool active = (m.WParam == NativeConstants.TRUE);

                    if (MinMaxState == FormWindowState.Minimized)
                    {
                        DefWndProc(ref m);
                    }
                    else
                    {
                        m.Result = NativeConstants.TRUE;
                    }
                    break;
                }
            case (int)WindowMessages.WM_WINDOWPOSCHANGED:
                    DefWndProc(ref m);
                    UpdateBounds();
                    var pos = (WINDOWPOS)Marshal.PtrToStructure(m.LParam, typeof(WINDOWPOS));
                    SetWindowRegion(m.HWnd, 0, 0, pos.cx, pos.cy);
                    m.Result = NativeConstants.TRUE;
                    break;
            default:
                base.WndProc(ref m);
                break;
        }
    }

    #endregion

    #region Window

    private void SetWindowRegion(IntPtr hwnd, int left, int top, int right, int bottom)
    {
        var rgn = NativeMethods.CreateRectRgn(0, 0, 0, 0);
        var hrg = new HandleRef((object)this, rgn);
        var r = NativeMethods.GetWindowRgn(hwnd, hrg.Handle);
        RECT box;
        NativeMethods.GetRgnBox(hrg.Handle, out box);
        if (box.left != left || box.top != top || box.right != right || box.bottom != bottom)
        {
            var hr = new HandleRef((object)this, NativeMethods.CreateRectRgn(left, top, right, bottom));
            NativeMethods.SetWindowRgn(hwnd, hr.Handle, NativeMethods.IsWindowVisible(hwnd));
        }
        NativeMethods.DeleteObject(rgn);
    }

    public FormWindowState MinMaxState
    {
        get
        {
            var s = NativeMethods.GetWindowLong(Handle, NativeConstants.GWL_STYLE);
            var max = (s & (int)WindowStyle.WS_MAXIMIZE) > 0;
            if (max) return FormWindowState.Maximized;
            var min = (s & (int)WindowStyle.WS_MINIMIZE) > 0;
            if (min) return FormWindowState.Minimized;
            return FormWindowState.Normal;
        }
    }

    #endregion
1개의 좋아요

참고하겠습니다! 답변 감사합니다!