Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.83/64: Рейтинг темы: голосов - 64, средняя оценка - 4.83
1 / 1 / 0
Регистрация: 23.02.2017
Сообщений: 17

Скриншот, printscreen

05.03.2017, 23:11. Показов 13025. Ответов 48
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток уважаемые форумчане.
В общем стоит задача сделать скриншот экрана, поскольку я с программированием на этапе знакомства решил попробовать написать программу которая сделает скриншот, потом будет обрезать участки этого изображения и сравнивать с шаблонами (что-то типа разгадки несложной капчи ).
Я еще не понимаю как эти шаблоны создавать но одно мне стало ясно: в первую очередь нужно сделать скриншот и сохранить его на компьютер.
Так вот гуляя по просторам интернета я несколько дней читал как это воплотить в реальность, этот самый скриншот.
Было много примеров кода.
И тут я наткнулся на тему на этом же форуме где светила программирования решали эту же задачу в далеком 2013 году.
Мои логические выводы приняли решение использовать этот код:
C++
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
inline int GetFilePointer(HANDLE FileHandle){
    return SetFilePointer(FileHandle, 0, 0, FILE_CURRENT);
}
 
bool SaveBMPFile(char *filename, HBITMAP bitmap, HDC bitmapDC, int width, int height){
    bool Success=0;
    HBITMAP OffscrBmp=NULL;
    HDC OffscrDC=NULL;
    LPBITMAPINFO lpbi=NULL;
    LPVOID lpvBits=NULL;
    HANDLE BmpFile=INVALID_HANDLE_VALUE;
    BITMAPFILEHEADER bmfh;
    if ((OffscrBmp = CreateCompatibleBitmap(bitmapDC, width, height)) == NULL)
        return 0;
    if ((OffscrDC = CreateCompatibleDC(bitmapDC)) == NULL)
        return 0;
    HBITMAP OldBmp = (HBITMAP)SelectObject(OffscrDC, OffscrBmp);
    BitBlt(OffscrDC, 0, 0, width, height, bitmapDC, 0, 0, SRCCOPY);
    if ((lpbi = (LPBITMAPINFO)(new char[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)])) == NULL) 
        return 0;
    ZeroMemory(&lpbi->bmiHeader, sizeof(BITMAPINFOHEADER));
    lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    SelectObject(OffscrDC, OldBmp);
    if (!GetDIBits(OffscrDC, OffscrBmp, 0, height, NULL, lpbi, DIB_RGB_COLORS))
        return 0;
    if ((lpvBits = new char[lpbi->bmiHeader.biSizeImage]) == NULL)
        return 0;
    if (!GetDIBits(OffscrDC, OffscrBmp, 0, height, lpvBits, lpbi, DIB_RGB_COLORS))
        return 0;
    if ((BmpFile = CreateFile(filename,
                        GENERIC_WRITE,
                        0, NULL,
                        CREATE_ALWAYS,
                        FILE_ATTRIBUTE_NORMAL,
                        NULL)) == INVALID_HANDLE_VALUE)
        return 0;
    DWORD Written;
    bmfh.bfType = 19778;
    bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
    if (!WriteFile(BmpFile, &bmfh, sizeof(bmfh), &Written, NULL))
        return 0;
    if (Written < sizeof(bmfh)) 
        return 0; 
    if (!WriteFile(BmpFile, &lpbi->bmiHeader, sizeof(BITMAPINFOHEADER), &Written, NULL)) 
        return 0;
    if (Written < sizeof(BITMAPINFOHEADER)) 
        return 0;
    int PalEntries;
    if (lpbi->bmiHeader.biCompression == BI_BITFIELDS) 
        PalEntries = 3;
    else PalEntries = (lpbi->bmiHeader.biBitCount <= 8) ?
                      (int)(1 << lpbi->bmiHeader.biBitCount) : 0;
    if(lpbi->bmiHeader.biClrUsed) 
    PalEntries = lpbi->bmiHeader.biClrUsed;
    if(PalEntries){
    if (!WriteFile(BmpFile, &lpbi->bmiColors, PalEntries * sizeof(RGBQUAD), &Written, NULL)) 
        return 0;
        if (Written < PalEntries * sizeof(RGBQUAD)) 
            return 0;
    }
    bmfh.bfOffBits = GetFilePointer(BmpFile);
    if (!WriteFile(BmpFile, lpvBits, lpbi->bmiHeader.biSizeImage, &Written, NULL)) 
        return 0;
    if (Written < lpbi->bmiHeader.biSizeImage) 
        return 0;
    bmfh.bfSize = GetFilePointer(BmpFile);
    SetFilePointer(BmpFile, 0, 0, FILE_BEGIN);
    if (!WriteFile(BmpFile, &bmfh, sizeof(bmfh), &Written, NULL))
        return 0;
    if (Written < sizeof(bmfh)) 
        return 0;
 
 
    CloseHandle (BmpFile);
 
    delete [] (char*)lpvBits;
    delete [] lpbi;
 
    DeleteDC (OffscrDC);
    DeleteObject (OffscrBmp);
 
 
    return 1;
}
 
