С Новым годом! Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.82/11: Рейтинг темы: голосов - 11, средняя оценка - 4.82
0 / 0 / 0
Регистрация: 11.11.2017
Сообщений: 9

Работа со скриншотом экрана в clipboard

11.11.2017, 09:50. Показов 2539. Ответов 25
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, вопрос следующий:
нужно узнать значение в RGB палитре заданного пикселя в скриншоте экрана, сделанного посредством нажатия print screen.
Задачу решал так:

сохранял содержимое в файл на диск

Visual Basic
1
SavePicture Clipboard.GetData(vbCFBitmap), "c:\1.bmp"
потом открывал и уже выдергивал значение пикселя в переменную s по координатам (x,y) для разрешения 1600х900

Visual Basic
1
2
3
Open "c:\1.bmp" For Binary As 1
Get #1, ((900- y - 1) * 1600+ (x + 1)) * 3 + 55 , s
Close #1
Но каждый раз записывать и считывать из файла долго, нельзя ли как-нибудь выдергивать значение из RGB палитры напрямую из clipboard'a?

Спасибо.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
11.11.2017, 09:50
Ответы с готовыми решениями:

Класс Clipboard - ошибка «Requested Clipboard operation did not succeed»
Пытаюсь скопировать текст программно таким образом: Clipboard.SetText("something") Вместо выполнения поручения, он напрочь отказывается...

Работа с clipboard
Добрый день, пытаясь сделать программу появилась проблема. Хочу чтобы при нажатии на кнопку(CopyButton) в буфер копировался текст из...

Работа с Clipboard
Здравствуйте! Заметил, что если скопировать картинку (клик ПКМ->Копировать), в буфер обмена помещается строка с адресом этой картинки. Хочу...

25
 Аватар для Pro_grammer
6807 / 2839 / 527
Регистрация: 24.04.2011
Сообщений: 5,308
Записей в блоге: 10
11.11.2017, 10:12
Напрямую вряд ли, а вот через Picture запросто:
Visual Basic
1
2
Picture1.Picture = Clipboard.GetData
MsgBox Picture1.Point(10, 10)
Причем Picture может на форме быть невидимой.
1
0 / 0 / 0
Регистрация: 11.11.2017
Сообщений: 9
11.11.2017, 12:14  [ТС]
Спасибо за наводку, мысль была загонять в picturebox, но показалось, что выигрыша во времени исполнения не будет.
В связи с этим еще пара вопросов:
1. как распознать, что он мне выдает в MsgBox? Выдает восьмизначное число, и каковы значения конкретно по R,G,B? как-то по битам раскладывать что ли?
2. Какую прибавку примерно в скорости может дать такой метод по сравнению с записью-чтением на диск для обычного хард диска скоростью 7200 об/мин при условии, что это в цикле.
Спасибо.
0
Заблокирован
11.11.2017, 13:02
Цитата Сообщение от Gaskon Посмотреть сообщение
каковы значения конкретно по R,G,B?
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
 
Private Type RGBN
  R As Byte
  G As Byte
  B As Byte
  N As Byte
End Type
 
Private Sub Form_Load()
Dim c As RGBN
CopyMemory c, Picture1.Point(10, 10), 4
msgbox c.r,,"RED=" 'etc...
End Sub
0
0 / 0 / 0
Регистрация: 11.11.2017
Сообщений: 9
11.11.2017, 14:45  [ТС]
Цитата Сообщение от Остап Бонд Посмотреть сообщение
Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)
 
Private Type RGBN
  R As Byte
  G As Byte
  B As Byte
  N As Byte
End Type
 
Private Sub Form_Load()
Dim c As RGBN
CopyMemory c, Picture1.Point(10, 10), 4
msgbox c.r,,"RED=" 'etc...
End Sub
Работает только с первым пикселем по picture1.point(1,1), данные из программы и фотошопа совпадают(в фотошопе, я так понимаю, это будут координаты (0,0)), дальше по какому принципу идет-непонятно. Насколько я понимаю, начинает же с левого верхнего угла скриншота, но ставлю следующие пиксели-и данные вообще не ясно откуда.

Добавлено через 18 минут
И что это за тип RGBN, что значит в нем N? гугл не дал ничего внятного, я так понимаю, что программа идет с шагом 4, может в этом дело и она сбивается дальше первого пикселя? хотя заменял 4 на 3- не заработало...и (10,10) в примере-это же координаты x и y?

Добавлено через 26 минут
Нда, это удивительно, но грузить даже в невидимый picturebox оказалось дольше, чем писать в файл на диск и считывать из него примерно процентов на 40, в связи с чем вопрос снимается за неактуальностью, спасибо за помощь.
0
 Аватар для Pro_grammer
6807 / 2839 / 527
Регистрация: 24.04.2011
Сообщений: 5,308
Записей в блоге: 10
11.11.2017, 15:35
Цитата Сообщение от Gaskon Посмотреть сообщение
picturebox оказалось дольше
Там скорее всего очень тормозит Picture1.Point
Надо заменить на API
Visual Basic
1
2
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Color = GetPixel(Picture1.hdc, 10, 10) ' Средствами API
Это значительно быстрее работает.
0
0 / 0 / 0
Регистрация: 11.11.2017
Сообщений: 9
11.11.2017, 16:19  [ТС]
Цитата Сообщение от Pro_grammer Посмотреть сообщение
Там скорее всего очень тормозит Picture1.Point
Надо заменить на API
Visual Basic
1
2
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Color = GetPixel(Picture1.hdc, 10, 10) ' Средствами API
Это значительно быстрее работает.
Нет, принципиальной разности в скорости выполнения с предыдущим методом не заметил.
0
 Аватар для Alex77755
11525 / 3812 / 683
Регистрация: 13.02.2009
Сообщений: 11,229
11.11.2017, 17:54
не то написал
0
 Аватар для VBOrion
10 / 6 / 0
Регистрация: 06.11.2017
Сообщений: 21
11.11.2017, 23:57
Visual Basic
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
Option Explicit
 
Private Type RGBQUAD
  rgbBlue As Byte
  rgbGreen As Byte
  rgbRed As Byte
  rgbReserved As Byte
End Type
Private Type BITMAPINFOHEADER
  biSize As Long
  biWidth As Long
  biHeight As Long
  biPlanes As Integer
  biBitCount As Integer
  biCompression As Long
  biSizeImage As Long
  biXPelsPerMeter As Long
  biYPelsPerMeter As Long
  biClrUsed As Long
  biClrImportant As Long
End Type
Private Type BITMAPINFO
  bmiHeader As BITMAPINFOHEADER
  bmiColors As RGBQUAD
End Type
Private Declare Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
 
Private Sub Form_Load()
    Dim pix As RGBQUAD
    
    pix = GetPixelFromHBitmap(Clipboard.GetData().Handle, 390, 57)
    
    MsgBox "R: " & Hex(pix.rgbRed) & " G: " & Hex(pix.rgbGreen) & " B: " & Hex(pix.rgbBlue)
    
End Sub
 
Private Function GetPixelFromHBitmap( ByVal hBitmap As Long, ByVal x As Long, ByVal y As Long) As RGBQUAD
    Dim hdc As Long
    Dim info As BITMAPINFO
    Dim success As Boolean
    
    hdc = GetDC(0)
    
    info.bmiHeader.biSize = Len(info.bmiHeader)
    
    If GetDIBits(hdc, hBitmap, 0, 1, ByVal 0&, info, 0) Then
        
        If info.bmiHeader.biHeight > 0 Then
            
            y = info.bmiHeader.biHeight - y - 1
            
        End If
        
        Dim bits() As RGBQUAD
        
        ReDim bits(info.bmiHeader.biWidth - 1)
        
        info.bmiHeader.biBitCount = 32
        
        If GetDIBits(hdc, hBitmap, y, 1, bits(0), info, 0) Then
            
            GetPixelFromHBitmap = bits(x)
            success = True
            
        End If
        
    End If
    
    ReleaseDC 0, hdc
    
    If Not success Then
        Err.Raise 5
    End If
    
End Function
А вообще для чего требуется из буфера обмена? Можно получить скриншот используя GetDC(0) и BitBlt.
3
es geht mir gut
 Аватар для SoftIce
11274 / 4760 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439
12.11.2017, 00:21
Цитата Сообщение от Gaskon Посмотреть сообщение
нужно узнать значение в RGB палитре заданного пикселя в скриншоте экрана, сделанного посредством нажатия print screen

А зачем делать скриншот, а потом анализировать буфер ?
Можно же сразу определить цвет пикселя прямо на "экране".
0
es geht mir gut
 Аватар для SoftIce
11274 / 4760 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439
12.11.2017, 00:39
Цитата Сообщение от SoftIce Посмотреть сообщение
сразу определить цвет пикселя прямо на "экране".
Visual Basic
1
2
3
4
5
6
7
Private Declare Function CreateDC Lib "gdi32" Alias "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String, ByVal lpOutput As String, lpInitData) As Long
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Private Sub Command1_Click()
    Dim dM, scrColor As Long
    scrColor = GetPixel(CreateDC("DISPLAY", vbNullString, vbNullString, dM), 10, 110)   'Да простит меня компилятор за игнорирование структуры DEVMODE, она слишком большая :)
    BackColor = scrColor 'проверяем
End Sub
Миниатюры
Работа со скриншотом экрана в clipboard  
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
12.11.2017, 10:37
SoftIce, код содержит утечку ресурсов, должно быть DeleteDC.
DEVMODE и так не нужен для DISPLAY:
If lpszDriver is DISPLAY, lpInitData must be NULL; GDI then uses the display device's current DEVMODE.
Вместо создания нового DC лучше и быстрее брать уже готовый DC (GetDC/ReleaseDC).
GetPixel, если мне не изменяет память, довольно медленная операция (создание битмапа 1x1 пиксель, BitBlt в него, трансляция цвета, уничтожение временного битмапа), поэтому как предложил VBOrion, я бы для увеличения скорости использовал GetDiBits. Хотя еще можно попробовать использовать GetObject которая для DIB растров возвращает указатель на пиксели без всяких преобразований.
1
es geht mir gut
 Аватар для SoftIce
11274 / 4760 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439
12.11.2017, 12:46
Цитата Сообщение от The trick Посмотреть сообщение
SoftIce, код содержит утечку ресурсов, должно быть DeleteDC.
Да, я уж понял потом. Чего только в полночь не накосячишь...
0
0 / 0 / 0
Регистрация: 11.11.2017
Сообщений: 9
13.11.2017, 07:37  [ТС]
Спасибо за интерес к теме.
Смысл задачи-отследить происходящее на экране, понять что это и оперативно отреагировать, поэтому делать скриншот и выдергивать из буфера обмена абсолютно не обязательно, скорее даже лучше обойтись без этого, если возможно. Просто за незнанием другого способа решил воспользоваться таким.
А можно ли с примером привести оптимальный вариант?
Благодарю.
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
13.11.2017, 14:24
По мотивам кода VBOrion:
Visual Basic
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
Option Explicit
 
Private Const OBJ_BITMAP  As Long = 7
 
Private Type RGBQUAD
    rgbBlue         As Byte
    rgbGreen        As Byte
    rgbRed          As Byte
    rgbReserved     As Byte
End Type
Private Type BITMAPINFOHEADER
    biSize          As Long
    biWidth         As Long
    biHeight        As Long
    biPlanes        As Integer
    biBitCount      As Integer
    biCompression   As Long
    biSizeImage     As Long
    biXPelsPerMeter As Long
    biYPelsPerMeter As Long
    biClrUsed       As Long
    biClrImportant  As Long
End Type
Private Type BITMAPINFO
    bmiHeader       As BITMAPINFOHEADER
    bmiColors       As RGBQUAD
End Type
 
Private Declare Function GetDIBits Lib "gdi32" ( _
                         ByVal aHDC As Long, _
                         ByVal hBitmap As Long, _
                         ByVal nStartScan As Long, _
                         ByVal nNumScans As Long, _
                         ByRef lpBits As Any, _
                         ByRef lpBI As BITMAPINFO, _
                         ByVal wUsage As Long) As Long
Private Declare Function GetDC Lib "user32" ( _
                         ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" ( _
                         ByVal hwnd As Long, _
                         ByVal hDC As Long) As Long
Private Declare Function GetCurrentObject Lib "gdi32" ( _
                         ByVal hDC As Long, _
                         ByVal uObjectType As Long) As Long
 
Private Sub Form_Load()
    Dim tScreenshot()   As RGBQUAD
    
    If Not TakeScreenShot(tScreenshot()) Then
        MsgBox "TakeScreenShot failed"
        Exit Sub
    End If
    
    ' // В массиве tScreenshot все пиксели экрана.
    ' // Получаем доступ к 414;54
    
    MsgBox "R: " & Hex(tScreenshot(414, 54).rgbRed) & _
           " G: " & Hex(tScreenshot(414, 54).rgbGreen) & _
           " B: " & Hex(tScreenshot(414, 54).rgbBlue)
 
End Sub
 
