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

Сделать скриншот экрана / копировать экранную область видеопамяти

20.01.2013, 18:32. Показов 21893. Ответов 24
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток. Для работы программы необходимо получить копию(скриншот) экрана, с запущенным directX приложением (собственно скриншот самого приложения и надо получить). Проблема в том, что трогать само directX приложение (получить хендл и прочее) нельзя.
Собственно вопрос - с помощью чего можно реализовать эту функцию, при этом получить максимальное быстродействие (получать копию экрана необходимо не реже 4-х раз в секунду, при этом необходимо его успевать обрабатывать)? Экзотические варианты типа написания собственного драйвера не подойдут)))
Заранее спасибо.

PS Будет ли программа делать скриншот всего экрана, или только приложения - не принципиально, главное скорость + нормальный скрин directX пиложения.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
20.01.2013, 18:32
Ответы с готовыми решениями:

Как сделать скриншот, получая данные непосредственно из видеопамяти.
Я так предполагаю, нужно использовать asm вставки. Искал в сети исходники, но так и не нашел.

как сделать экранную форму большую, чем размер экрана?
Люди подскажите - кто знает - как сделать экранную форму в Дельфи - больше размера самого размера экрана...????

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

24
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
20.01.2013, 18:44
ну если средствами winapi, то можно попробовать тупо взять dc экрана и скопировать куда-нибудь к себе.
HDC hScreenDc = GetDC(NULL);
потом какой-нибудь BitBlt
Если известны координаты и размер нужного окна, то из контекста можно выборочно копировать лишь нужный регион.
На счет скорости - хз. Нужно пробовать.
Если другими либами, то в них наверняка есть для этого спец средства.
0
8 / 8 / 1
Регистрация: 11.08.2012
Сообщений: 112
20.01.2013, 18:50  [ТС]
Цитата Сообщение от DU Посмотреть сообщение
потом какой-нибудь BitBlt
Насколько я знаю - BitBlt имеет кучу программных прослоек, в виду чего скорость получится не очень высокой. С другой стороны удастся ли с помощью BitBlt копировать то, что в выводится с помощью directX ?
А нет какого нибудь прямого способа копирования видимой области видеопамяти, без нарушения качества выводимой картинки?
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
20.01.2013, 18:54
на счет directX - это я не знаю. пробовать нужно.
как может пострадать качество я не понимаю. моник скажем 1000 на 1000. копируем эти самые пиксели. куда что тут может ухудшиться? короче, быстрее будет попробовать, чем рассуждать.
еще можно попробовать такой вариант, без писанины.
нажать PrintScreen и скопировать в пэинт то, что получилось. эсли копируется - значит можно эмулировать эти нажатия и потом забирать из буфера содержимое.
1
8 / 8 / 1
Регистрация: 11.08.2012
Сообщений: 112
20.01.2013, 19:03  [ТС]
Цитата Сообщение от DU Посмотреть сообщение
как может пострадать качество я не понимаю. моник скажем 1000 на 1000. копируем эти самые пиксели. куда что тут может ухудшиться
Ну в данном случае я имел ввиду вариант когда происходит непосредственное чтение экранной области видеопамяти.(например при помощи ddraw).

Кстати, использование ddraw вместо BitBlt не более быстрая альтернатива?
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
20.01.2013, 19:09
это нужно замерять или знать подробности реализации того и другого. я к сожалению не знаю ничего
0
8 / 8 / 1
Регистрация: 11.08.2012
Сообщений: 112
20.01.2013, 21:14  [ТС]
С BitBlt буду пробовать завтра - послезавтра.
Может еще кто какие варианты знает? Желательно с примерами.
0
Эксперт С++
 Аватар для schdub
3073 / 1411 / 425
Регистрация: 19.01.2009
Сообщений: 3,894
21.01.2013, 10:52
Various methods for capturing the screen
2
8 / 8 / 1
Регистрация: 11.08.2012
Сообщений: 112
22.01.2013, 18:16  [ТС]
schdub, а по вашему мнению, какой способ более быстрым будет?

Добавлено через 4 часа 30 минут
Взял пример из ссылке выше, скомпилировал, программа компилируется, но вылетает с ошибкой. По инглишу я не шпрехаю, на русскоязычных форумах практически никакой информации не нашел, кто может подсказать в чем дело?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <stdio.h>
#include <Windows.h>
#include <d3d9.h>
#include <d3dx9tex.h>
 
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"d3d9.lib")
 
 
int main()
{
    IDirect3DDevice9* g_pd3dDevice;
    IDirect3DSurface9* pSurface;
 
    g_pd3dDevice->CreateOffscreenPlainSurface(1920, 1080,
        D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL);
    g_pd3dDevice->GetFrontBufferData(0, pSurface);
    D3DXSaveSurfaceToFile(L"Desktop.bmp",D3DXIFF_BMP,pSurface,NULL,NULL);
    pSurface->Release(); 
 
    return 0;
}
Добавлено через 2 часа 19 минут
Видимо необходимо инициализировать еще что то, но вот что?

Добавлено через 17 часов 1 минуту
В примере сказано, что g_pd3dDevice является объектом IDirect3DDevice9, который необходимо правильно инициализировать. А вот кто ни будь может подсказать, как в данном случае его инициализировать то?

Добавлено через 1 час 54 минуты
Ура товарищи, все заработало. Вот полный код:
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
#include <iostream>
#include <stdio.h>
#include <Windows.h>
#include <d3d9.h>
#include <d3dx9tex.h>
 
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"d3d9.lib")
 
 
int main()
{
    IDirect3D9 *g_pD3D;
    HWND hWnd;
    
    IDirect3DDevice9 *g_pd3dDevice;
    IDirect3DSurface9 *pSurface;
    D3DDISPLAYMODE d3ddm;
    D3DPRESENT_PARAMETERS d3dpp;
 
    hWnd=GetConsoleWindow();
 
 
    if((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) {
     printf("fail 1");
    }
    if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) {
    printf("fail 2");
    }
    ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
 
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = d3ddm.Format;
    d3dpp.BackBufferHeight = d3ddm.Height;
    d3dpp.BackBufferWidth = d3ddm.Width;
 
 
    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
                               D3DDEVTYPE_HAL, hWnd,
                               D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                               &d3dpp, &g_pd3dDevice))) {
    printf("fail 3");
    }
 
 
    
    if(FAILED(g_pd3dDevice->CreateOffscreenPlainSurface(d3ddm.Width, d3ddm.Height,
        D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL)))
    {
        printf("fail 4");
    }
 
    g_pd3dDevice->GetFrontBufferData(0, pSurface);
    D3DXSaveSurfaceToFile(L"Desktop.bmp",D3DXIFF_BMP,pSurface,NULL,NULL);
    pSurface->Release(); 
 
    return 0;
}
Создается скриншот рабочего стола + приложений directX
0
MЫW
 Аватар для phantom96
124 / 109 / 9
Регистрация: 15.02.2013
Сообщений: 538
16.04.2013, 23:16
Ermak, попробовал повторить скрин, пока скринил рабочий стол было нормально. Попробовал заскринить содержимое игры вылетела AccessViolationException. Скриню библиотекой вызываемой через C#, но ошибка как я понял из-за того что игра пытается защититься от внешних воздействий. Я что-то не так понял или надо обходить защиту?
0
5 / 5 / 5
Регистрация: 26.02.2012
Сообщений: 51
16.04.2013, 23:24
phantom96, конечно бред, но все-таки: может студия запущена не в режиме администратора?
0
MЫW
 Аватар для phantom96
124 / 109 / 9
Регистрация: 15.02.2013
Сообщений: 538
16.04.2013, 23:34
Я и без студии пробовал) Перевёл игру в оконный режим заскринилась, полноэкранный и опять вылет.

Добавлено через 7 минут
Как вообще происходит событие скрина когда человек нажимает на printscreen? BitBlt, direct? В какую сторону копать чтобы повторить действия клавиши?
0
8 / 8 / 1
Регистрация: 11.08.2012
Сообщений: 112
19.04.2013, 21:39  [ТС]
Цитата Сообщение от phantom96 Посмотреть сообщение
Я и без студии пробовал) Перевёл игру в оконный режим заскринилась, полноэкранный и опять вылет.
Есть подозрение что нужно брать хендл самой игры, и передавать ее в инициализации ddraw

Добавлено через 7 минут
Цитата Сообщение от Ermak_nk Посмотреть сообщение
ddraw
не ddraw а d3d, перепутал))
0
MЫW
 Аватар для phantom96
124 / 109 / 9
Регистрация: 15.02.2013
Сообщений: 538
20.04.2013, 02:20
У меня руки ну совсем кривые не покажете что и куда брать?)

Добавлено через 1 минуту
Кстати в самом коде fail 3 проходит.

Добавлено через 1 минуту
Вы уж простите за такие глупые вопросы, я в этом коде вообще ничего не понимаю. На С++ пытаюсь что-то сделать т.к. на C# с этим вообще туго будет. Хочу дллку скринящую потом просто импортить в C#...

Добавлено через 53 минуты
Буду оооочень благодарен если кто-то всё-таки поможет...( У меня голова уже гудит от этих примеров срининга. Столько всего поскачивал с codeproject'а. Всё заваливается на полном экране. Самый большой успех пока у Taxi recorder, и тот с выключенным сглаживанием. Не заставлять же всех сглаживание вырубать...(
0
8 / 8 / 1
Регистрация: 11.08.2012
Сообщений: 112
20.04.2013, 20:21  [ТС]
Цитата Сообщение от phantom96 Посмотреть сообщение
У меня руки ну совсем кривые не покажете что и куда брать?)
Наврятли я тот человек, кто может направить на путь истинный, ибо мое знакомство с d3d ограничилось именно получением скрина экрана, и на этом пока закончилось) Так что в данной ситуации надо садится и разбираться более подробнее.
Вот тут есть довольно неплохое описание на русском, собственно с помощью которого я и разобрался.
Можно наверное сначала поиграться со структурой d3dpp (описание ее есть по ссылке приведенной выше).
Как получить хендл окна - есть полно тем в интернете (помойму даже попадались темы на этом форуме).
Также возможно не совпадают разрешение рабочего стола, и разрешение игры.

Добавлено через 8 минут
Если неважна скорость, может быть действительно проще эмулировать нажатие PrtScr и из буфера обмена выдерать скрин?
0
MЫW
 Аватар для phantom96
124 / 109 / 9
Регистрация: 15.02.2013
Сообщений: 538
20.04.2013, 22:08
Сейчас так и выдерается...( Проблема в другом заключается. В Win7 нужно включить сглаживание при включённом Aero чтобы скрин не чёрным был)))

Добавлено через 2 минуты
Скорость мне не особо важна. Хоть 30 секунд на файл, но пока успехи нулевые... Либо включённые аеро и сглаживание и принтскрин либо выключенные аеро и сглаживание и SlimDX.
0
0 / 0 / 0
Регистрация: 15.11.2012
Сообщений: 53
22.07.2013, 14:46
в общем нужен минималистичный способ "снять" все пиксели с экрана... я так понял без подключения

#include <d3d9.h>
#include <d3dx9tex.h>

будут черные квадраты? или как-то можно обойти...

то есть такой вариант не подходит да...

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void CaptureScreen()
{
    int nScreenWidth = GetSystemMetrics(SM_CXSCREEN);
    int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);
    HWND hDesktopWnd = GetDesktopWindow();
    HDC hDesktopDC = GetDC(hDesktopWnd);
    HDC hCaptureDC = CreateCompatibleDC(hDesktopDC);
    HBITMAP hCaptureBitmap =CreateCompatibleBitmap(hDesktopDC, 
                            nScreenWidth, nScreenHeight);
    SelectObject(hCaptureDC,hCaptureBitmap); 
    BitBlt(hCaptureDC,0,0,nScreenWidth,nScreenHeight,
           hDesktopDC,0,0,SRCCOPY|CAPTUREBLT); 
    SaveCapturedBitmap(hCaptureBitmap); //Place holder - Put your code
                                //here to save the captured image to disk
    ReleaseDC(hDesktopWnd,hDesktopDC);
    DeleteDC(hCaptureDC);
    DeleteObject(hCaptureBitmap);
}
В Win7 нужно включить сглаживание при включённом Aero чтобы скрин не чёрным был
подробнее можешь рассказать, как включить его?

Добавлено через 17 минут
подскажите, где тут ошибка...

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
// ...
 
extern void* pBits;
 
#define BITSPERPIXEL 32
 
int main()
{
    IDirect3D9 *g_pD3D;
    HWND hWnd;
    
    IDirect3DDevice9 *g_pd3dDevice;
    IDirect3DSurface9 *pSurface;
    D3DDISPLAYMODE d3ddm;
    D3DPRESENT_PARAMETERS d3dpp;
 
    hWnd = GetConsoleWindow();
 
    if((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) {
     printf("fail 1");
    }
 
    if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) {
     printf("fail 2");
    }
 
    ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
 
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = d3ddm.Format;
    d3dpp.BackBufferHeight = d3ddm.Height;
    d3dpp.BackBufferWidth = d3ddm.Width;
 
    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,
                               D3DDEVTYPE_HAL, hWnd,
                               D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                               &d3dpp, &g_pd3dDevice))) {
     printf("fail 3");
    }
 
    if(FAILED(g_pd3dDevice->CreateOffscreenPlainSurface(d3ddm.Width, d3ddm.Height,
        D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL)))
    {
        printf("fail 4");
    }
 
    g_pd3dDevice->GetFrontBufferData(0, pSurface);
D3DLOCKED_RECT lockedRect;
pSurface->LockRect(&lockedRect,NULL,
                   D3DLOCK_NO_DIRTY_UPDATE|
                   D3DLOCK_NOSYSLOCK|D3DLOCK_READONLY);
 
for( int i=0 ; i < d3ddm.Height ; i++)
{
    memcpy( (BYTE*) pBits + i * d3ddm.Width * BITSPERPIXEL / 8 , 
        (BYTE*) lockedRect.pBits + i* lockedRect.Pitch , 
        d3ddm.Width * BITSPERPIXEL / 8);
}
 
pSurface->UnlockRect();
pSurface->Release();
 
    return 0;
}
нужно получить указатель на массив байтов

кстати

#include <d3dx9tex.h>

#pragma comment(lib,"d3dx9.lib")

у меня визуал студия не может найти. а ошибка следующая: "неразрешенный внешний символ void * pBits"
кстати, а что если у юзера всетаки BITSPERPIXEL не 32? что тогда будет? и как вычислить это значение...
0
MЫW
 Аватар для phantom96
124 / 109 / 9
Регистрация: 15.02.2013
Сообщений: 538
22.07.2013, 17:23
time123, включить сглаживание нужно в приложении с которого скрин делается, либо выключить аеро через WinAPI.
0
8 / 8 / 1
Регистрация: 11.08.2012
Сообщений: 112
22.07.2013, 21:40  [ТС]
Цитата Сообщение от time123 Посмотреть сообщение
у меня визуал студия не может найти
Потому что по дефолту их нет. Надо скачивать из инета.

Цитата Сообщение от time123 Посмотреть сообщение
подскажите, где тут ошибка...
Не компилириуется? Или что происходит?

Добавлено через 5 минут
Вот кусок кода, делал бота для онлайн игры
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
HRESULT InitD3D(HWND hWnd)
{
    D3DPRESENT_PARAMETERS   d3dpp;
 
    if((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) 
    {
        printf("fail 1");
        return E_FAIL;
    }
    if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) 
    {
        printf("fail 2");
        return E_FAIL;
    }
 
    ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS));
 
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = d3ddm.Format;
    d3dpp.BackBufferHeight = d3ddm.Height;
    d3dpp.BackBufferWidth = d3ddm.Width;
 
 
    if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                               D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                               &d3dpp, &g_pd3dDevice))) 
    {
        printf("fail 3");
        return E_FAIL;
    }
    
    return S_OK;
}
 
HRESULT GetScreenshot()
{
    if(FAILED(g_pd3dDevice->CreateOffscreenPlainSurface(d3ddm.Width, d3ddm.Height,
        D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL)))
    {
        printf("fail 4");
        return E_FAIL;
    }
    if(FAILED(g_pd3dDevice->GetFrontBufferData(0, pSurface)))
    {
        printf("fail 5");
        return E_FAIL;
    }
    return S_OK;
}
 
bool GetConstColor(CONSTCOLOR *ConstColor)
{
    D3DSURFACE_DESC     surfaceDesc;  // описание поверхности
    D3DLOCKED_RECT      lockedRect;
    DWORD               *imageData; // указатель на начало памяти поверхности
    int                 index;
    unsigned char r,g,b;
 
    if(FAILED(GetScreenshot())) return false;
 
    pSurface->GetDesc(&surfaceDesc);
    pSurface->LockRect(&lockedRect, 0, 0);
 
    imageData = (DWORD*)lockedRect.pBits;// указатель на начало памяти поверхности
 
    index = ConstColor->y * lockedRect.Pitch/4 + ConstColor->x; //вычисляем координату точки на поверхности
    
    r = (imageData[index]>>16);
    g = (imageData[index]>>8);
    b = imageData[index];
 
    if(r > 255 - accuracy) r = 0xff;
    else r += accuracy;
    if(g > 255 - accuracy) g = 0xff;
    else g += accuracy;
    if(b > 255 - accuracy) b = 0xff;
    else b += accuracy;
 
    ConstColor->imageDataMAX = 0;
    ConstColor->imageDataMAX = (r<<16)|(g<<8)|b;
 
    r = (imageData[index]>>16);
    g = (imageData[index]>>8);
    b = imageData[index];
 
    if(r < accuracy) r = 0;
    else r -= accuracy;
    if(g < accuracy) g = 0;
    else g -= accuracy;
    if(b < accuracy) b = 0;
    else b -= accuracy;
 
    ConstColor->imageDataMIN = 0;
    ConstColor->imageDataMIN = (r<<16)|(g<<8)|b;
 
 
    pSurface->UnlockRect();
    pSurface->Release();
 
    return true;
}
0
0 / 0 / 0
Регистрация: 15.11.2012
Сообщений: 53
30.07.2013, 16:18
насчет моего кода, там проблема в pBits, extern убрал, подскажите, как правильно выделить именно необходимое кол-во памяти? ну то есть необходимо узнать на сколько байтов pBits будет ссылаться. и если потом преобразовать в char* это дело, ничего страшного не произойдет, так ведь?)

и еще, посоветуйте пожалуйста, как можно эти данные с указателя pBits на жесткий диск скинуть в файл test.bmp чтобы проверить, все ли работает...

Добавлено через 15 часов 26 минут
такой вопрос, есть фукнция для создания скриншота

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
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
144
145
146
147
148
149
150
151
152
153
154
155
156
int CaptureBMP(LPCTSTR szFile)
{
    // Source[1]
    HDC hdcScr, hdcMem;
    HBITMAP hbmScr;
    BITMAP bmp;
    int iXRes, iYRes;
 
    // Create a normal DC and a memory DC for the entire screen. The
    // normal DC provides a "snapshot" of the screen contents. The
    // memory DC keeps a copy of this "snapshot" in the associated
    // bitmap.
    hdcScr = CreateDC("DISPLAY", NULL, NULL, NULL);
    hdcMem = CreateCompatibleDC(hdcScr);
 
    iXRes = GetDeviceCaps(hdcScr, HORZRES);
    iYRes = GetDeviceCaps(hdcScr, VERTRES);
 
    // Create a compatible bitmap for hdcScreen.
    hbmScr = CreateCompatibleBitmap(hdcScr, iXRes, iYRes);
    if (hbmScr == 0) return 0;
 
    // Select the bitmaps into the compatible DC.
    if (!SelectObject(hdcMem, hbmScr)) return 0;
 
    // Copy color data for the entire display into a
    // bitmap that is selected into a compatible DC.
    if (!StretchBlt(hdcMem,
        0, 0, iXRes, iYRes,
        hdcScr,
        0, 0, iXRes, iYRes,
        SRCCOPY))
 
        return 0;
 
    // Source[2]
    PBITMAPINFO pbmi;
    WORD cClrBits;
 
    // Retrieve the bitmap's color format, width, and height.
    if (!GetObject(hbmScr, sizeof(BITMAP), (LPSTR) &bmp)) return 0;
 
    // Convert the color format to a count of bits.
    cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
    if (cClrBits == 1)
        cClrBits = 1;
    else if (cClrBits <= 4)
        cClrBits = 4;
    else if (cClrBits <= 8)
        cClrBits = 8;
    else if (cClrBits <= 16)
        cClrBits = 16;
    else if (cClrBits <= 24)
        cClrBits = 24;
    else cClrBits = 32;
 
    // Allocate memory for the BITMAPINFO structure. (This structure
    // contains a BITMAPINFOHEADER structure and an array of RGBQUAD
    // data structures.)
    if (cClrBits != 24)
        pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
                sizeof(BITMAPINFOHEADER) +
                sizeof(RGBQUAD) * (1 << cClrBits));
 
    // There is no RGBQUAD array for the 24-bit-per-pixel format.
    else
        pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
                sizeof(BITMAPINFOHEADER));
 
    // Initialize the fields in the BITMAPINFO structure.
    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    pbmi->bmiHeader.biWidth = bmp.bmWidth;
    pbmi->bmiHeader.biHeight = bmp.bmHeight;
    pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
    pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
    if (cClrBits < 24)
        pbmi->bmiHeader.biClrUsed = (1 << cClrBits);
 
    // If the bitmap is not compressed, set the BI_RGB flag.
    pbmi->bmiHeader.biCompression = BI_RGB;
 
    // Compute the number of bytes in the array of color
    // indices and store the result in biSizeImage.
    pbmi->bmiHeader.biSizeImage = (pbmi->bmiHeader.biWidth + 7) / 8
                                    * pbmi->bmiHeader.biHeight * cClrBits;
 
    // Set biClrImportant to 0, indicating that all of the
    // device colors are important.
    pbmi->bmiHeader.biClrImportant = 0;
 
    HANDLE hf;                  // file handle
    BITMAPFILEHEADER hdr;       // bitmap file-header
    PBITMAPINFOHEADER pbih;     // bitmap info-header
    LPBYTE lpBits;              // memory pointer
    DWORD dwTotal;              // total count of bytes
    DWORD cb;                   // incremental count of bytes
    BYTE *hp;                   // byte pointer
    DWORD dwTmp;
 
    pbih = (PBITMAPINFOHEADER) pbmi;
    lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
 
    if (!lpBits) return 0;
 
    // Retrieve the color table (RGBQUAD array) and the bits
    // (array of palette indices) from the DIB.
    if (!GetDIBits(hdcMem, hbmScr, 0, (WORD) pbih->biHeight, lpBits, pbmi, DIB_RGB_COLORS)) return 0;
 
    // Create the .BMP file.
    hf = CreateFile(szFile,
                    GENERIC_READ | GENERIC_WRITE,
                    (DWORD) 0,
                    NULL,
                    CREATE_ALWAYS,
                    FILE_ATTRIBUTE_NORMAL,
                    (HANDLE) NULL);
    if (hf == INVALID_HANDLE_VALUE) return 0;
 
    hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M"
 
    // Compute the size of the entire file.
    hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) +
                 pbih->biSize + pbih->biClrUsed *
                 sizeof(RGBQUAD) + pbih->biSizeImage);
    hdr.bfReserved1 = 0;
    hdr.bfReserved2 = 0;
 
    // Compute the offset to the array of color indices.
    hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
                    pbih->biSize + pbih->biClrUsed *
                    sizeof (RGBQUAD);
 
    // Copy the BITMAPFILEHEADER into the .BMP file.
    if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL)) return 0;
 
    // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
    if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER)
                + pbih->biClrUsed * sizeof (RGBQUAD),
                (LPDWORD) &dwTmp, NULL))
        return 0;
 
    // Copy the array of color indices into the .BMP file.
    dwTotal = cb = pbih->biSizeImage;
    hp = lpBits;
    if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp, NULL)) return 0;
 
    // Close the .BMP file.
    if (!CloseHandle(hf)) return 0;
 
    // Free memory.
    GlobalFree((HGLOBAL)lpBits);
    ReleaseDC(0, hdcScr);
    ReleaseDC(0, hdcMem);
 
    return 1;
}
скажите, можно ли как-то изначально создать скриншот 800x600 при этом чтобы в него поместился весь рабочий стол (то есть уменьшить его)?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
30.07.2013, 16:18
Помогаю со студенческими работами здесь

Сделать скриншот экрана
Подскажите, пожалуйста, как реализовать на СИ какие библиотеки использовать?

Сделать скриншот части экрана
Для работы программа делает скриншоты несколько раз в секунду, и чтобы оптимизировать всё это дело, я решил делать снимки только нужной...

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

Не могу сделать скриншот экрана
не могу сделать скриншот экрана. помогите

Как сделать скриншот экрана?
Как сделать скриншот экрана (допустим, 200 на 300px, по координатам x: 150, y: 20) и поместить его в image?


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
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