bool ScreenCapture(int x, int y, int width, int height, char *filename, HWND hwnd){
    
 
    HDC hDC= GetDC(hwnd);
    HDC hDc = CreateCompatibleDC(hDC);    
    
    
    HBITMAP hBmp = CreateCompatibleBitmap(hDC, width, height);   
    
 
    HGDIOBJ old= SelectObject(hDc, hBmp);   
    BitBlt(hDc, 0, 0, width, height, hDC, x, y, SRCCOPY);  
    
    bool ret = SaveBMPFile(filename, hBmp, hDc, width, height); 
 
 
    SelectObject(hDc, old);
 
    DeleteObject(hBmp);  
 
    DeleteDC (hDc);
    ReleaseDC (hwnd, hDC);
     
    return ret;
}
Подскажите пожалуйста как запустить этот код, какие библиотеки нужно подключить, и почему тут нет функции main, ведь все учебники говорят что без нее выполнение программы невозможно.
Работаю на Dev-C++
Благодарен за любую помощь о добрые люди
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
05.03.2017, 23:11
Ответы с готовыми решениями:

Скриншот с GDI+
Доброго времени суток. Нашел код на этом форуме который делает скрин экрана. Пишу на VS2010 код у меня заработал только когда создал...

Не выводится скриншот на просмотр
В теле функции WinMain() я создаю все контексты после создания главного окна (CreateWindow) ResX = GetSystemMetrics(SM_CXSCREEN); ...

