MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Как сделать, чтобы пользователь мог изменять размер панели в уже включённой программе?"
Answer 1286226
Ну так чем не устаивает решение с WS_THICKFRAME, кода немного, да и пересоздавать ничего не нужно. Правда, просто так поменять стиль уже созданного элемента управления, похоже, невозможно, но можно ввести промежуточную форму. Как-то так:
const uint WS_THICKFRAME = 0x00040000; const int GWL_STYLE = (-16); [DllImport("user32.dll")] public static extern uint SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong); [DllImport("user32.dll")] public static extern uint GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("user32.dll")] public static extern int SetParent(IntPtr hWnd, IntPtr NewParent); // ... Point loc = panel1.Location; Form f = new Form(); f.FormBorderStyle = FormBorderStyle.None; f.Size = panel1.Size; f.CreateControl(); SetParent(f.Handle, this.Handle); uint x = GetWindowLong(f.Handle, GWL_STYLE); x |= WS_THICKFRAME; SetWindowLong(f.Handle, GWL_STYLE,x); panel1.Location = new Point(0, 0); panel1.Parent = f; panel1.Dock = DockStyle.Fill; f.Location = loc; f.Show();
Здесь создается промежуточная форма f, без заголовка, но с рамкой изменения размера. В форму добавляется заранее созданная панель panel1. Затем форма f делается дочерней для основной формы, а ее положение и размер устанавливаются такими же, как у panel1. Благодаря этому, размером панели можно управлять рамкой формы f. Панель panel1 при этом может быть создана в конструкторе, и установленные через конструктор события не слетают при изменении владельца окна.
Дополнение
Если нужно убрать рамку, мало кода уже не получится. Нужно создавать свой класс элемента управления с переопределением стиля и оконной процедуры (как в ответе Alexander Petrov здесь: https://stackoverflow.com/a/37943359/8674428), и добавлять шаманство с неклиентской областью окна, начало которому было положено здесь: https://ru.stackoverflow.com/a/1130986/240512
Вот код:
public class SizeablePanel : Panel { protected override CreateParams CreateParams { get { const int WS_SIZEBOX = 0x40000; var cp = base.CreateParams; cp.Style |= WS_SIZEBOX; return cp; } } const uint WM_NCCALCSIZE = 0x0083; const uint WM_NCHITTEST = 0x0084; const uint HTTOPLEFT = 13; const uint HTTOPRIGHT = 14; const uint HTTOP = 12; const uint HTCAPTION = 2; const uint HTLEFT = 10; const uint HTNOWHERE = 0; const uint HTRIGHT = 11; const uint HTBOTTOM = 15; const uint HTBOTTOMLEFT = 16; const uint HTBOTTOMRIGHT = 17; int xborder=5; int yborder=5; [StructLayout(LayoutKind.Sequential)] public struct RECT { public int left, top, right, bottom; } static int GET_X_LPARAM(IntPtr lp) { short loword = (short)((ulong)lp & 0xffff); return loword; } static int GET_Y_LPARAM(IntPtr lp) { short hiword = (short)((((ulong)lp) >> 16) & 0xffff); return hiword; } [DllImport("user32.dll", SetLastError = true)] static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect); //обработка координат мыши для неклиентской области IntPtr HitTestNCA(IntPtr hWnd, IntPtr wParam, IntPtr lParam) { // Get the point coordinates for the hit test. var ptMouse = new Point(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); // Get the window rectangle. RECT rcWindow; GetWindowRect(hWnd, out rcWindow); // Determine if the hit test is for resizing. Default middle (1,1). ushort uRow = 1; ushort uCol = 1; // Determine if the point is at the top or bottom of the window. if (ptMouse.Y >= rcWindow.top && ptMouse.Y < rcWindow.top + yborder) { //fOnResizeBorder = (ptMouse.Y < (rcWindow.top - rcWindow.top)); uRow = 0; } else if (ptMouse.Y < rcWindow.bottom && ptMouse.Y >= rcWindow.bottom - yborder) { uRow = 2; } // Determine if the point is at the left or right of the window. if (ptMouse.X >= rcWindow.left && ptMouse.X < rcWindow.left + xborder) { uCol = 0; // left side } else if (ptMouse.X < rcWindow.right && ptMouse.X >= rcWindow.right - xborder) { uCol = 2; // right side } // Hit test (HTTOPLEFT, ... HTBOTTOMRIGHT) IntPtr[,] hitTests = new IntPtr[,] { { (IntPtr)HTTOPLEFT, (IntPtr)HTTOP, (IntPtr)HTTOPRIGHT }, { (IntPtr)HTLEFT, (IntPtr)HTNOWHERE, (IntPtr)HTRIGHT}, { (IntPtr)HTBOTTOMLEFT, (IntPtr)HTBOTTOM, (IntPtr)HTBOTTOMRIGHT }, }; return hitTests[uRow, uCol]; } protected override void WndProc(ref Message m) { if (m.Msg == WM_NCCALCSIZE) { //убираем рамку m.Result = IntPtr.Zero; return; } if (m.Msg == WM_NCHITTEST) { //обработка событий мыши IntPtr lRet = HitTestNCA(m.HWnd, m.WParam, m.LParam); if (lRet != (IntPtr)HTNOWHERE) { m.Result = lRet; return; } } base.WndProc(ref m); } }
SizeablePanel не имеет видимой рамки, но ее размер можно изменять перетаскиванием за 5-пиксельную область у края. Цвет панели, естественно, должен отличаться от цвета формы, чтобы можно было найти этот край. Панель также можно поместить на форму через конструктор (не забудьте перестроить решение, чтобы элемент управления появился на панели конструктора).
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.