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

Скриншот, printscreen

05.03.2017, 23:11. Показов 12933. Ответов 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
284 / 232 / 114
Регистрация: 07.09.2016
Сообщений: 584
05.03.2017, 23:35
Лучший ответ Сообщение было отмечено Boyard1 как решение

Решение

похоже вы совсем не шарите, ибо делается все проще некуда. см в конец кода:
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
111
112
113
114
115
116
117
118
#include <windows.h>
 
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 = CreateFileA(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;
}
 
int main()
{
  ScreenCapture(0, 0, 100, 100, "d://tmp/screen.bmp", NULL);
  return 0;
}
2
Джоуи
 Аватар для Joey
1083 / 645 / 240
Регистрация: 05.05.2015
Сообщений: 3,559
Записей в блоге: 2
05.03.2017, 23:39
Цитата Сообщение от Boyard1 Посмотреть сообщение
почему тут нет функции main
Это не код программы, а только код нескольких функций, которые нужно включить в свою программу и из нее (из main) запускать. Приведите ссылку на эту тему, о которой Вы говорите.

Вообще, скриншот - довольно популярная тема (у меня самого за плечами программа по трем разным типам скриншотов).
Если очень надо, вот код с main (из этой темы Скриншот
Кликните здесь для просмотра всего текста
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
#include <windows.h>
#include <stdio.h>
#include <iostream>
 
#include <gdiplus.h>
 
using namespace std;
 
#pragma comment(lib, "GdiPlus.lib") /* наш многострадальный lib-файл */
using namespace Gdiplus; /* как хочешь, но мне не в кайф постоянно писать Gdiplus:: */
 
 
static const GUID png = 
{ 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } }; 
 
 
int main()
{
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    
    HDC scrdc, memdc; 
    HBITMAP membit;
    // Получаем HDC рабочего стола
    // Параметр HWND для рабочего стола всегда равен нулю.
    scrdc = GetDC(0);
    // Определяем разрешение экрана
    int Height, Width;
    Height = GetSystemMetrics(SM_CYSCREEN);
    Width = GetSystemMetrics(SM_CXSCREEN);
    // Создаем новый DC, идентичный десктоповскому и битмап размером с экран.
    memdc = CreateCompatibleDC(scrdc);
    membit = CreateCompatibleBitmap(scrdc, Width, Height);
    SelectObject(memdc, membit);
    // Улыбаемся... Снято!
    BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
    HBITMAP hBitmap;
    hBitmap =(HBITMAP) SelectObject(memdc, membit);
     Gdiplus::Bitmap bitmap(hBitmap, NULL);
    bitmap.Save(L"c:\\screen.png", &png);
 
    DeleteObject(hBitmap);
 
    //GdiplusShutdown(gdiplusToken);
    return 0;
}


Цитата Сообщение от Boyard1 Посмотреть сообщение
Мои логические выводы приняли решение
Это пять!

Хотелось бы дать совет
Цитата Сообщение от Boyard1 Посмотреть сообщение
Работаю на Dev-C++
- я сам работал с Dev-C++, это немного глючная, слабая и устаревшая (заброшена авторами) IDE
1
1 / 1 / 0
Регистрация: 23.02.2017
Сообщений: 17
05.03.2017, 23:44  [ТС]
Не работает

Вот ссылка на тему с которой код стащил: Как создать скриншот части экрана?
Миниатюры
Скриншот, printscreen  
0
284 / 232 / 114
Регистрация: 07.09.2016
Сообщений: 584
05.03.2017, 23:48
алгоритм такой:
смотрите для на какую функцию undefinde reference
например BitBlt
вбиваете в гугле. попадаете на мсдн:
https://msdn.microsoft.com/ru-... s.85).aspx
в конце описания табличка:
Requirements

Minimum supported client
Windows 2000 Professional [desktop apps only]
Minimum supported server
Windows 2000 Server [desktop apps only]
Header
Wingdi.h (include Windows.h)
Library
Gdi32.lib
DLL
Gdi32.dll

Library
Gdi32.lib


надо залинковать библиотеку к проекту.
пробуете запустить.
повторяете до тех пор, пока ошибки не закончатся.
как это делать в Dev++ хз.
2
1 / 1 / 0
Регистрация: 23.02.2017
Сообщений: 17
05.03.2017, 23:50  [ТС]
Joey, не работает, может у меня библиотеки какой-то нет?
Миниатюры
Скриншот, printscreen  
0
1 / 1 / 0
Регистрация: 23.02.2017
Сообщений: 17
05.03.2017, 23:51  [ТС]
Понял спасибо, пошел пробовать...
Ххххх - интрижка
0
284 / 232 / 114
Регистрация: 07.09.2016
Сообщений: 584
06.03.2017, 00:05
если вы из-за любой ошибки будете приходить на форум - далеко не уедете. там же написано, что существующие функции принимают три аргумента, а вы в вызове два передали. нужен третий. что это за третий аргумент - смотрите по коду, ну или nullptr попробуйте. может прокатит.
0
1 / 1 / 0
Регистрация: 23.02.2017
Сообщений: 17
07.03.2017, 14:47  [ТС]
Доброго времени суток.
в первую очередь решил сменить ide
удалил Dev-C++
установил visual studio 2015 но версия оказалась не рабочая, потребовала лицензию, я думал она бесплатная. Но при запуске она мне выдавала сообщение что ваш срок истек, и ничего кроме закрытия нельзя было сделать.
Ну что-ж мы не сдаемся...
а время идет
Решил удалить visual studio и поставить или eclipse или code blocks.
Стандартными средствами виндовс через панель управления ее небыло возможно удалить.
Мы не сдаемся...
а время идет.
Зашел в ccleaner и при попытке удалить студию комп просто потух во время удаления.
мы не сдавались до последнего.
пришлось переустановить windows.
Время продолжало беспощадно бежать в бездну.
Поставил code blocks.
Решил запустить код с второго поста вот этот:
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
111
112
113
114
115
116
117
118
#include <windows.h>
 
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 = CreateFileA(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;
}
 
int main()
{
  ScreenCapture(0, 0, 100, 100, "d://tmp/screen.bmp", NULL);
  return 0;
}
подключил необходимую библиотеку.
программа выполняется, но файл не сохраняет на комп.
Экспериментировал с директориями, ничего не получается
вот в этой строке пытался изменить директорию, больше ничего не трогал:
C++
1
ScreenCapture(0, 0, 100, 100, "D:\screen.bmp", NULL);
Подскажите пожалуйста что и где нужно подправить?
Время продолжает утекать как песок сквозь пальцы.
Заранее спасибо за любую помощь.
Миниатюры
Скриншот, printscreen  
1
1 / 1 / 0
Регистрация: 23.02.2017
Сообщений: 17
07.03.2017, 14:57  [ТС]
Методом экспериментирования добился успеха. оказалось нужно было еще один слеш поставить.
D:\\screen.bmp
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
05.05.2020, 23:32
Здравствуйте,

Тоже понадобилось сделать "сриншот" рабочего стола, но не для сохранения, а для точного поиска в нем какого то статического рисунка, ну для примера "мой компьютер".

Нагуглил в том числе и в данном теме этот код, пока что не очень понимаю как он работает:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        HDC HDC_Screen = CreateDC(L"DISPLAY", NULL, NULL, NULL);
 
        HDC HDC_CreateCompatibleDC = CreateCompatibleDC(HDC_Screen);
 
        HBITMAP Bitmap = CreateCompatibleBitmap(HDC_Screen,
            GetDeviceCaps(HDC_Screen, HORZRES),
            GetDeviceCaps(HDC_Screen, VERTRES));
 
 
        BOOL my_BitBlt = BitBlt(HDC_CreateCompatibleDC,
            0, 0,
            0, 0,
            HDC_Screen,
            0, 0,
            SRCCOPY);
И если возможно подскажите пожалуйста:

1)Что в итоге произошло по выполнению этого кода ? Отдельные описания функций я прочитал на MSDNе - но общая картина ка кто не складывается.
2)Как мне получится доступ как бы к массиву данных скриншота ? Чтобы просто попиксельное сравнение с заданным "рисунком" сравнить ?
0
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
06.05.2020, 00:04
Этим кодом скорее всего будет плохо. Есть два типа битмапов: DDB и DIB.
CreateCompatibleBitmap() создаёт DDB. Из такого можно получить пиксели только копированием через GetBitmapBits() или GetDIBits(). Лишнее копирование это как правило плохо.
Думаю в современном коде лучше создавать DIB - при помощи CreateDIBSection().

Добавлено через 3 минуты
При снятии скриншота обычно получается 24-битное изображение. Но возможно что вам требуется 32-битное.
Как управлять форматом при использовании CreateCompatibleBitmap() не смог найти, возможно что никак.
А вот для CreateDIBSection() всё указывается явно и строго соблюдается.

Добавлено через 2 минуты
Для работы на версиях Windows между 2000 и Vista помимо SRCCOPY нужен флаг CAPTUREBLT:
C++
1
... , SRCCOPY | CAPTUREBLT);
Добавлено через 1 минуту
Не уверен правда как лучше - просто во всех версиях фигачить с CAPTUREBLT или всё же приделывать проверку версии ОС...
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
06.05.2020, 14:31
Не совсем понимаю, что ожидать от функции CreateDIBSection:

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
BITMAPINFO My_struct_BITMAPINFO;
 
//////////////////////////////////////////
My_struct_BITMAPINFO.bmiHeader.biBitCount = sizeof(My_struct_BITMAPINFO.bmiHeader);
My_struct_BITMAPINFO.bmiHeader.biWidth = 1920;
My_struct_BITMAPINFO.bmiHeader.biHeight = 1080;
My_struct_BITMAPINFO.bmiHeader.biPlanes = 1;
My_struct_BITMAPINFO.bmiHeader.biBitCount = 32;
My_struct_BITMAPINFO.bmiHeader.biCompression = BI_RGB;
My_struct_BITMAPINFO.bmiHeader.biSizeImage = 0;
//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 =
//////////////////////////////////////////
 
void* my_char_DIB;
void** my_char_DIB1 = &my_char_DIB;
 
 
HBITMAP HBITMAP_DIBSection = CreateDIBSection(HDC_Screen, &My_struct_BITMAPINFO, DIB_RGB_COLORS, my_char_DIB1, NULL, NULL);
 
 
int error = GetLastError();                         //Ошибки вроде нет
cout << error << endl;                             //выводится ноль
cout << HBITMAP_DIBSection << endl;     //Но и тут не понятно, что выводится - 00000000
 
char* my_char = (char*)*my_char_DIB1;
 
cout << my_char[0] << endl;  // ничего не выводится
cout << my_char[1] << endl; // ничего не выводится
0
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
07.05.2020, 01:13
Ну первое что я нашёл - у вас опечатка, вы не в то поле пишете размер структуры. В итоге в нужном поле у вас скорее всего неопределённый мусор.


Ловчее и надёжнее сперва обнулить всю переменную-структуру так:
C++
1
2
BITMAPINFO My_struct_BITMAPINFO;
ZeroMemory(&My_struct_BITMAPINFO, sizeof(My_struct_BITMAPINFO));
или так:
C++
1
BITMAPINFO My_struct_BITMAPINFO = {0};
А затем задать только нужные поля. При этом с одной стороны BI_RGB равен нулю и его писать нет смысла, но с другой стороны это мы взяли и "подсмотрели" что оно ноль - а писать желательно явно: оставить на вероятность что вдруг где-то оно будет не нулём.
C++
1
2
3
4
5
6
My_struct_BITMAPINFO.bmiHeader.biSize = sizeof(My_struct_BITMAPINFO.bmiHeader); // а у вас вместо biSize чего стояло? чуть внимательнее нада :)
My_struct_BITMAPINFO.bmiHeader.biWidth = 1920;
My_struct_BITMAPINFO.bmiHeader.biHeight = 1080;
My_struct_BITMAPINFO.bmiHeader.biPlanes = 1;
My_struct_BITMAPINFO.bmiHeader.biBitCount = 32;
My_struct_BITMAPINFO.bmiHeader.biCompression = BI_RGB;
По поводу GetLastError() в справке по функции CreateDIBSection() не говорится (по крайней мере на данный момент):
Return value
  • If the function succeeds, the return value is a handle to the newly created DIB, and *ppvBits points to the bitmap bit values.
  • If the function fails, the return value is NULL, and *ppvBits is NULL.
  • This function can return the following value.
    ERROR_INVALID_PARAMETEROne or more of the input parameters is invalid.
Так что для обнаружения ошибок проверяем HBITMAP_DIBSection на NULL (проверку my_char_DIB наверное можно опустить). Кстати почему my_char_DIB?
Можем проверять и на ERROR_INVALID_PARAMETER, чтоб уж всё наверняка.

Указатель на буфер объявляют обычно как-то так:
C++
1
unsigned char* my_DIB_data;
или так:
C++
1
RGBQUAD* my_DIB_data;
А в функцию передают так:
C++
1
... , (VOID**)&my_DIB_data , ...
Добавлено через 3 минуты
Когда изображение biBitCount == 32 пиксели аккурат RGBQUAD. У него там и поля удобные. И по идее как к массиву можно обращаться.
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
07.05.2020, 11:55
Цитата Сообщение от GoodWeather Посмотреть сообщение
Ну первое что я нашёл - у вас опечатка, вы не в то поле пишете размер структуры.
Да, прошу прощения, Спасибо, не внимателен.

Цитата Сообщение от GoodWeather Посмотреть сообщение
Указатель на буфер объявляют обычно как-то так:
C++
1
unsigned char* my_DIB_data;
или так:
C++
1
RGBQUAD* my_DIB_data;
А в функцию передают так:
C++
1
... , (VOID**)&my_DIB_data , ...
В итоге:

C++
1
cout << HBITMAP_DIBSection << endl;
HBITMAP_DIBSection - Выдает не нулевое значение, значит видимо функция завершается успешно, возвращаемое значение является дескриптором недавно созданного DIB, а * ppvBits указывает на битовые значения битовой карты.

Пытаюсь обратится по указателю:
C++
1
2
3
unsigned char* my_DIB_data;
 
HBITMAP HBITMAP_DIBSection = CreateDIBSection(HDC_Screen, &My_struct_BITMAPINFO, DIB_RGB_COLORS, (VOID**)&my_DIB_data, NULL, NULL);
Как я понимаю в my_DIB_data - функция присвоила адрес памяти, где хранится адрес памяти, который уже указывает на место в памяти, который якобы должен "указывает на битовые значения битовой карты."

То есть для доступа к массиву этой битовой карты - my_DIB_data нужно разыменовывать и привести к char, чтобы можно было по байтового обращаться к памяти:

C++
1
cout << (char)(*my_DIB_data[0]) << endl;
Но VS2017 ругается, что операнд * должен быть указателем. Что то не так я обращаюсь получается
0
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
07.05.2020, 15:26
Цитата Сообщение от Optimus11 Посмотреть сообщение
Как я понимаю в my_DIB_data - функция присвоила...
Да. Теперь переменная указывает на начало массива пикселей.

Почему cout? У вас консольное что ли? Что вы хотите этим способом увидеть? Это уже указатель, зачем второй раз звёздочку?
Кстати, если смотреть что там находится сразу после CreateDIBSection() - то там скорее всего зачищено, одни нули.

C++
1
2
3
4
5
6
my_DIB_data[0] = 0; // первый пиксель: blue
my_DIB_data[1] = 0; // первый пиксель: green
my_DIB_data[2] = 0; // первый пиксель: red
my_DIB_data[3] = 0; // первый пиксель: alpha
my_DIB_data[4] = 255; // второй пиксель: blue
...
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
07.05.2020, 16:14
Цитата Сообщение от GoodWeather Посмотреть сообщение
У вас консольное что ли? Что вы хотите этим способом увидеть? Это уже указатель, зачем второй раз звёздочку?
Пока что да, консольное.
Я хотел увидеть значение которое, как понял должно быть в этом массиве. Значение пикселей. Так как я указывал 32 бита, то, как я понял один пиксель этого скриншота будет занимать 4 байта.

Я только немного не правильно выводил занчение, нужно было конечно привести к (int).

Цитата Сообщение от GoodWeather Посмотреть сообщение
Это уже указатель, зачем второй раз звёздочку?
Я вот этот момент так и не понимаю - там указатель или указатель на указатель ? Вроде, как функция принимает именно указатель на указатель да еще и на void. Поэтому я как бы пытался его сначала разыменовать, а потом привести к char.

Но даже, если обращаться сразу, как к указателю:
C++
1
2
3
4
cout << (int)my_DIB_data[0] << endl;
cout << (int)my_DIB_data[1] << endl;
cout << (int)my_DIB_data[2] << endl;
cout << (int)my_DIB_data[3] << endl;
То выводятся одни нули.


Цитата Сообщение от GoodWeather Посмотреть сообщение
Кстати, если смотреть что там находится сразу после CreateDIBSection() - то там скорее всего зачищено, одни нули.
Получается, что так. Но почему ?? Ведь функция CreateDIBSection:
C++
1
возвращаемое значение является дескриптором недавно созданного DIB, а * ppvBits указывает на битовые значения битовой карты.
Что тогда означает, что * ppvBits указывает на битовые значения битовой карты?
0
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
07.05.2020, 17:14
Мы объявляем указатель. Сами выбирая какого типа.
Можем объявить или указатель на VOID или указатель на unsigned char или указатель на int или указатель на RGBQUAD - как захотим.
А в функцию CreateDIBSection() надо передать указатель на наш указатель. Просто чтоб функция могла изменить значение нашего указателя.

Если у вас указатель на простой тип вроде unsigned char или int, то не надо ни к чему приводить.

Вы только что создали новый битмап. Что же в нём должно быть по-вашему? Радуга? Картина Ван-Гога?
Вам выделили память, чтоб там не было случайного мусора - обнулили её.
Теперь у вас битмап залитый цветом (0, 0, 0, 0). Нарисуйте на нём что-нибудь - тогда и будут не нули.

Добавлено через 22 минуты
а... Вы ж в #11 пытались сделать скриншот... Посмотрим...
Цитата Сообщение от Optimus11 Посмотреть сообщение
C++
1
BOOL my_BitBlt = BitBlt(HDC_CreateCompatibleDC, 0, 0, 0, 0, HDC_Screen, 0, 0, SRCCOPY);
  • Начало копируемой области: 0, 0;
  • Размеры копируемой области: тоже 0, 0;
Так что по факту мы ничего не копируем, потому что запрашиваем пустую площадь. Ширина и высота должны же быть хоть какими-то?
C++
1
BitBlt(HDC_CreateCompatibleDC, 0, 0, My_struct_BITMAPINFO.bmiHeader.biWidth, My_struct_BITMAPINFO.bmiHeader.biHeight, HDC_Screen, 0, 0, SRCCOPY | CAPTUREBLT);
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
07.05.2020, 18:12
Цитата Сообщение от GoodWeather Посмотреть сообщение
Если у вас указатель на простой тип вроде unsigned char или int, то не надо ни к чему приводить.

Вы только что создали новый битмап. Что же в нём должно быть по-вашему? Радуга? Картина Ван-Гога?
Вам выделили память, чтоб там не было случайного мусора - обнулили её.
Теперь у вас битмап залитый цветом (0, 0, 0, 0). Нарисуйте на нём что-нибудь - тогда и будут не нули.
Правильно ли я понимаю, что, чтобы в выделенном памяти через функцию CreateDIBSection - что то нарисовать, нужно применить функцию SelectObject:
C++
1
Функция SelectObject выделяет объект в указанном контексте устройства (DC). Новый объект заменяет предыдущий объект того же типа.
Указанный контекст устройства получается будет - это дескриптор возвращенный функцией CreateCompatibleDC ?

А второй параметр функции SelectObject:
C++
1
Дескриптор объекта, который будет выбран. Указанный объект должен быть создан с помощью одной из следующих функций.
Это как раз дескриптор возвращенный функцией CreateDIBSection ?

То есть SelectObject нарисует в битовой карте рисунок, который как бы есть в CreateCompatibleDC ?

Добавлено через 48 минут
Не
C++
1
SelectObject(HDC_CreateCompatibleDC, HBITMAP_DIBSection);
Не рисует картинку по указателю.
0
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
07.05.2020, 18:31
Для рисования на битмапе есть варианты:
  • Вручную менять пиксели
  • Использовать системную библиотеку GDI32
  • Использовать системную библиотеку GDI+
  • Использовать системные библиотеки типа DirectX или OpenGL
  • Или использовать всякие сторонние библиотеки
Для рисования через GDI+ вроде достаточно BITMAPINFO + выделенный кусок памяти.
Был ещё вроде какой-то метод с HBITMAP, но там игнорируется альфа-канал, да и вообще вроде бы копируется, а не используется переданный.
хм... А может когда с BITMAPINFO тоже копируется? Это я лучше ещё уточню...

Для рисования через GDI32 да, придётся создать HDC и выбрать битмап в него, так как все функции GDI32 работают через HDC:
C++
1
2
3
4
5
6
7
HDC My_HDC_Screen = GetDC(NULL);
HDC My_HDC_Memory = CreateCompatibleDC(My_HDC_Screen);
HGDIOBJ My_Old_Bitmap = SelectObject(My_HDC_Memory, HBITMAP_DIBSection);
if (My_Old_Bitmap != NULL)
    DeleteObject(My_Old_Bitmap);
// а тут можно и скриншот заодно снять...
ReleaseDC(NULL, My_HDC_Screen);
Добавлено через 1 минуту
SelectObject() не рисует, а "соединяет" HDC с HGDIOBJ - например с HBITMAP.

Добавлено через 41 секунду
BitBlt() - копирует с HDC на HDC в масштабе 1-к-1.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.05.2020, 18:31
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
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
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru