Shadow + Mouse Move for Borderless Windows Forms Application C#
Here you can copy source code of shadow for your borderless Windows Forms Application. By default if you set FormBorderStyle to None you can't have any shadow like Windows 10 have. But this code can help you to create absolutely the same shadow.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
private bool Drag; private int MouseX; private int MouseY; private const int WM_NCHITTEST = 0x84; private const int HTCLIENT = 0x1; private const int HTCAPTION = 0x2; private bool m_aeroEnabled; private const int CS_DROPSHADOW = 0x00020000; private const int WM_NCPAINT = 0x0085; private const int WM_ACTIVATEAPP = 0x001C; [System.Runtime.InteropServices.DllImport("dwmapi.dll")] public static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset); [System.Runtime.InteropServices.DllImport("dwmapi.dll")] public static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize); [System.Runtime.InteropServices.DllImport("dwmapi.dll")] public static extern int DwmIsCompositionEnabled(ref int pfEnabled); [System.Runtime.InteropServices.DllImport("Gdi32.dll", EntryPoint = "CreateRoundRectRgn")] private static extern IntPtr CreateRoundRectRgn( int nLeftRect, int nTopRect, int nRightRect, int nBottomRect, int nWidthEllipse, int nHeightEllipse ); public struct MARGINS { public int leftWidth; public int rightWidth; public int topHeight; public int bottomHeight; } protected override CreateParams CreateParams { get { m_aeroEnabled = CheckAeroEnabled(); CreateParams cp = base.CreateParams; if (!m_aeroEnabled) cp.ClassStyle |= CS_DROPSHADOW; return cp; } } private bool CheckAeroEnabled() { if (Environment.OSVersion.Version.Major >= 6) { int enabled = 0; DwmIsCompositionEnabled(ref enabled); return (enabled == 1) ? true : false; } return false; } protected override void WndProc(ref Message m) { switch (m.Msg) { case WM_NCPAINT: if (m_aeroEnabled) { var v = 2; DwmSetWindowAttribute(this.Handle, 2, ref v, 4); MARGINS margins = new MARGINS() { bottomHeight = 1, leftWidth = 0, rightWidth = 0, topHeight = 0 }; DwmExtendFrameIntoClientArea(this.Handle, ref margins); } break; default: break; } base.WndProc(ref m); if (m.Msg == WM_NCHITTEST && (int)m.Result == HTCLIENT) m.Result = (IntPtr)HTCAPTION; } private void PanelMove_MouseDown(object sender, MouseEventArgs e) { Drag = true; MouseX = Cursor.Position.X - this.Left; MouseY = Cursor.Position.Y - this.Top; } private void PanelMove_MouseMove(object sender, MouseEventArgs e) { if (Drag) { this.Top = Cursor.Position.Y - MouseY; this.Left = Cursor.Position.X - MouseX; } } private void PanelMove_MouseUp(object sender, MouseEventArgs e) { Drag = false; } |
Добрый день!
Скажите пожалуйста, а для чего нужны методы PanelMove_Mouse*? Без них всё вроде работает.
И подскажите пожалуйста, как запретить разворачивание окна на весь экран по двойному клику?
Не смотря на то, что установил следующие параметры, как только добавляю ваш код, становится возможным по двойному клику разворачивать окно на весь экран
his.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MaximumSize = new System.Drawing.Size(409, 160);
this.MinimumSize = new System.Drawing.Size(409, 160);
Если убрать строчку if (m.Msg == WM_NCHITTEST && (int)m.Result == HTCLIENT) m.Result = (IntPtr)HTCAPTION;
то окно не разворачивается, но тогда придется задействовать методы PanelMove_Mouse*, а хотелось бы обойтись без этого
Добрый 🖐
Это нужно для того, чтобы форму можно было бы перемещать.
Сегодня как раз решал одну из проблем данного метода, но пока тщетно.
Вы можете поубирать лишний код, если всё работает. Но проверяйте, чтобы форму можно было таскать.
Либо создайте свою панель и прикрепите её вместо шапки. Но на неё придётся писать свой метод, MouseDown, который позволит таскать форму за эту самую панель.
Касаемо двойного клика по форме.
После BorderStyle = None довольно много становится недоступно, это спасибо Microsoft.
Идеальное решение нужно самому искать. Но здесь предложен наиболее удачный компромисс.
Спасибо, вроде всё понял 🙂
Пока остановился на следующем решении:
1. Убрал код, который по сути реализует функционал перетаскивания: if (m.Msg == WM_NCHITTEST && (int)m.Result == HTCLIENT) m.Result = (IntPtr)HTCAPTION;
2. Добавил обработчики событий для MouseDown, MouseMove, и MouseUp, дабы задействовать методы PanelMove_Mouse*, взамен удаленной строки из п.1:
MouseDown += new MouseEventHandler(PanelMove_MouseDown);
MouseMove += new MouseEventHandler(PanelMove_MouseMove);
MouseUp += new MouseEventHandler(PanelMove_MouseUp);
Теперь по двойному клику форма не разворачивается, но форму можно перемещать.
Красава 👏