Скриншот экрана и его вывод
Задумал написать прикол - делается скриншот экрана и сразу же выводится. Создается ощущение подвисания компьютера (но можно выключить через...

48
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
07.05.2020, 19:28
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от GoodWeather Посмотреть сообщение
SelectObject() не рисует, а "соединяет" HDC с HGDIOBJ - например с HBITMAP.
.
А что значит соединяет ? А результат соединения какой ожидается ?

Какая функция в итоге заполняет DB-буфер по указателю ? Bitbit ? Или все гораздо сложнее ?

Добавлено через 39 минут
Я тогда вообще не понимаю, если функция CreateDIBSection - создает по сути буфер в соответствии с заполненными параметрами из структуры BITMAPINFO, зачем первый аргументом в эту функцию нужно передавать дескриптор контекста устройства, что функция с ним делает.
0
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
07.05.2020, 20:42
Это надо читать про основы Windows GDI
Windows GDI (или GDI32) работает только через понятие "Device Context". Переменные типа HDC служат для хранения описателя (хэндла) конкретного "Device Context".
Само значение переменной HDC никому не ведомо и может быть как индексом какого-то внутреннего массива чего-то, так каким-то внутренним указателем на что-то.
Что именно это такое и как устроено внутри кода операционной системы - никто не скажет, типа коммерческая тайна. Считается "чёрный ящиком".
Прикладные программы могут лишь получать и использовать значения HDC, выданные операционной системой.

"Device Context" (HDC) имеет "текущие HGDIOBJ объекты" - каждого из типов по одному: Битмап, Палитра, Перо (ручка/контуры), Кисть (заполнение/заливка), Шрифт, Регион и Фигура (набор Форм).
Про них говорят "выбрано в HDC".
  • Если мы рисуем линию - она будет нарисована: текущим выбранным Пером, в текущем выбранном Регионе.
  • Если мы рисуем прямоугольник - он будет нарисован: текущим выбранным Пером, залит текущей выбранной Кистью, в текущем выбранном Регионе.
  • Если мы выводим текст - он будет нарисован: текущим выбранным Шрифтом, на текущем фоне, текущим цветом, в текущем выбранном Регионе.
  • и.т.д.и.т.п.
Если в HDC был выбран Битмап - то всё появится и на нём. Правда не во всякий HDC можно выбирать битмап, и битмап может быть выбран только в один HDC в один момент времени.
При создании нового HDC в него будут выбраны все обязательные объекты как объекты по умолчанию ("стоковые" объекты). Например Битмап будет монохромным (однобитным) и размерами 1x1.

Функция SelectObject() меняет текущий объект на тот что мы попросили, при этом возвращая старый (заменённый) текущий объект.
Считается за правило после окончания рисования возвращать старые объект обратно как было. Чтоб никто из использующих HDC не вредил друг-другу.

При помощи SelectObject() устанавливаем связь между HBITMAP и HDC.
Функция BitBlt() копирует заданный участок изображения с одного HDC на заданный участок другого HDC. Даже если в них нет никаких битмапов (например контролы в окнах).
Если же в HDC назначения (куда копируется) будет выбран битмап - данные изображения скопируются и в него тоже.

Добавлено через 3 минуты
Всё такое надо просто смотреть в справке. Там либо объясняется, либо будет просто "делайте так-то и всё тут".
https://docs.microsoft.com/en-... dibsection
hdc
  • A handle to a device context. If the value of iUsage is DIB_PAL_COLORS, the function uses this device context's logical palette to initialize the DIB colors.
Видимо вместо usage написали iUsage... Если третий параметр указан как DIB_PAL_COLORS, то оно будет брать оттуда палитру...

Добавлено через 11 минут
Так что по-идее оно в данном случае не нужно, но в справке нет пояснений можно ли передавать NULL, поэтому нам проще передавать, тем более что оно у нас и так уже есть.
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
27.05.2020, 20:47
Цитата Сообщение от GoodWeather Посмотреть сообщение
Указатель на буфер объявляют обычно как-то так:
C++
1
unsigned char* my_DIB_data;
А в функцию передают так:

C++
1
... , (VOID**)&my_DIB_data , ...
Все мозги уже сломал, не могу понять: функция CreateDIBSection принимает 4ым параметром:
Указатель на переменную, которая получает указатель на расположение значений битов DIB.
Объявив:
C++
1
char* my_DIB_data
Выделился участок памяти куда будет помещен адрес на выделенную память под массив char`ов.

Не могу понять, что происходит, когда указатель приводится к void**.

Просто ради понимания я пытался передавать в функцию просто объявленный указатель на указатель на void:
C++
1
2
3
4
5
void** my_char_DIB_p_p = 0;
 
HBITMAP HBITMAP_DIBSection = CreateDIBSection(HDC_CreateCompatibleDC, &My_struct_BITMAPINFO, DIB_RGB_COLORS, my_char_DIB_p_p , NULL, NULL); 
 
cout<<my_char_DIB_p_p;
Функция принимает этот указатель, не вызывает ошибки, но не заполняет его. Я ожидаю увидеть, что функция поместит в my_char_DIB_p_p адрес указателя на void, в котором будет хранится адрес на сам буффер char`ов.

То есть чтобы вывести адрес указателя void:
C++
1
cout<<my_char_DIB_p_p;   //таким образом я должен вывести адрес на указатель
И он выводится, но нулевой, то есть функция ничего не поместила в мой my_char_DIB_p_p.

Я не понимаю, как мне в явном виде пережать параметр в функцию и какой тогда должен быть этот параметр.
0
фрилансер
 Аватар для Алексей1153
6455 / 5657 / 1129
Регистрация: 11.10.2019
Сообщений: 15,070
27.05.2020, 21:26
Цитата Сообщение от Optimus11 Посмотреть сообщение
функция CreateDIBSection принимает 4ым параметром:
Указатель на переменную, которая получает указатель на расположение значений битов DIB.
вернёт указатель на внутреннюю выделенную память. Но поскольку функция будет менять значение внешней переменной-указателя, нужно передать указатель на эту переменную. Поэтому получается указатель на указатель. Приводить к void** не нужно, оно уже и так такой тип будет иметь при взятии адреса



Добавлено через 2 минуты
void* my_char_DIB_p_p = 0;

HBITMAP HBITMAP_DIBSection = CreateDIBSection(HDC_CreateCompatibleDC, &My_struct_BITMAPINFO, DIB_RGB_COLORS, &my_char_DIB_p_p , NULL, NULL);
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
27.05.2020, 21:53
Цитата Сообщение от Алексей1153 Посмотреть сообщение
вернёт указатель на внутреннюю выделенную память. Но поскольку функция будет менять значение внешней переменной-указателя, нужно передать указатель на эту переменную. Поэтому получается указатель на указатель. Приводить к void** не нужно, оно уже и так такой тип будет иметь при взятии адреса
;
Спасибо!
После Вашего ответа понял, что я не так делал:

C++
1
2
3
void** my_char_DIB_p_p = 0;
 
HBITMAP HBITMAP_DIBSection = CreateDIBSection(HDC_CreateCompatibleDC, &My_struct_BITMAPINFO, DIB_RGB_COLORS, my_char_DIB_p_p , NULL, NULL);
Я объявил указатель на указатель и в качестве значения поместил туда ноль. Переда в функцию my_char_DIB_p_p - я передал не адрес указателя, а ноль , соответственно функция и не смогла поместить в ноль -- > адрес на буфер данных.
Странно только, что функция ошибку не выдала, видимо для нее - это не ошибка.
0
фрилансер
 Аватар для Алексей1153
6455 / 5657 / 1129
Регистрация: 11.10.2019
Сообщений: 15,070
27.05.2020, 22:08
Цитата Сообщение от Optimus11 Посмотреть сообщение
передал не адрес указателя, а ноль
всё верно ))

Цитата Сообщение от Optimus11 Посмотреть сообщение
Странно только, что функция ошибку не выдала, видимо для нее - это не ошибка.
не ошибка, ведь самой функции этот внешний указатель до фени. Если пользователь хочет узнать адрес - он передаёт указатель на свой указатель. Если не хочет - передаёт нулевой указатель
1
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
27.05.2020, 23:32
Цитата Сообщение от Optimus11
функция CreateDIBSection принимает 4ым параметром:
Указатель на переменную, которая получает указатель на расположение значений битов DIB.
Функция принимает указатель (валидный) на переменную типа "указатель". То есть реальный указатель на участок памяти размером в указатель.
Цитата Сообщение от Optimus11
...я пытался передавать в функцию просто объявленный...
А у вас вышло объявление переменной типа "указатель на указатель". Но она указывает в пустоту.
Можно конечно было выделить память вручную, но удобнее же просто объявить переменную типа "указатель" и передавать указатель на неё.
Цитата Сообщение от Optimus11
Странно только, что функция ошибку не выдала, видимо для нее - это не ошибка.
Точно не помню, но вроде бы просто делается вывод что вам не нужна данная информация.

Добавлено через 1 минуту
Её же можно получить в любой момент позднее.
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
01.06.2020, 19:49
Немного не по теме: а как Windows делает скриншот рабочего стола из двух мониторов с разной настройкой битности ?

Ну то есть, грубо говоря, я просто нажал кнопку принтскреен, windows в буфер поместила массив с пикселями, причем часть массива описывает к примеру пиксель 16-битный, вторая часть массива 32-битный. Предположим далее я вставляя их в paint и сохраняю, ка файл bmp 32-разрядный. Но часть то массива описывает пиксель 16-ю битами.
Получается при сохранении эти 16 бит преобразовываются в 32-разрядный массив и таким образом сохраняются ?
0
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
02.06.2020, 02:03
хм... Вроде бы как у всех мониторов один общий HDC. По крайней мере раньше всегда было так.

Разные области одного и того же массива не могут быть разного типа. Наверняка HDC будет максимальной битности.
И просто некоторые мониторы могут быть аппаратно в другом режиме... А вот какой сигнал они получают по проводу от видеокарты - фиг знает...

Добавлено через 1 минуту
Где-то между "итоговым битмапом всего рабочего стола" и "конечными пикселями мониторов" оно как-то конвертится...

Добавлено через 1 минуту
А вообще редко у кого много мониторов. Я вот даже потестить не смогу никак. Ещё поискать надо, где одолжить у кого лишний...

Добавлено через 7 минут
Где-то же в ОС производится разделение по мониторам? Вероятно уже там и подстраивают.
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
03.06.2020, 17:19
Я сдаюсь:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
VOID** my_char_DIB_p_p = new void*;    
 
HBITMAP DIBSection = CreateDIBSection(HDC_CreateCompatibleDC, &My_struct_BITMAPINFO, DIB_RGB_COLORS, my_char_DIB_p_p, NULL, NULL);
 
SelectObject();
BitBlt();
 
/////////////////////////////////////////////////////
 
 
char* chars = (char*)*my_char_DIB_p_p;  //Создам указатель и просвою ему значение участка памяти из my_char_DIB_p_p, которое заполнила функция CreateDIBSection
 
for (int i = 0; i < 10; i++)  //Проверю точно ли там помещенные какие то данные, выведу первые 10 байт
{
cout<<chars[i] << endl;              //Выводятся данные есть
}
До этого момента все замечательно. Я использовал данные, теперь мне она больше не нужны и память нужно освободить:

C++
1
2
delete [] chars;
// или delete[]  (char*)*my_char_DIB_p_p;
И все на этой строке возникает ошибка "процесс завершает работу с кодом -1073741819."

Я не понимаю почему ? chars - содержит в себе значение адреса который указывает на память выделенную через CreateDIBSection, я просто хочу теперь освободить эту память. В чем же ошибка то ?
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
03.06.2020, 19:03
Цитата Сообщение от Optimus11 Посмотреть сообщение
В чем же ошибка то ?
В том, что вы пытаетесь "удалить" то, что не "создавали".
Всё что вы можете удалить, это delete my_char_DIB_p_p;
Хотя не понятно зачем вообще выделять память под один указатель в куче.
1
фрилансер
 Аватар для Алексей1153
6455 / 5657 / 1129
Регистрация: 11.10.2019
Сообщений: 15,070
03.06.2020, 19:06
Optimus11, char* chars - переменная, которая указывает на тип char . А my_char_DIB_p_p указывает на тип void*. Ты насильно приводишь указатель одного типа к другому и пытаешься там память освободить, при этом ещё и указывая []

зачем ты всё это делаешь?
Вот без всякой магии:

C++
1
2
3
4
5
6
7
8
9
10
VOID* my_char_DIB_p_p=0;
HBITMAP DIBSection = CreateDIBSection(HDC_CreateCompatibleDC, &My_struct_BITMAPINFO, DIB_RGB_COLORS, &my_char_DIB_p_p, NULL, NULL);
 
SelectObject(....);
BitBlt(....);
 
for (int i = 0; i < 10; i++)
{
   std::cout<<((char*)my_char_DIB_p_p)[i]<< std::endl;
}
кстати, а почему именно 10 ?

никакого delete не надо, удаление производится вызовом DeleteObject для хендла HBITMAP
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
03.06.2020, 19:07
[QUOTE=zayats80888;14615993]В том, что вы пытаетесь "удалить" то, что не "создавали".
Всё что вы можете удалить, это delete my_char_DIB_p_p;
А как тогда можно освободить эту память? Или этого нельзя принципе ?

Цитата Сообщение от zayats80888 Посмотреть сообщение
Хотя не понятно зачем вообще выделять память под один указатель в куче.
Ну это так просто.
0
03.06.2020, 19:09

Не по теме:

Цитата Сообщение от Optimus11 Посмотреть сообщение
А как тогда можно освободить эту память? Или этого нельзя принципе ?
Выше уже написали.

0
фрилансер
 Аватар для Алексей1153
6455 / 5657 / 1129
Регистрация: 11.10.2019
Сообщений: 15,070
03.06.2020, 19:10
Цитата Сообщение от Optimus11 Посмотреть сообщение
//Проверю точно ли там помещенные какие то данные, выведу первые 10 байт
можно просто в отладчике остановиться и посмотреть в редакторе дампа памяти, что там лежит
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
03.06.2020, 19:29
Цитата Сообщение от Алексей1153 Посмотреть сообщение
никакого delete не надо, удаление производится вызовом DeleteObject для хендла HBITMAP
А если я все это делаю в отдельной функции и функция должна возвратить указатель на этот массив ?
То есть мне этот массив нужно будет уже освобождать из main`а получается.
0
фрилансер
 Аватар для Алексей1153
6455 / 5657 / 1129
Регистрация: 11.10.2019
Сообщений: 15,070
03.06.2020, 19:40
Optimus11, достаточно помнить только хендл HBITMAP. При помощи хендла можно и работать с этим битмапом и удалить его

Добавлено через 4 минуты
Optimus11, аналогии из того же WinAPI:

HWND - хендл окна. Через него производится вся работа с окном
HDC - хендл контекста устройства

для каждого типа хендла свой набор WinAPI-функций
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
03.06.2020, 19:54
Спасибо!
0
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
03.06.2020, 20:23
Дак напишите класс, который будет хранить и TDIBSection и HBITMAP и Scan0 и возможно даже HDC (ну или метод чтоб получать его).

Добавлено через 1 минуту
Цитата Сообщение от Optimus11 Посмотреть сообщение
я просто хочу теперь освободить эту память
Только через DeleteObject() для HBITMAP.
И оно "помечает" на освобождение, не гарантируется что непосредственно само освобождение будет моментально.
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
11.06.2020, 20:14
Без подсказки не разобраться

Снятие скриншота экрана прексрано работает, но в сегодня вдруг мне подумалось просто протестириовать взятие скриншотоа в цикле на 10 тыщ раз, так на всякий случай и вот видимо не зря, потому что то на некотором элементе цикла вылазет ошибка:
C++
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
HDC HDC_Screen1;
HDC HDC_CreateCompatibleDC;
BITMAPINFO My_struct_BITMAPINFO;
HBITMAP HBITMAP_DIBSection;
VOID* my_char_DIB_p_p;
 
 
    for (int i = 0; i < 10000; i++)       //Цикл
    {
        HDC_Screen1 = GetDC(NULL); 
        if (HDC_Screen1 == NULL)
        {
            cout << "Error:GetDC==NULL" << endl;
        }
 
        HDC_CreateCompatibleDC = CreateCompatibleDC(HDC_Screen1);  
        if (HDC_CreateCompatibleDC == NULL)
        {
            cout << "Error:CreateCompatibleDC==NULL" << endl;
        }
 
        //////////////////////////////////////////
            //Заполним стуктуру BITMAPINFO:
        My_struct_BITMAPINFO;
 
        My_struct_BITMAPINFO.bmiHeader.biSize = sizeof(My_struct_BITMAPINFO.bmiHeader);  
        My_struct_BITMAPINFO.bmiHeader.biWidth = 500;                           
        My_struct_BITMAPINFO.bmiHeader.biHeight = 500;                          
        My_struct_BITMAPINFO.bmiHeader.biPlanes = 1;                                   
        My_struct_BITMAPINFO.bmiHeader.biBitCount = GetDeviceCaps(GetDC(NULL), BITSPIXEL);           
        My_struct_BITMAPINFO.bmiHeader.biCompression = BI_RGB;                         
        My_struct_BITMAPINFO.bmiHeader.biSizeImage = 500 * 500 * (GetDeviceCaps(GetDC(NULL), BITSPIXEL)) / 8;     
        //My_struct_BITMAPINFO.bmiHeader.biXPelsPerMeter =
        //My_struct_BITMAPINFO.bmiHeader.biYPelsPerMeter =
        My_struct_BITMAPINFO.bmiHeader.biClrUsed = 0;
        My_struct_BITMAPINFO.bmiHeader.biClrImportant = 0;
        //My_struct_BITMAPINFO.bmiColors =
        //////////////////////////////////////////
 
 
        HBITMAP_DIBSection = CreateDIBSection(HDC_CreateCompatibleDC, &My_struct_BITMAPINFO, DIB_RGB_COLORS, &my_char_DIB_p_p, NULL, NULL); 
        if (HBITMAP_DIBSection == NULL)
        {
            cout << "Error:CreateDIBSection==NULL: GetLastError: " + to_string(GetLastError()) << endl;
        }
 
        ReleaseDC(NULL, HDC_Screen1);            
        DeleteDC(HDC_CreateCompatibleDC);          
        DeleteObject(HBITMAP_DIBSection);
        }
    }
И вот на на 4997 номере цикла вылетает ошибка от функции CreateDIBSection:
C++
1
GetLastError = 87
ERROR_INVALID_PARAMETER
87 (0x57)
Неверный параметр.
Какой параметр не верный, почему не верный. Почему до этого 4996 раз был верный, а на 4997 не верный. Причем каждый раз срабатывает именно на 4997 разе.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
11.06.2020, 20:14
Помогаю со студенческими работами здесь

Скриншот с окна Internet Explorer 8
есть код, который делает снимок с окна IE(причём полностью всего, а не только содержимого страницы - надо именно так) . Всё хорошо...

Сделать скриншот средствами WinAPI
Может есть у кого код функции, чтобы делала скрин рабочего стола и сохраняла в JPG файл ? делаю средствами DirectX ... без него нужно...

Получить скриншот посредством GetDC
Мне нужно прочитать содержимое экрана. Я выяснил, что для этого нужно использовать функцию GetDC(NULL). А потом не забыть сделать...

Скриншот клиентской части приложения по координатам
Была задача реализовать функцию, которая делает скрин клиентской части приложения по координатам. Я даже не знаю с чего начать, подскажите...

Как создать скриншот части экрана?
Можно весь экран заскриншотить потому, что это частный случай части. Но дело не в этом. Скриншот ведь предполагает какой-то файл...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru