Скриншот экрана в QT4

Модератор: Модераторы разделов

Andrey801
Сообщения: 17
ОС: windows хочу muilinux.

Скриншот экрана в QT4

Сообщение Andrey801 »

Все здравствуйте.
Возникла необходимость сделать снимок экрана windows (нужно и в linux но это отдельная история ) в QT4.
Насколько понял, платформонезависимого способа нет поэтому решил использовать в windows winAPI.
Компилирую в QT 4.3.0 + MinGW + QDevelop

Код:

BOOL save2bitmap(HWND hWnd,HBITMAP hBitmap) { TCHAR szFileName[MAX_LOADSTRING] = {'x','f','i','l','e'}; BITMAP bmp; BITMAPINFO *pbmi,bmi; BITMAPFILEHEADER bfh; WORD wClrBits; HANDLE hFile; LPBYTE lpData; HDC hDC, hTempDC; unsigned long ulWritten; //Получение параметров рисунка if (!GetObject(hBitmap,sizeof(bmp),&bmp)) return FALSE; //Количество битов под пиксель wClrBits = (WORD)(bmp.bmPlanes*bmp.bmBitsPixel); if (wClrBits == 1); else if (wClrBits <=4) wClrBits = 4; else if (wClrBits <=8) wClrBits = 8; else if (wClrBits <=16) wClrBits = 16; else if (wClrBits <=24) wClrBits = 24; else if (wClrBits <=32) wClrBits = 32; //Выделение памяти для BITMAPINFO if (wClrBits !=24) pbmi = (PBITMAPINFO)LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*(1<<wClrBits)); else pbmi = (PBITMAPINFO)LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER)); //Заполнение BITMAPINFO pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmi->bmiHeader.biHeight = bmp.bmHeight; pbmi->bmiHeader.biWidth = bmp.bmWidth; pbmi->bmiHeader.biPlanes = bmp.bmPlanes; pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; if (wClrBits <24) pbmi->bmiHeader.biClrUsed = (1<<wClrBits); pbmi->bmiHeader.biCompression = BI_RGB; //..количество памяти, необходимоц для таблицы цветов pbmi->bmiHeader.biSizeImage = ((bmp.bmWidth*wClrBits+31)&~31)/8 * bmp.bmHeight; pbmi->bmiHeader.biClrImportant = 0; //Получение памяти под таблицу цветов и массив индексов lpData = (LPBYTE) GlobalAlloc(GMEM_FIXED,pbmi->bmiHeader.biSizeImage); if (!lpData) return FALSE; //Копирование таблицы цветов в выделенную область памяти hDC = GetDC(hWnd); hTempDC = CreateCompatibleDC(hDC); ReleaseDC(hWnd,hDC); SelectObject(hTempDC,hBitmap); bmi = *pbmi; if (!GetDIBits(hTempDC,hBitmap,0,(WORD)bmp.bmHeight,lpData,&bmi,DIB_RGB_COLORS)) { ReleaseDC(hWnd,hDC); //DeleteDC(hTempDC); GlobalFree((HGLOBAL) lpData); return FALSE; } ReleaseDC(hWnd,hDC); //DeleteDC(hTempDC); //Создание файла if ((hFile=CreateFile(szFileName,GENERIC_WRITE,0,NULL,CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL)) == INVALID_HANDLE_VALUE) { GlobalFree((HGLOBAL) lpData); return FALSE; } //Заполняем структуру информации о файле bfh.bfType = 0x4d42; bfh.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) + pbmi->bmiHeader.biSize + pbmi->bmiHeader.biClrUsed*sizeof(RGBQUAD) + pbmi->bmiHeader.biSizeImage); bfh.bfReserved1 = 0; bfh.bfReserved2 = 0; //Смещение данных рисунка от начала файлаэ bfh.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + pbmi->bmiHeader.biSize + pbmi->bmiHeader.biClrUsed*sizeof(RGBQUAD)); //Запись данных в файл //..BITMAPFILEHEADER if (!WriteFile(hFile,&bfh,sizeof(bfh),&ulWritten,NULL)) { GlobalFree(lpData); CloseHandle(hFile); return FALSE; } //..BITMAPINFOHEADER и RGBQUAD if (!WriteFile(hFile,&pbmi->bmiHeader,sizeof(BITMAPINFOHEADER) + pbmi->bmiHeader.biClrUsed*sizeof(RGBQUAD),&ulWritten,NULL)) { GlobalFree(lpData); CloseHandle(hFile); return FALSE; } //..массив цветов и индексов if (!WriteFile(hFile,lpData,pbmi->bmiHeader.biSizeImage,&ulWritten,NULL)) { GlobalFree(lpData); CloseHandle(hFile); return FALSE; } //Запись закончена CloseHandle(hFile); return TRUE; }


получаю отчёт

Код:

Сборка (make)... C:/MinGW/bin/mingw32-make.exe -f Makefile.Release mingw32-make.exe[1]: Entering directory `D:/dev/c/QT+Mingw/fileUp2/bmpToFile/b2f' g++ -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -Wl,-s -Wl,-subsystem,console -mthreads -Wl -o bin\b2f.exe build/dialogimpl.o build/main.o build/moc_dialogimpl.o -L"c:\Qt\4.3.3\lib" -lQtGui4 -lQtCore4 mingw32-make.exe[1]: Leaving directory `D:/dev/c/QT+Mingw/fileUp2/bmpToFile/b2f' build/dialogimpl.o(.text+0xa39):dialogimpl.cpp: undefined reference to `GetObjectW@12' build/dialogimpl.o(.text+0xb70):dialogimpl.cpp: undefined reference to `CreateCompatibleDC@4' build/dialogimpl.o(.text+0xb9e):dialogimpl.cpp: undefined reference to `SelectObject@8' build/dialogimpl.o(.text+0xbe8):dialogimpl.cpp: undefined reference to `GetDIBits@28' collect2: ld returned 1 exit status mingw32-make.exe[1]: *** [bin\b2f.exe] Error 1 C:\MinGW\bin\mingw32-make.exe: *** [release] Error 2 ---------------------- Сборка завершена с 2 ошибками ----------------------


Функция GetObjectW' объявлена в файле wingdi.h, но его подключение не помогло.
Есть ли какой то другой способ сохранить в файл снимок окна в С++ вообще и в QT в частности?

Также буду очень благодарен за информацию как то же сделать в linux.
Большое спасибо всем кто откликнется, Андрей.
Спасибо сказали:
mikluxo
Сообщения: 283
ОС: Slackware 12.2

Re: Скриншот экрана в QT4

Сообщение mikluxo »

Вообще есть в документации
http://doc.trolltech.com/4.2/desktop-screenshot.html
Никакие winApi лучше не использовать(переносимости не будет).

Теперь отчета, скорее всего там нужно прописать -llibgdi32 или что-либо в этом роде(находится в директории lib каталога с mingw). Я как-то Windows Sockets изучал, там нужно было явно прописывать библиотеку, с которой он будет линковаться(ws2_32 была в моем случае).
Но я думаю, что лучше все-таки реализовывать это с помощью средств qt.
Ich weiss, dass ich nichts weiss, aber wissen Sie es auch?
Завистники на что не взглянут,
подымут вечно лай,
А ты себе своей дорогою ступай,
Полают, да отстанут. Крылов
Спасибо сказали:
Andrey801
Сообщения: 17
ОС: windows хочу muilinux.

Re: Скриншот экрана в QT4

Сообщение Andrey801 »

Большущее вам спасибо! Как я умудрился не найти в ассистанте, даже стыдно! Всё оказалось просто как ящик! Конечно средствами QT лучше и проще!
А не знаете как в QT спрятать значок в панели задач? Дело в том что программа висит в трее (использовал код из документации desktop/systray - КАК Я НЕ ЗАМЕТИЛ РЯДОМ КАТАЛОГ SCREENSHOT !)
но при такой реализации, когда окно программы видимо, есть и его значок на панели задач. Мне очень надо его скрыть, опять же в виндовс через winAPI решил... А как в Линукс такое сделать?
Ну и раз уж пошёл спрашивать обо всём, можно ли в QT как то сделать чтобы окно постоянно было поверх других окон =).
Спасибо сказали:
Andrey801
Сообщения: 17
ОС: windows хочу muilinux.

Re: Скриншот экрана в QT4

Сообщение Andrey801 »

PS С последним вопросом разобрался

Код:

int main(int argc, char ** argv) { QApplication app( argc, argv ); Qt::WindowFlags flag = 0; flag |= Qt::SplashScreen;//удаление рамок окна и значка с taskbar flag |= Qt::WindowStaysOnTopHint;//всегда поверх других DialogImpl* win = new DialogImpl(0,flag) ; win->show(); return app.exec(); }
Спасибо сказали:
mikluxo
Сообщения: 283
ОС: Slackware 12.2

Re: Скриншот экрана в QT4

Сообщение mikluxo »

Andrey801 писал(а):
05.11.2008 22:46
Как я умудрился не найти в ассистанте, даже стыдно!

У всех такое бывает время от времени. Сам не раз так мимо проходил.
А насчет трея классная весчь, не сталкивался, но возьму на вооружение. :dwarf:
Ich weiss, dass ich nichts weiss, aber wissen Sie es auch?
Завистники на что не взглянут,
подымут вечно лай,
А ты себе своей дорогою ступай,
Полают, да отстанут. Крылов
Спасибо сказали: