Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Программный скриншот на C++

39K
04 декабря 2008 года
SaBo
20 / / 04.12.2008
Привет!
Есть такая задача: сделать скриншот определённого участка на экране и сохранить его в BMP. Координаты этого участка, естественно, имеются.

Что для этого надо юзать?
Перелапатил уже тонны инфы - всё время какие-нибудь ошибки вылазят.

Очень прошу дать конкретные функции/классы/либы для работы.
Т.к. я новичок в C++, то посты в стиле "юзай _name_" мне не помогут - пожалуйста, не тратьте своё время.
39K
04 декабря 2008 года
SaBo
20 / / 04.12.2008
Вот даже что-то накатал:

Код:
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <iostream>

using namespace std;

PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp){
    BITMAP bmp;
    PBITMAPINFO pbmi;
    WORD    cClrBits;

    // Retrieve the bitmap color format, width, and height.
    GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp);

    // 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.
    // For Windows NT, the width must be DWORD aligned unless
    // the bitmap is RLE compressed. This example shows this.
    // For Windows 95/98/Me, the width must be WORD aligned unless the
    // bitmap is RLE compressed.
    pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 * pbmi->bmiHeader.biHeight;
    // Set biClrImportant to 0, indicating that all of the
    // device colors are important.
     pbmi->bmiHeader.biClrImportant = 0;
     return pbmi;
}

void CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC){
     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) pbi;
    lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

    // Retrieve the color table (RGBQUAD array) and the bits
    // (array of palette indices) from the DIB.
    GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, DIB_RGB_COLORS);

// Create the .BMP file.
    hf = CreateFile(pszFile, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    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.
    WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp,  NULL);

    // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
    WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + pbih->biClrUsed * sizeof (RGBQUAD), (LPDWORD) &dwTmp, NULL);

    // Copy the array of color indices into the .BMP file.
    dwTotal = cb = pbih->biSizeImage;
    hp = lpBits;
    WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL);

    // Close the .BMP file.
    CloseHandle(hf);

    // Free memory.
    GlobalFree((HGLOBAL)lpBits);
}


void main(int argc, LPTSTR argv[]){
locale::global(locale("rus"));
int sx = GetSystemMetrics(SM_CXSCREEN), sy = GetSystemMetrics(SM_CYSCREEN);
HDC hDC = GetDC(GetDesktopWindow());
HDC MyHDC = CreateCompatibleDC(hDC);
HBITMAP hBMP = CreateCompatibleBitmap(hDC, sx, sy);
SelectObject(MyHDC, hBMP);
LOGBRUSH MyBrush;
MyBrush.lbStyle = BS_SOLID;
MyBrush.lbColor = 0xFF0000;
HBRUSH hBrush = CreateBrushIndirect(&MyBrush);
RECT MyRect = {0, 0, sx, sy};
FillRect(MyHDC, &MyRect, hBrush);

BitBlt(MyHDC, 0, 0, sx, sy, hDC, 0, 0, SRCCOPY);
if(argc==2) CreateBMPFile(argv[1], CreateBitmapInfoStruct(hBMP), hBMP, MyHDC);

for(int i=0; i<argc; i++) printf("Argument #%d: %s\n", i, argv);
printf("Desktop DC = %d\nHBITMAP hBMP = %d", (int)hDC, (int)hBMP);
}


Только вот что с этим дальше делать???
39K
04 декабря 2008 года
SaBo
20 / / 04.12.2008
Вот ещё нашёл, выдаёт последовательность чисел, похожие на RGB:

Код:
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <iostream>

using namespace std;

HDC hDCCom;
BYTE* bitPointer;

void Call1()
{
    for(int i=0; i<1280 * 4; i+=4)
    {
        cout<<(int)bitPointer<<endl;
        cout<<(int)bitPointer[i+1]<<endl;
        cout<<(int)bitPointer[i+2]<<endl;
    }
}

