Изменить размер окна без полей в правом нижнем углу
Я бы хотел, чтобы пользователь изменил размер окна без полей в правом нижнем углу, как если бы я мог изменить размер окна автозаполнения элемента управления combobox.
Я не могу найти свойства для настройки формы таким образом.
Может быть, кто-то может помочь мне в этой проблеме.
Изображение можно найти здесь:
4 ответа
Надлежащим способом для достижения этой цели было бы добавить обработчик proc сообщения (переопределяя Form.WndProc
например) к вашей форме и обработать WM_NCHITTEST
сообщение. (Вы можете найти определение C# этого сообщения на http://pinvoke.net/.) В частности, когда вы получаете сообщение, рассчитайте, соответствует ли тест попадания точке в области, для которой вы назначили изменение размера, и, если это так, верните HTBOTTOMRIGHT. Окно по умолчанию будет делать все остальное за вас, так как будет предполагать, что пользователь щелкнул в правом нижнем углу границы окна, даже если у вашего окна нет границы.
Этот подход требует небольшого взаимодействия с Win32, но он сделает ваш изменение размера точно таким же, как и любое другое изменение размера окна.
Самый простой способ - сделать так, как сказал @benPearce, поместить панель в угол и отрегулировать размер формы, используя ширину / высоту. Это будет работать, но изменение размера не будет гладким, особенно в Vista и Win7 Basic, где полная перерисовка отключена при стандартном перемещении и изменении размера, в то время как будет пытаться перерисовать на каждом шаге.
Обновление: в обоих подходах вы должны также выяснить, как рисовать захват. Например, вы можете поместить растровое изображение стандартного захвата. Тем не менее, учитывая, что ваша форма не имеет заголовка и границы, поэтому вы не обязательно застряли со стандартными визуальными элементами Windows, вы можете выбрать что-то фантастическое.
Обновление 2: если у вас есть элемент управления, охватывающий все окно, он будет использовать сообщения мыши в форме. Вы должны каким-то образом обрезать место, которое вы хотите использовать для изменения размера этого элемента управления. У вас есть несколько вариантов решения этой проблемы:
- Измените размер элемента управления, чтобы освободить место для ручки изменения размера.
- Настройте область управления (через свойство Region), чтобы исключить изменение размера.
- Закройте ручку изменения размера панели, прослушайте ее сообщение MouseEnter и установите для свойства формы Capture значение true, что приведет к тому, что все дальнейшие сообщения мыши перейдут к нему. Примечание: вам придется освободить захват, как только мышь покинет эту область после завершения изменения размера.
Я бы порекомендовал перейти на вариант 1 как самый простой. Вариант 3 является наиболее сложным и требует подробных сведений о том, как работает ввод с помощью мыши в Windows, поэтому я не рекомендовал бы его. Вариант 2 является хорошей альтернативой варианту 1, но вам нужно будет попытаться увидеть, как элемент управления ListView отреагирует на его область, подвергаемую настройке.
Вот код, соответствующий объяснениям Франци, я писал его, но он тем временем ответил, так что проголосуйте за его объяснение, и это хорошо, если этот код соответствует вашим потребностям.
protected override void WndProc(ref Message m) {
const int wmNcHitTest = 0x84;
const int htBottomLeft = 16;
const int htBottomRight = 17;
if (m.Msg == wmNcHitTest) {
int x = (int) (m.LParam.ToInt64() & 0xFFFF);
int y = (int) ((m.LParam.ToInt64() & 0xFFFF0000) >> 16);
Point pt = PointToClient(new Point(x, y));
Size clientSize = ClientSize;
if (pt.X >= clientSize.Width - 16 && pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16) {
m.Result = (IntPtr) (IsMirrored ? htBottomLeft : htBottomRight);
return;
}
}
base.WndProc(ref m);
}
Редактировать: чтобы написать захват, вы можете инициализировать new VisualStyleRenderer(VisualStyleElement.Status.Gripper.Normal)
и использовать его PaintBackground()
метод.
Большое спасибо за размещение этого замечательного образца и объяснения. Ниже я добавил некоторые дополнения, которые могут заинтересовать других. Некоторые из приведенных здесь кодов взяты из других публикаций в стеке, но возможность увидеть их в одном блоке кода может оказаться полезной для других. Я хотел иметь возможность изменять размер формы на ВСЕХ границах, а не только в правом нижнем углу. Я также хотел иметь возможность перетаскивать форму. Наконец, я хотел тень.
//***********************************************************
//This gives us the ability to resize the borderless from any borders instead of just the lower right corner
protected override void WndProc(ref Message m)
{
const int wmNcHitTest = 0x84;
const int htLeft = 10;
const int htRight = 11;
const int htTop = 12;
const int htTopLeft = 13;
const int htTopRight = 14;
const int htBottom = 15;
const int htBottomLeft = 16;
const int htBottomRight = 17;
if (m.Msg == wmNcHitTest)
{
int x = (int)(m.LParam.ToInt64() & 0xFFFF);
int y = (int)((m.LParam.ToInt64() & 0xFFFF0000) >> 16);
Point pt = PointToClient(new Point(x, y));
Size clientSize = ClientSize;
///allow resize on the lower right corner
if (pt.X >= clientSize.Width - 16 && pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16)
{
m.Result = (IntPtr)(IsMirrored ? htBottomLeft : htBottomRight);
return;
}
///allow resize on the lower left corner
if (pt.X <= 16 && pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16)
{
m.Result = (IntPtr)(IsMirrored ? htBottomRight : htBottomLeft);
return;
}
///allow resize on the upper right corner
if (pt.X <= 16 && pt.Y <= 16 && clientSize.Height >= 16)
{
m.Result = (IntPtr)(IsMirrored ? htTopRight : htTopLeft);
return;
}
///allow resize on the upper left corner
if (pt.X >= clientSize.Width - 16 && pt.Y <= 16 && clientSize.Height >= 16)
{
m.Result = (IntPtr)(IsMirrored ? htTopLeft : htTopRight);
return;
}
///allow resize on the top border
if (pt.Y <= 16 && clientSize.Height >= 16)
{
m.Result = (IntPtr)(htTop);
return;
}
///allow resize on the bottom border
if (pt.Y >= clientSize.Height - 16 && clientSize.Height >= 16)
{
m.Result = (IntPtr)(htBottom);
return;
}
///allow resize on the left border
if (pt.X <= 16 && clientSize.Height >= 16)
{
m.Result = (IntPtr)(htLeft);
return;
}
///allow resize on the right border
if (pt.X >= clientSize.Width - 16 && clientSize.Height >= 16)
{
m.Result = (IntPtr)(htRight);
return;
}
}
base.WndProc(ref m);
}
//***********************************************************
//***********************************************************
//This gives us the ability to drag the borderless form to a new location
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
private void YOURCONTROL_MouseDown(object sender, MouseEventArgs e)
{
//ctrl-leftclick anywhere on the control to drag the form to a new location
if (e.Button == MouseButtons.Left && Control.ModifierKeys == Keys.Control)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
//***********************************************************
//***********************************************************
//This gives us the drop shadow behind the borderless form
private const int CS_DROPSHADOW = 0x20000;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ClassStyle |= CS_DROPSHADOW;
return cp;
}
}
//***********************************************************
Поместите панель или какой-либо другой элемент управления в угол, используя события MouseDown и MouseMove панели, соответствующим образом отрегулируйте размер форм.
В MouseDown я записываю координаты, затем в MouseMove вы можете рассчитать разницу от исходного положения для настройки размера форм.