С++ + WinAPI (захват изображения)
Начнём с того, что после очередного обновления VS Community 2022 перестала работать на Windows 7. Просмотрев список «системных требований» быстро выяснилось, что на семёрке новая студия работать совсем не обязана. Well, shit…
Но бежать вприпрыжку перелезать на уютненькую десяточку или, прости Пажитнов, садиться на палки (барабанные) — спасибо, видели, пакетик для рвоты уже полон, так что решительным решением откатываемся на VS Community 2019 и не парим себе мозги — для наших грязных намерений великих целей этого более чем достаточно.
Итак, с нытьём закончили, переходим к делу. В текущей статье мы разберемся как нам делать скриншотики, не более того.
Для этого нам достаточно пустого как наше светлое будущее проекта:
Добавим воды файл для кода:
Итак, для начала ёбнем по Тбилиси попробуем сделать скриншот всей области рабочего стола:
#include <Windows.h> //это нам нужно для взаимодействия с WinAPI
HWND hwnd; //типо наше «окошно»
int a0, a1, b0, b1, w, h; //да, вся это шалупонь целочисленная, и координаты, и ширина, и высота
int main () { //погнали
hwnd = GetConsoleWindow (); //да, у нас консоль
ShowWindow (hwnd, SW_HIDE ()); //но мы её тут же прячем с глаз долой
a0 = GetSystemMetrics (SM_XVIRTUALSCREEN); //и берем
b0 = GetSystemMetrics (SM_YVIRTUALSCREEN); //координаты
a1 = GetSystemMetrics (SM_CXVIRTUALSCREEN); //крайних точек
b1 = GetSystemMetrics (SM_CYVIRTUALSCREEN); //нашего экрана
w = a1 — a0; //рассчитываем длину и ширину
h = b1 — b0; //срочно зовите Перельмана!
HDC hScreen = GetDC (NULL); //получаем контекст
HDC hDC = CreateCompatibleDC (hScreen); //и создаем
HBITMAP hbitmap = CreateCompatibleBitmap (hScreen, w, h); //картинку
HGDIOBJ myobj = SelectObject (hDC, hbitmap); //далее выбираем
BOOL bRet = BitBlt (hDC, 0, 0, w, h, hScreen, a0, b0, SRCCOPY); //и заполняем пикселями
//скопируем, наверное картинку в буфер обмена пока
OpenClipboard (NULL); //открываем буфер
EmptyClipboard (); //очищаем
SetClipboardData (CF_BITMAP, hbitmap); //вносим инфу
CloseClipboard (); //не забываем закрыть
return 0; //фсё
}
Запустим бумеранг сборку и проверим работу вот этого всего:
Вы резонно заметите, что не хотите показывать своих 2D-тяночек, которые у вас там на рабочем столе или ещё чего. Ну, что ж…
В таком случае мы можем делать скриншот только отдельно взятого окна, создаем проект всё по той же гиблой схеме и немного наклоняем ось земли изменяем код:
#include <Windows.h> //это нам нужно для взаимодействия с WinAPI
int a0, a1, b0, b1, w, h; //тут всё то же самое
int main () { //опять же стартуем
FreeConsole (); //консольку, в принципе, можно и так убрать
keybd_event (VK_MENU, 0, 0, 0); //только вот keybd_event (VK_TAB, 0, 0, 0); //она, сволочь
keybd_event (VK_TAB, 0, KEYEVENTF_KEYUP, 0); //убирает фокус с окна
keybd_event (VK_MENU, 0, KEYEVENTF_KEYUP, 0); //так что мы обратно альт-табаемся
Sleep (500); //и немножечко ждём (да, вроде костыль, а вроде и хитрость)
RECT rcClient; //определяем прямоугольник, да можно через rcWindow, но я захотел так HWND hWnd; //наше окно
hWnd = GetForegroundWindow (); //берем то, что сейчас активно
GetClientRect (hWnd, &rcClient); //и забираем его крайние точки
a0 = rcClient.left; //да, кстати
b0 = rcClient.top; //а вот a1 = rcClient.right; //и наши
b1 = rcClient.bottom; //точки
w = a1 — a0; //тут всё так же h = b1 — b0; //очень сложные рассчеты
HDC hScreen = GetDC (NULL); //контекст
HDC hDC = CreateCompatibleDC (hScreen); //далее
HBITMAP hbitmap = CreateCompatibleBitmap (hScreen, w, h); //картинка
HGDIOBJ myobj = SelectObject (hDC, hbitmap); //прямо как в BOOL bRet = BitBlt (hDC, 0, 0, w, h, hScreen, a0, b0, SRCCOPY); //примере выше
OpenClipboard (NULL); //опять
EmptyClipboard (); //копируем
SetClipboardData (CF_BITMAP, hbitmap); //картинку
CloseClipboard (); //в буфер
return 0; //да, я обленился
}
Проверяем погоду за окном результат:



