Мне для оптимизации некоторой рутины, надо программу которая может делать скриншоты, даже если работают 3д приложения. Еще из требований работа из консоли. Может подскажет кто?
так а какая разница же? обычный метод работает во всех случаях, а если речь об оверлейном выводе (как в AVP 2o1o), то тут уж делу ничем не помочь, ящитаю.
Comer_ что же за обычный метод? я перепробовал кучу, и если запущенно 3д приложение кторое работает на весь экран, но скрин получается, как будто нету вовсе этого приложения
Насколько мне известно, приложения, использующие OpenGL спокойно фоткаются через PrtSc. Вот только как его заставить работать через OpenGL - более сложный вопрос.
spa Код (Text): SLV, 24.06.2009 3:20:52: /* получить снимок экрана */ BOOL PrintScreen(char *file) { HDC hdc, memdc, hdcScreen; BITMAPINFO bmpinfo; BITMAPFILEHEADER finfo; BITMAPINFOHEADER *info; HBITMAP hBitmap; void* pBits; HWND hwndScreen; int i; BYTE *bits; HANDLE fp; long ctsize, imgsize, pixels; char *ptr; BOOL ret_val = FALSE; hdc = GetWindowDC(GetDesktopWindow()); if (hdc == 0) return FALSE; memdc = CreateCompatibleDC(hdc); if (memdc == 0) return FALSE; bmpinfo.bmiHeader.biWidth= GetDeviceCaps(hdc,HORZRES); bmpinfo.bmiHeader.biHeight= GetDeviceCaps(hdc,VERTRES); bmpinfo.bmiHeader.biPlanes=1; bmpinfo.bmiHeader.biBitCount=24; bmpinfo.bmiHeader.biCompression=BI_RGB; bmpinfo.bmiHeader.biSizeImage=0; bmpinfo.bmiHeader.biXPelsPerMeter=2834; bmpinfo.bmiHeader.biYPelsPerMeter=2834; bmpinfo.bmiHeader.biClrUsed=0; bmpinfo.bmiHeader.biClrImportant=0; bmpinfo.bmiHeader.biSize=sizeof(bmpinfo.bmiHeader); hBitmap = CreateDIBSection(hdc, &bmpinfo, DIB_PAL_COLORS, &pBits, 0, 0); SelectObject(memdc, hBitmap); BitBlt(memdc, 0, 0, bmpinfo.bmiHeader.biWidth, bmpinfo.bmiHeader.biHeight, hdc, 0, 0, SRCCOPY); hwndScreen = GetDesktopWindow(); hdcScreen = GetDC(hwndScreen); if (hdcScreen == 0) return FALSE; info = (BITMAPINFOHEADER*)malloc(sizeof(BITMAPFILEHEADER)+(1024*sizeof(RGBQUAD))); if (info == 0) return FALSE; info->biSize = sizeof(BITMAPINFOHEADER); info->biBitCount = 0; i = GetDIBits(hdcScreen, hBitmap, 0, 0, NULL, (BITMAPINFO*)info, DIB_RGB_COLORS); info->biBitCount=8; info->biCompression=BI_RGB; pixels=info->biWidth*info->biHeight; switch(info->biBitCount) { case 4: ctsize=16; imgsize=pixels/2; break; case 8: ctsize=256; imgsize=pixels; break; case 16: ctsize=0; imgsize=pixels*2; break; case 24: ctsize=0; imgsize=pixels*3; break; case 32: ctsize=0; imgsize=pixels*4; break; default: { ReleaseDC( hwndScreen,hdcScreen ); return FALSE; } } bits = (unsigned char*)malloc(imgsize); if (bits == 0) { free(info); return FALSE; } i = GetDIBits(hdcScreen, hBitmap, 0, info->biHeight, bits, (BITMAPINFO*)info, DIB_RGB_COLORS); ptr = (char *)&finfo.bfType; ptr[0]='B'; ptr[1]='M'; finfo.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(sizeof(RGBQUAD)*ctsize); finfo.bfSize=finfo.bfOffBits+imgsize; finfo.bfReserved1=0; finfo.bfReserved2=0; fp = _fcreate(file); if (fp != INVALID_HANDLE_VALUE) { _fwrite(fp, &finfo, sizeof(BITMAPFILEHEADER)); _fwrite(fp, info, sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*ctsize); _fwrite(fp, bits, imgsize); _fclose(fp); ret_val = TRUE; } free(info); free(bits); ReleaseDC(hwndScreen,hdcScreen); return ret_val; }
Ну, собственной как я и говорил, получается скрин как будто нету приложения, а показывает то что под ним. Может это из-за windows7?
Думаю, что тут без DX не обойтись, нужно получить рабочую в данный момент поверхность экрана и сохранить её. Как-то можно, давно уже дела имел с дикс. Я писАл поверх окон, а вот пройдёт ли такое в 3д - не знаю, для 3д юзал оверлей. Или можно повторить действия fraps.
Booster у меня доступ, к удаленной консоли и все. У меня есть и граф удаленный доступ, но мне нужен лишь скришот.
spa Возьмите Taksi (taksi.sourceforge.net) и доточите напильником под вашу конкретную задачу. Работает по тому же принципу, что и Fraps (сиречь хукает вывод DirectX).
Понимаю, но между писать и прочитать не такая уж и большая разница. Код (Text): DDCAPS caps; DDSCAPS2 capsovbb;/*for overlay back buffer*/ extern HWND hWnd; LPDIRECTDRAW7 lpDDraw; DDSURFACEDESC2 ddsd; DDSURFACEDESC2 ddsdo;/*for overlay*/ DDOVERLAYFX ddofx; LPDIRECTDRAWSURFACE7 lpPrimarySurface; LPDIRECTDRAWSURFACE7 lpOverlaySurface; LPDIRECTDRAWSURFACE7 lpOverlaySurfaceBB; #define OVERLAY_WIDTH 256; #define OVERLAY_HEIGHT 64; bool OverlaysSupported(void); bool OverlayUpdate(void); void DDrawDone(void); bool OverlayInit(void); bool DDrawInit(void); bool DDrawInit(void) { if (DirectDrawCreateEx(NULL,(void**)&lpDDraw,IID_IDirectDraw7,NULL)!=DD_OK) return FALSE; ZeroMemory(&caps, sizeof(caps)); caps.dwSize=sizeof(caps); if (lpDDraw->GetCaps(&caps, 0)!=DD_OK) return FALSE; if (lpDDraw->SetCooperativeLevel(hWnd,DDSCL_NORMAL)!=DD_OK) return FALSE; ZeroMemory(&ddsd,sizeof(ddsd)); ddsd.dwSize=sizeof(ddsd); ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE; ddsd.dwFlags=DDSD_CAPS; if (lpDDraw->CreateSurface(&ddsd,&lpPrimarySurface,NULL)!=DD_OK) return FALSE; return TRUE; } ^тут есть немного лишнего кода дальше Код (Text): lpPrimarySurface->Lock(NULL,&ddsd,DDLOCK_WAIT,NULL); //длинну можно получить из ddsd.dwWidth //ширину из <аналогично> .. тут, наверно, лучше побыстрому скопировать куда-нибудь буфер (int*)ddsd.lpSurface //- указатель на буфер .. //и обязательно lpPrimarySurface->Unlock(NULL); При копирвании нужно учитывать округление, насколько я помню. Читал про него на этом сайте. Но когда я эксперементировал - я забивал на всё это и просто копировал raw изображение в файл. Когда вы скопируете ddsd.lpSurface, то там у вас будет raw data, возможно стоит поискать какую-нибудь граф либу, которая поддерживает рав инпут. Посмотрел как это делат taxi - (искать MakeScreenShot) какие-то замарочки с ави а в MakeScreenShotGDIP, соответсвенно, гдиплюс. Бр-р-р-р.
Z3N спасибо за код, мб потом гляну. Просто дхсдк нету, нече нету. Я вообще софт готовый искал ), но все равно спасибо ,как смогу обязательно проверю работоспособность.
Как я и предполагал мой метод не работает при полноэкранном DX приложении, извините. ДДРАУ не хочет создавать нужную поверхность. Хотя при огл всё работает. Во время написания тестовой проги я выяснил, что гдиплюс может работать с ддрав7 поверхностями и сохраниение скриншота не представляет трудности, просто image->Save(...) %). Интересно, как винде удаётся делать скрины и в dx 3д приложениях? Может кто-нибудь знает, что там подвешено на клавишу PrintScreen??? У мена принтскрин снимает и с dx приложений.
Z3N Было бы конечно интересно знать алгоритм работы PrintScreen (если кто то видел инфу - поделитесь). А метод который ты предложил я тоже пробовал (давно). Да и метод этот очень уж тормозной (как мне помнится). Я сейчаз вообще разбираюсь вот с этим делом http://www.wasm.ru/forum/viewtopic.php?id=30224 (вообще занятное это дело - стрелять по воробьям из пушки). Пока получаю скрины только на WinXP. В d3d ещё не пробовал ...