Private Function TakeScreenShot( _
                 ByRef tBits() As RGBQUAD) As Boolean
    Dim hDC     As Long
    Dim hBmp    As Long
    Dim tBI     As BITMAPINFO
    
    hDC = GetDC(0)
    
    If hDC = 0 Then
        MsgBox "GetDC failed " & Err.LastDllError
        Exit Function
    End If
    
    hBmp = GetCurrentObject(hDC, OBJ_BITMAP)
    
    If hBmp = 0 Then
        MsgBox "GetCurrentObject failed " & Err.LastDllError
        GoTo CleanUp
    End If
    
    tBI.bmiHeader.biSize = Len(tBI.bmiHeader)
    
    If GetDIBits(hDC, hBmp, 0, 1, ByVal 0&, tBI, 0) = 0 Then
        MsgBox "GetDIBits failed " & Err.LastDllError
        GoTo CleanUp
    End If
 
    tBI.bmiHeader.biHeight = -Abs(tBI.bmiHeader.biHeight)
    tBI.bmiHeader.biBitCount = 32
    tBI.bmiHeader.biCompression = 0
    
    ReDim tBits(tBI.bmiHeader.biWidth - 1, (-tBI.bmiHeader.biHeight) - 1)
 
    If GetDIBits(hDC, hBmp, 0, -tBI.bmiHeader.biHeight, tBits(0, 0), tBI, 0) = 0 Then
        MsgBox "GetDIBits failed " & Err.LastDllError
        GoTo CleanUp
    End If
    
    TakeScreenShot = True
    
CleanUp:
    
    ReleaseDC 0, hDC
       
End Function
2
0 / 0 / 0
Регистрация: 11.11.2017
Сообщений: 9
13.11.2017, 18:20  [ТС]
Знаете, а метод, предложенный SoftIce
Private Declare Function CreateDC Lib "gdi32" Alias "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String, ByVal lpOutput As String, lpInitData) As Long
Private Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Private Sub Command1_Click()
Dim dM, scrColor As Long
scrColor = GetPixel(CreateDC("DISPLAY", vbNullString, vbNullString, dM), 10, 110) 'Да простит меня компилятор за игнорирование структуры DEVMODE, она слишком большая
BackColor = scrColor 'проверяем
End Sub
оказался самым быстрым. В связи с этим вопрос:как его подкорректировать дабы устранить утечку ресурсов? Добавить DeleteDC?
Но куда его впихнуть?

Добавлено через 19 минут
А вот со стабильностью данного метода странные вещи произошли, после цикла в 10000 окно проекта просто заглючило.
0
es geht mir gut
 Аватар для SoftIce
11274 / 4760 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439
13.11.2017, 19:58
Цитата Сообщение от Gaskon Посмотреть сообщение
после цикла в 10000 окно проекта просто заглючило
Память утекла ? Поэтому и нужен DeleteDC
0
Фриланс Pascal/Delphi etc
 Аватар для ILinker
67 / 73 / 16
Регистрация: 25.11.2016
Сообщений: 263
13.11.2017, 21:05
А что нельзя 1 раз создать битмап и на него блиттить DC экрана?
0
 Аватар для VBOrion
10 / 6 / 0
Регистрация: 06.11.2017
Сообщений: 21
13.11.2017, 21:31
Цитата Сообщение от Gaskon Посмотреть сообщение
оказался самым быстрым. В связи с этим вопрос:как его подкорректировать дабы устранить утечку ресурсов? Добавить DeleteDC?
Но куда его впихнуть?
Для произвольного пикселя можно и GetPixel использовать, а вот для группы - GetDiBits .
0
es geht mir gut
 Аватар для SoftIce
11274 / 4760 / 1183
Регистрация: 27.07.2011
Сообщений: 11,439
13.11.2017, 21:34
Цитата Сообщение от Gaskon Посмотреть сообщение
после цикла в 10000
Да, кстати, Вы что, весь этот код в цикл засунули?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
13.11.2017, 21:34
Помогаю со студенческими работами здесь

Работа с классом Clipboard
Ребят, у меня такая проблема: недавно решил написать программку, которая в частности, работает с буфером обмена: помещает в него список...

Работа с Буфером обмена (Clipboard)
Всем привет! Ребята, в простом не могу найти решение. Подскажите, почему не работает. Мне нужно скопировать в "Буфер...

Работа с Clipboard. Как убрать мерцающую рамку?
При работе (Excel)макроса, внутри создаваемого документа происходит запись в Clipboard. При просмотре документа последняя скопированная в...

Ошибка при работе с Clipboard: "Сannot open clipboard. Отказано в доступе."
Хотел написать программу для автоматической замены текста в буфере обмена, но при обращении к буферу получаю ошибку "Сannot open...

Работа с разрешением экрана
Здравствуйте! Столкнулась с такой проблемой. Нужно создать cmd-файл для изменения разрешения экрана, и записать параметры текущего...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru