.NET / Создание окна выделения области для скриншотера

в 23:00, , рубрики: си шарп, скриншотер, форма, метки: , , ,

.NET / Создание окна выделения области для скриншотера
Ранее, читатель AlexanderG, выкладывал программку, которая в один клик делает скриншот всего экрана и автоматически выгружает его на хостинг. Все очень круто, быстро и удобно, но на мой взгляд, не хватает одного функционала — выделения нужной области, потому я решил дописать программу.
В этой статье, я попробую описать создание своей полноценной формы, вместо унылой стандартной. В моем случаи, мне нужна была красивая прозрачная панель выделения области экрана для создания скриншота, которую можно перемещать и менять ее размеры. Это моя первая программа на c#, потому статья ориентирована на новичков.
Создаем свою форму

Вот схема, по которой я делал свое окно.
Итак, для начала нужно убрать стандартную форму, для этого переключаем свойство FormBorderStyle в None, ставим прозрачность Opacity, у меня 65%.
Далее создаем панель, задаем нужный цвет и свойства Dock: Fill, Size: 200;200. Затем создаем еще одну панель, цвет выбираем любой другой, свойство Location: 2;2, Size: 196;196. Можно создавать и одну панель, так я делал рамку. Думаю с привязкой граней вы разберетесь сами.
Теперь приступим к ресайзу панели, код:Point ResizeLocation = Point.Empty;
void panResize_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ResizeLocation = e.Location;
ResizeLocation.Offset(-this.Width, -this.Height);
if (!(ResizeLocation.X > -17 || ResizeLocation.Y > -17)) //17 - ширина области ресайза
ResizeLocation = Point.Empty;
}
else
ResizeLocation = Point.Empty;
}
void panResize_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
label1.Text = this.Width.ToString() + "x" + this.Height.ToString();
if (e.Button == MouseButtons.Left && !ResizeLocation.IsEmpty)
{
if this.Cursor == Cursors.SizeNWSE)
Size = new Size(e.Location.X - ResizeLocation.X, e.Location.Y - ResizeLocation.Y);
else if (this.Cursor == Cursors.SizeWE)
Size = new Size(e.Location.X - ResizeLocation.X, Size.Height);
else if (this.Cursor == Cursors.SizeNS)
Size = new Size(Size.Width, e.Location.Y - ResizeLocation.Y);
}
else if (e.X - this.Width > -17 && e.Y - this.Height > -17)
this.Cursor = Cursors.SizeNWSE;
else if (e.X - this.Width > -17)
this.Cursor = Cursors.SizeWE;
else if (e.Y - this.Height > -17)
this.Cursor = Cursors.SizeNS;
else
{
this.Cursor = Cursors.Default;
}
}
void panResize_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
ResizeLocation = Point.Empty;
}
Тянуть можно только за правую и нижнюю грань, а также за правый нижний угол, доделать для всех сторон не сложно.
В событиях панели: MouseDown: panResize_MouseDown, MouseMove:panResize_MouseMove, MouseUp:panResize_MouseUp.
Для перемещения окна, создаем picturebox поверх панелей (сделайте margin больше, чем область ресайза) используем API (или как в примере на msdn.microsoft.com):private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(this.Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
Для работы, нужно добавить:[DllImportAttribute("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
В событиях picturebox: MouseDown:Form1_MouseDown.
Можно еще добавить запрет на вытаскивание формы за границы экрана:protected override void WndProc(ref Message m)
{
if (m.Msg == WM_MOVING)
{
RECT rc;
rc = (RECT)Marshal.PtrToStructure(m.LParam, typeof(RECT));
// Попытка выхода за левую границу экрана ...
if (rc.Left < 0)
{
rc.Left = 0;
rc.Right = this.Width;
}
// Попытка выхода за верхнюю границу экрана ...
if (rc.Top Screen.PrimaryScreen.Bounds.Right)
{
rc.Left = Screen.PrimaryScreen.Bounds.Right - this.Width;
rc.Right = Screen.PrimaryScreen.Bounds.Right;
}
// Попытка выхода за нижнюю границу экрана ...
if (rc.Bottom > Screen.PrimaryScreen.Bounds.Bottom)
{
rc.Bottom = Screen.PrimaryScreen.Bounds.Bottom;
rc.Top = Screen.PrimaryScreen.Bounds.Bottom - this.Height;
}
Marshal.StructureToPtr(rc, m.LParam, true);
}
base.WndProc(ref m);
}Вот сама программа, она умеет:
ЛКМ — делать скрин всего экрана
ПКМ — вызывает меню, откуда можно сделать скрин выделеной области
— автоматически загружать изображение на сервер
Также сделал простенький хостинг изображений, в сердце сайта — Chevereto, есть мультиаплоад, изменение размера, короткие ссылки. HTV.SU.


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js