void Call2()
{
    for(int i=0; i<1280; ++i)
    {
        COLORREF col = GetPixel(hDCCom, i, 767);
        cout<<(int)GetRValue(col)<<endl;
        cout<<(int)GetGValue(col)<<endl;
        cout<<(int)GetBValue(col)<<endl;
    }
}


int main()
{

    HDC screen = GetDC(NULL);
    RECT rect;
    GetWindowRect(GetDesktopWindow(), &rect);
    hDCCom = CreateCompatibleDC(screen);
    HBITMAP hBitmap = CreateCompatibleBitmap(screen, 1280, 768);
    SelectObject(hDCCom, hBitmap);
    BitBlt(hDCCom, 0, 0, rect.right-rect.left, rect.bottom-rect.top, screen, 0, 0, SRCCOPY);   



    BITMAPINFO bi;
    bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
    bi.bmiHeader.biWidth = 1280;
    bi.bmiHeader.biHeight = 768;
    bi.bmiHeader.biPlanes = 1;
    bi.bmiHeader.biBitCount = 32;
    bi.bmiHeader.biCompression = BI_RGB;
    bi.bmiHeader.biSizeImage = 1280 * 4 * 768;
    bi.bmiHeader.biClrUsed = 0;
    bi.bmiHeader.biClrImportant = 0;

    HBITMAP hBitmap2 = CreateDIBSection( hDCCom, &bi, DIB_RGB_COLORS, (void**) (&bitPointer), NULL, NULL);
    SelectObject(hDCCom, hBitmap2);
    BitBlt(hDCCom, 0, 0, rect.right-rect.left, rect.bottom-rect.top, screen, 0, 0, SRCCOPY);
   




    for(unsigned int i=0; i<100000; ++i)
    {
        Call1();
        Call2();
    }

    return 0;
}
288
05 декабря 2008 года
nikitozz
1.2K / / 09.03.2007
Вопрос уже неоднократно поднимался. Поищите в темах "C++ Builder", "MS Visual C++", "Delphi". Если сейчас найду, скину ссылки.
39K
05 декабря 2008 года
SaBo
20 / / 04.12.2008
Цитата: nikitozz
Вопрос уже неоднократно поднимался. Поищите в темах "C++ Builder", "MS Visual C++", "Delphi". Если сейчас найду, скину ссылки.



То, что он неоднократно обсуждался и не только на этом форуме, это я уже нашёл ))
Только вот результат нулевой

288
05 декабря 2008 года
nikitozz
1.2K / / 09.03.2007
Цитата: SaBo
То, что он неоднократно обсуждался и не только на этом форуме, это я уже нашёл ))
Только вот результат нулевой



В смысле нулевой?

39K
05 декабря 2008 года
SaBo
20 / / 04.12.2008
Нулевой - ничего не получалось.

Но я нашёл две статьи:
http://hellknights.void.ru/articles/0x48k-VisualSpy.htm
http://www.rsdn.ru/article/files/Classes/InitGdiPlus.xml

И по ним написал прогу:

Код:
#include "stdafx.h"
#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;
}


Которая действительно сохраняет скрин в файл png.
Только вот выдаёт ошибку:

Цитата:
Инструкция по адресу "0x4ec142cd" обратилась к памяти по адресу "0x008941ac". Память не может быть "read".

39K
05 декабря 2008 года
SaBo
20 / / 04.12.2008
Если из VC++ запустить просто через F5, от выдаёт такое:

Цитата:
Необработанное исключение в "0x4ec142cd" в "prntscr.exe": 0xC0000005: Нарушение прав доступа при чтении "0x0089440c".

39K
05 декабря 2008 года
SaBo
20 / / 04.12.2008
Всё, разобрался!

Окончательно программа для скрина экрана выглядит так:

Код:
#include "stdafx.h"
#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;
}


Всем спасибо ))
50K
12 мая 2009 года
Owyn
1 / / 12.05.2009
Цитата: SaBo
Всё, разобрался!

Окончательно программа для скрина экрана выглядит так:

Код:
#include "stdafx.h"
#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;
}


Всем спасибо ))



спасибо, работает :D
у меня теперь только один вопрос, как исправить этот код что бы он делал скрин в jpeg? *пс - говорят в этом коде memory leaks

39K
14 мая 2009 года
SaBo
20 / / 04.12.2008
Цитата: Owyn
спасибо, работает :D
у меня теперь только один вопрос, как исправить этот код что бы он делал скрин в jpeg? *пс - говорят в этом коде memory leaks



А хз... Давно уже этим занимался и программа, которую писал, уже давно мне не нужна =))

50K
30 июля 2009 года
foreach
10 / / 30.07.2009
хм
bitmap.Save(L"c:\\screen.png", &png);
Что значит буква L?
288
30 июля 2009 года
nikitozz
1.2K / / 09.03.2007
Цитата: foreach
хм
bitmap.Save(L"c:\\screen.png", &png);
Что значит буква L?



Что это литерал Unicode строки.

89K
19 декабря 2014 года
deko
1 / / 19.12.2014
Я сделал более безопасную версию снимка содержимого окна в MFC (без memory leaks).

Код:
#include <gdiplus.h>
#pragma comment(lib, "GdiPlus.lib")

//Код можно не менять в любой функции CWnd объекта
void CBreslerView::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags){
    if (nChar == 0x50){ //Нажаите Alt+P снимок экрана
        //Инициализация
        using namespace Gdiplus;
        GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR gdiplusToken;
        if ( GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) != S_OK ) return;
        //Определяем размера окна
        CRect rWnd;   GetClientRect(&rWnd);
        int Height, Width;   Width = rWnd.Width();   Height = rWnd.Height(); //GetSystemMetrics(SM_CXSCREEN);
        //Создаем новый DC, идентичный устройству окна и битмап
        HDC scrdc, memdc;   HBITMAP membit;
        scrdc = GetDC()->m_hDC;
        if ( (memdc = CreateCompatibleDC(scrdc)) == 0 ) return;  
        if ( (membit = CreateCompatibleBitmap(scrdc, Width, Height)) == 0 ) return;
        //Снимок
        if ( SelectObject(memdc, membit) == 0 ) return;
        if (BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY) == 0) return;
        //Сохранение
        char cPathDesktop[MAX_PATH];
        if ( SHGetFolderPath(0, CSIDL_DESKTOPDIRECTORY, 0, SHGFP_TYPE_CURRENT, cPathDesktop) == S_OK){ //получение пути до рабочего стола
            Gdiplus::Bitmap bitmap(membit, NULL);
            SYSTEMTIME systime;
            GetLocalTime(&systime);
            char cCurTime[256];
            sprintf_s(cCurTime, "%d-%d-%d %d-%d-%02d", systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute, systime.wSecond);
            wstring szPath = WStr( Str(cPathDesktop)+"Osc img "+Str(cCurTime)+".png");
            static const GUID png = { 0x557cf406, 0x1a04, 0x11d3, { 0x9a, 0x73, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e } };
            bitmap.Save(szPath.c_str(), &png);
        }
        //Очистка
        DeleteObject(membit);
        DeleteDC(memdc);
        GdiplusShutdown(gdiplusToken);
    }
    CScrollView::OnSysKeyDown(nChar, nRepCnt, nFlags);
}

Используемые функции
Код:
#include "Shlobj.h" //для определения пути до рабочего стола
#include <sstream>
#include <windows.h>

template<class C> string Str(const C& a){
    ostringstream ss;   ss.precision(10);   ss << a;
    return ss.str();
}
wstring WStr(const char* sz1){
    size_t Length = strlen(sz1);
    wchar_t* ConvLit = new wchar_t[Length+1];
    MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED, sz1, (int)Length, ConvLit, (int)Length);
    ConvLit[Length] = '\0';
    wstring wszConv(ConvLit);
    delete[] ConvLit;
    return wszConv;
}
inline wstring WStr(const string &sz1)  {return WStr( sz1.c_str() );}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог