С Новым годом! Форум программистов, компьютерный форум, киберфорум
Visual Basic .NET
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.53/15: Рейтинг темы: голосов - 15, средняя оценка - 4.53
148 / 116 / 10
Регистрация: 12.09.2011
Сообщений: 785
1

Выделение участка изображения в PictureBox

25.01.2015, 17:16. Показов 2973. Ответов 11
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Привет всем!

Хотел бы реализовать функцию, которая бы позволяла на изображении в PictureBox менять размер и положение участка выделения (прямоугольника) с помощью мыши, то есть, например, как в Paint или любом другом графическом редакторе. На изображении стоит прямоугольник и, тягая за его края, можно было бы менять размер этого прямоугольника. Рисование самого прямоугольника делаю так:

VB.NET
1
2
3
4
5
6
7
8
9
       Dim g As Graphics
 
        Dim bmp As New Bitmap(PictureBox1.Image)
 
        g = Graphics.FromImage(bmp) 
 
        Dim pen As New Pen(Color.Red, 3)
 
        g.DrawRectangle(pen, rect)
где rect - это тип Rectangle, определяющий его границы.

Как можно мышь к прямоугольнику привязать, чтобы менять его размеры, подскажите, пожалуйста?

Спасибо!
0
Programming
Эксперт
9485 / 562 / 19
Регистрация: 12.04.2006
Сообщений: 11,671
Блог
25.01.2015, 17:16
Ответы с готовыми решениями:

Выделение области изображения в picturebox
Есть изображение, внутри которого нужно выделить область с которой дальше придется...

Работа с pictureBox (выделение части изображения)
Здравствуйте, уважаемые форумчане. У меня появилась проблема с выделением участка картинки в...

Выделение участка на странице
Добрый день! Помогите с проектом, не силен в JS, необходимо реализовать функцию выделения участка...

Склеивание изображения нескольких picturebox в один picturebox
Здравствуй, такой вопрос возник на счет picturebox. Можно ли из 3-ех к примеру picturebox(в каждом...

11
39 / 28 / 8
Регистрация: 14.04.2012
Сообщений: 249
25.01.2015, 19:33 2
Цитата Сообщение от Vinemax Посмотреть сообщение
Как можно мышь к прямоугольнику привязать, чтобы менять его размеры, подскажите, пожалуйста?
можно считывать координаты курсора. Когда он подойдёт к границы прямоугольника, произвести нужное действие.
1
148 / 116 / 10
Регистрация: 12.09.2011
Сообщений: 785
25.01.2015, 22:17  [ТС] 3
kostrorod, это очевидно ) Просто хотел знать как именно это сделать
0
39 / 28 / 8
Регистрация: 14.04.2012
Сообщений: 249
25.01.2015, 22:41 4
Цитата Сообщение от Vinemax Посмотреть сообщение
Просто хотел знать как именно это сделать
VB.NET
1
2
3
4
5
Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        
            if e.X = PozX then ' если курсор подошёл к позиции Х прямоугольника  (PozX) совершить действие
            
end sub
1
211 / 228 / 87
Регистрация: 21.04.2013
Сообщений: 404
26.01.2015, 03:23 5
Лучший ответ Сообщение было отмечено Vinemax как решение

Решение

Цитата Сообщение от Vinemax Посмотреть сообщение
на изображении в PictureBox менять размер и положение участка выделения (прямоугольника) с помощью мыши
Я бы сделал отдельный контрол.
Для перемещения c копированием написАл такой пример (код сырой):
VB.NET
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
96
97
98
99
100
101
Public Class UC
    Inherits UserControl
 
    Private _MouseDown As Boolean = False
    Private _Coords As Point
    Private _Rectangle As Rectangle
 
    Private _Image As Bitmap
    Public Property Image As Bitmap
        Get
            Return _Image
        End Get
        Set(ByVal value As Bitmap)
            _Image = value
            Me.Refresh()
        End Set
    End Property
 
    Private _Clip As Bitmap
    Public ReadOnly Property Clip As Bitmap
        Get
            Return _Clip
        End Get
    End Property
 
    Sub New()
        Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
        Me.SetStyle(ControlStyles.UserPaint, True)
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
    End Sub
 
    Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
        'MyBase.OnMouseDown(e)
 
        _MouseDown = True
        _Coords = e.Location
 
        If Not _Rectangle.Contains(_Coords) And _Clip IsNot Nothing Then
            Graphics.FromImage(_Image).DrawImage(_Clip, _Rectangle)
            _Clip = Nothing
            _Rectangle = Nothing
            Me.Refresh()
        End If
    End Sub
    Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.MouseEventArgs)
        'MyBase.OnMouseUp(e)
 
        _MouseDown = False
 
        If _Rectangle.Width > 0 And _Rectangle.Height > 0 And _Clip Is Nothing Then
            _Clip = New Bitmap(_Rectangle.Width, _Rectangle.Height, Imaging.PixelFormat.Format32bppArgb)
            Graphics.FromImage(_Clip).DrawImage(_Image, _
                                                New Rectangle(0, 0, _Rectangle.Width, _Rectangle.Height), _
                                                _Rectangle, _
                                                GraphicsUnit.Pixel)
        End If
    End Sub
 
    Protected Overrides Sub OnMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
        'MyBase.OnMouseMove(e)
 
        If _MouseDown Then
            Dim c As Point = e.Location
            Dim w As Integer = c.X - _Coords.X
            Dim h As Integer = c.Y - _Coords.Y
 
            If _Clip IsNot Nothing Then
                _Rectangle.X += w
                _Rectangle.Y += h
                _Coords = c
 
            Else
 
                If w <> 0 And h <> 0 Then
                    _Rectangle = New Rectangle(If(w > 0, _Coords.X, c.X), _
                                               If(h > 0, _Coords.Y, c.Y), _
                                               Math.Abs(w), _
                                               Math.Abs(h))
                End If
 
            End If
 
            Me.Refresh()
        End If
    End Sub
 
    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
 
        If _Image IsNot Nothing Then e.Graphics.DrawImage(_Image, 0, 0, _Image.Width, _Image.Height)
 
        If _Clip IsNot Nothing Then e.Graphics.DrawImage(_Clip, _Rectangle)
 
        If _Rectangle <> Nothing Then
            Dim p As New Pen(Color.Cyan, 1)
            p.DashStyle = DashStyle.Dash
            e.Graphics.DrawRectangle(p, _Rectangle)
            p.Dispose()
        End If
    End Sub
End Class
Миниатюры
Выделение участка изображения в PictureBox  
1
1717 / 1204 / 228
Регистрация: 23.12.2010
Сообщений: 1,541
26.01.2015, 07:46 6
Лучший ответ Сообщение было отмечено Памирыч как решение

Решение

VB.NET
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
Public Class RubberBand 
    ' ----- The three types of rubber bands. 
    Public Enum RubberBandStyle 
        DashedLine 
        ThickLine 
        SolidBox 
        SolidBoxWithDashedLine 
    End Enum 
 
    ' ----- The current drawing state. 
    Public Enum RubberBandState 
        Inactive 
        FirstTime 
        Active 
    End Enum 
 
    ' ----- Class-level variables. 
    Private BasePoint As Point 
    Private ExtentPoint As Point 
    Private CurrentState As RubberBandState 
    Private BaseControl As Control 
    Public Style As RubberBandStyle 
    Public BackColor As Color 
    Public Sub New(ByVal useControl As Control, _ 
          Optional ByVal useStyle As RubberBandStyle = _ 
          RubberBandStyle.DashedLine) 
        ' ----- Constructor with one or two parameters. 
        BaseControl = useControl 
        Style = useStyle 
        BackColor = Color.Black 
    End Sub 
 
    Public Sub New(ByVal useControl As Control, ByVal useStyle As RubberBandStyle, ByVal useColor As Color) 
        ' ----- Constructor with three parameters. 
        BaseControl = useControl 
        Style = useStyle 
        BackColor = useColor 
    End Sub 
 
    Public ReadOnly Property Rectangle() As Rectangle 
        Get 
            ' ----- Return the bounds of the  rubber-band area. 
            Dim result As Rectangle 
 
            ' ----- Ensure the coordinates go left to 
            ' right, top to bottom. 
            result.X = IIf(BasePoint.X < ExtentPoint.X, _ 
               BasePoint.X, ExtentPoint.X) 
            result.Y = IIf(BasePoint.Y < ExtentPoint.Y, _ 
               BasePoint.Y, ExtentPoint.Y) 
            result.Width = Math.Abs(ExtentPoint.X - BasePoint.X) 
            result.Height = Math.Abs(ExtentPoint.Y - BasePoint.Y) 
            Return result 
        End Get 
    End Property 
 
    Public Sub Start(ByVal x As Integer, ByVal y As Integer) 
        ' ----- Start drawing the rubber band. The user must 
        '       call Stretch() to actually draw the first 
        '       band image. 
        BasePoint.X = x 
        BasePoint.Y = y 
        ExtentPoint.X = x 
        ExtentPoint.Y = y 
        Normalize(BasePoint) 
        CurrentState = RubberBandState.FirstTime 
    End Sub 
 
    Public Sub Stretch(ByVal x As Integer, ByVal y As Integer) 
        ' ----- Change the size of the rubber band. 
        Dim newPoint As Point 
 
        ' ----- Prepare the new stretch point. 
        newPoint.X = x 
        newPoint.Y = y 
        Normalize(newPoint) 
 
        Select Case CurrentState 
            Case RubberBandState.Inactive 
                ' ----- Rubber band not in use. 
                Return 
            Case RubberBandState.FirstTime 
                ' ----- Draw the initial rubber band. 
                ExtentPoint = newPoint 
                DrawTheRectangle() 
                CurrentState = RubberBandState.Active 
            Case RubberBandState.Active 
                ' ----- Undraw the previous band, then 
                '       draw the new one. 
                DrawTheRectangle() 
                ExtentPoint = newPoint 
                DrawTheRectangle() 
        End Select 
    End Sub 
 
    Public Sub Finish() 
        ' ----- Stop drawing the rubber band. 
        DrawTheRectangle() 
        CurrentState = 0 
    End Sub 
 
    Private Sub Normalize(ByRef whichPoint As Point) 
        ' ----- Don't let the rubber band go outside the view. 
        If (whichPoint.X < 0) Then whichPoint.X = 0 
        If (whichPoint.X >= BaseControl.ClientSize.Width) Then whichPoint.X = BaseControl.ClientSize.Width - 1 
 
        If (whichPoint.Y < 0) Then whichPoint.Y = 0 
        If (whichPoint.Y >= BaseControl.ClientSize.Height) Then whichPoint.Y = BaseControl.ClientSize.Height - 1 
    End Sub 
 
    Private Sub DrawTheRectangle() 
        ' ----- Draw the rectangle on the control or 
        '       form surface. 
        Dim drawArea As Rectangle 
        Dim screenStart, screenEnd As Point 
 
        ' ----- Get the square that is the  rubber-band area. 
        screenStart = BaseControl.PointToScreen(BasePoint) 
        screenEnd = BaseControl.PointToScreen(ExtentPoint) 
        drawArea.X = screenStart.X 
        drawArea.Y = screenStart.Y 
        drawArea.Width = (screenEnd.X - screenStart.X) 
        drawArea.Height = (screenEnd.Y - screenStart.Y) 
 
        ' ----- Draw using the user-selected style. 
        Select Case Style 
            Case RubberBandStyle.DashedLine 
                ControlPaint.DrawReversibleFrame( _ 
                   drawArea, BackColor, FrameStyle.Dashed) 
            Case RubberBandStyle.ThickLine 
                ControlPaint.DrawReversibleFrame( _ 
                   drawArea, BackColor, FrameStyle.Thick) 
            Case RubberBandStyle.SolidBox 
                ControlPaint.FillReversibleRectangle( _ 
                   drawArea, BackColor) 
            Case RubberBandStyle.SolidBoxWithDashedLine 
                ControlPaint.FillReversibleRectangle( _ 
                   drawArea, BackColor) 
                ControlPaint.DrawReversibleFrame( _ 
                   drawArea, Color.Black, FrameStyle.Dashed) 
        End Select 
    End Sub 
End Class
В коде формы
VB.NET
1
Friend SelectionArea As RubberBand
И, например в процедуре загрузки формы
VB.NET
1
SelectionArea = New RubberBand(Me.Poligon, RubberBand.RubberBandStyle.DashedLine, Color.FromArgb(255, 0, 255))
где poligon - контрол, на котором рисуем выделение (если форма - me)
RubberBand.RubberBandStyle.DashedLine - стиль очерчивания (описан в классе rubberband)
Последний параметр - Цвет области выделения
И работа с ним при нажатии на кнопку мыши в пределах контрола, на котором рисуем область (mouse_down)
VB.NET
1
SelectionArea.Start(e.X, e.Y)
при очерчивании прямоугольника (при нажатой кнопке мыши (mousemove)
VB.NET
1
2
3
If e.Button = Windows.Forms.MouseButtons.Left Then 
            SelectionArea.Stretch(e.X, e.Y) 
        End If
Ну и при отпускании кнопки, в конце очерчивания области (mouseup)
VB.NET
1
SelectionArea.Finish()
В итоге объект SelectionArea будет иметь в своей структуре координаты прямоугольной области выделения.
Ну а дальше с этой информацией уже обрабатывайте то, что выделяли.
3
148 / 116 / 10
Регистрация: 12.09.2011
Сообщений: 785
26.01.2015, 08:53  [ТС] 7
Юпатов Дмитрий, спасибо большое! Буду пробовать сейчас...
0
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
18.12.2016, 04:36 8
Юпатов Дмитрий, прямоугольник выделения запаздывает за курсором мыши и сильно моргает при выделении - это неизбежно? Ведь в графических редакторах этих эфектов нет. А если попробовать вместо FillReversibleRectangle функцию API DrawFocusRect?
0
1717 / 1204 / 228
Регистрация: 23.12.2010
Сообщений: 1,541
18.12.2016, 11:40 9
не должен вообще то
0
179 / 69 / 13
Регистрация: 22.12.2015
Сообщений: 2,648
18.12.2016, 11:56 10
Юпатов Дмитрий, в архиве Ваш вариант, пример из MSDN и вариант с использованием API. Попробуйте

Не по теме:

Кстати, если подскажете как избавится от моргания изображения при старте захвата экрана (проект DrawFocusRect), буду очень признателен.

Вложения
Тип файла: rar SelectArea.rar (157.6 Кб, 89 просмотров)
3
1717 / 1204 / 228
Регистрация: 23.12.2010
Сообщений: 1,541
18.12.2016, 13:39 11
Хм... вариант с API самый шикарный, конечно.
2
82 / 72 / 15
Регистрация: 18.01.2014
Сообщений: 349
11.04.2018, 22:24 12
А с произвольной областью, не прямоугольной (например овал) можно что-нибудь придумать?

Чтобы также можно было перетаскивать часть изображения овальной формы, растягивать и т.д.

Или например System.Drawing.Drawing2D.GraphicsPath, в котором координаты вершин произвольной фигуры.

Добавлено через 4 часа 5 минут
Придумал алгоритм, но в одном месте застопорился.

1) Берем Path as GraphicPath,
2) у этого Path берем GetBounds
3) добавляем прямоугольник Getbounds к GraphicPath (Path.AddRectangle)
4) рисуем на отдельном новом BMP прямоугольную часть исходного изображения обрамленную Path.getbounds
5) Закрашиваем ненужные фрагменты у нового BMP, например белым цветом с помощью g.fillpath(white,Path)
6) Делаем белый цвет прозрачным
6.3) небольшая проблема с масштабом размеров между исходной картинкой и новым BMP, но она решаема
6.5) А вот здесь проблема: если в нужной части картинки тоже есть белый цвет, то он станет также прозрачным
7) в нужном месте исходной картинки рисуем этот BMP
Итого: копируется не прямоугольная, а произвольная замкнутая область
0
11.04.2018, 22:24
cpp_developer
Эксперт
20123 / 5690 / 417
Регистрация: 09.04.2010
Сообщений: 12,546
Блог
11.04.2018, 22:24
Помогаю со студенческими работами здесь

Выделение участка на TImage для заполнения его объектами
Добрый день. Нужно реализовать такую вещь... На компоненте TImage выделяется прямоугольная область,...

Как добиться качественного рисования изображения поверх изображения picturebox?
есть код: PictureBox p = (PictureBox)sender; ...

Поиск участка изображения
Как заскринить экран(каким способом?) найти небольшой кусок в изображении и занести его координаты...

Показ определённого участка изображения
Есть картинка picture.png на которой определённое количество мелких рисунков(четыре шт.)....

Передача координат выделенного участка изображения
Добрый день. Есть Главная форма, добавляю изображение для мини просмотра (Кнопка &quot;Добавить...

На PictureBox сделать, чтобы при выделении участка, начальная и конечная координаты прямоугольника сохранились в переменные
Есть обработчик: private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Блоги программистов
Обновление сайта www.historian.b­y
Reglage 05.01.2025
Обещал подвести итоги 2024 года для сайта. Однако начну с того, что изменилось за неделю. Добавил краткий урок по последовательности действий при анализе вредоносных файлов и значительно улучшил урок. . .
Как использовать GraphQL в C# с HotChocolate
Programming 05.01.2025
GraphQL — это современный подход к разработке API, который позволяет клиентам запрашивать только те данные, которые им необходимы. Это делает взаимодействие с API более гибким и эффективным по. . .
Модель полного двоичного суматора с помощью логических операций (python)
AlexSky-coder 04.01.2025
def binSum(x:list, y:list): s=^y] p=x and y for i in range(1,len(x)): s. append((x^y)^p) p=(x and y)or(p and (x or y)) return s x=list() y=list()
Это мы не проходили, это нам не задавали...(аси­­хронный счётчик с управляющим сигналом задержки).
Hrethgir 04.01.2025
Асинхронный счётчик на сумматорах (шестиразрядный по числу диодов на плате, но наверное разрядов будет больше - восемь или шестнадцать, а диоды на старшие), так как триггеры прошли тестирование и. . .
Руководство по созданию бота для Телеграм на Python
IT_Exp 04.01.2025
Боты для Телеграм представляют собой автоматизированные программы, которые выполняют различные задачи, взаимодействуя с пользователями через интерфейс мессенджера. В данной статье мы рассмотрим,. . .
Применение компонентов PrimeVue в Vue.js 3 на TypeScript
BasicMan 04.01.2025
Введение в PrimeVue и настройка окружения PrimeVue представляет собой мощную библиотеку компонентов пользовательского интерфейса для Vue. js 3, которая предоставляет разработчикам богатый набор. . .
Как стать Senior developer
cpp_developer 04.01.2025
В современной индустрии разработки программного обеспечения позиция Senior Developer представляет собой не просто следующую ступень карьерной лестницы, а качественно новый уровень профессионального. . .
Что известно о дате выхода Windows 12 и чего от нее ждать
IT_Exp 04.01.2025
В мире технологий постоянно происходят изменения, и операционные системы не являются исключением. Windows 11, выпущенная в октябре 2021 года, принесла множество инноваций и улучшений, но. . .
Что новенького в .NET Core 9
Programming 04.01.2025
Обзор ключевых изменений в . NET Core 9 Платформа . NET Core продолжает активно развиваться, и версия 9 представляет собой значительный шаг вперед в эволюции этой технологии. Новый релиз. . .
Инструкция по установке python3.13.1 в Debian 12
AlexSky-coder 03.01.2025
sudo apt update sudo apt install build-essential zlib1g-dev libncurses5-dev libgdbm-dev libnss3-dev libssl-dev libreadline-dev libffi-dev wget. . .
Затестил триггеры. архив проекта прилагаю с GOA файлами в настройках архиватора проектов.
Hrethgir 03.01.2025
В этот раз нет закольцованности, потому что от неё только глюки, как я понял, логика не вырезанная. Триггеры очень быстрые если верить измерениям с помощью анализатора от Gowin. Есть ещё регистры,. . .
Python в помощь DevOps
IT_Exp 03.01.2025
Причины использования Python в работе DevOps Python стал неотъемлемой частью мира DevOps, и это не случайно. Этот язык программирования обладает множеством преимуществ, которые делают его. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru