P
hmm, schade dass bisher niemand geantwortet hat... hätte echt gedacht, mir kann da jemand helfen. Naja mal sehen wie es weiter geht...
Denn ich habe mittlerweile ein wenig weitergeforscht und habe bei NeHe eine Funktion gefunden, mit der man über ein HBITMAP (das mit LoadImage aus einer Datei geladen wird) eine Textur erstellt wird. Das funktioniert wunderbar (Quellcode siehe unten). Auch habe ich Funktionen gefunden, die einen Screenshot erstellen und diesen in eine Datei speichern. Auch diese funktioniert.
Nun habe ich versucht, diese beiden Funktionen zu vereinen und damit mein Problem zu lösen. Dazu wollte ich zum Kopieren der Bilddaten von dem DC des Desktop in den DC des HBITMAP statt der Funktion BitBlt die Funktion StretchBlt verwenden, damit das resultierende BITMAP anschließend die Größe 1024x1024 hat.
Nur leider funktioniert das nicht, ich erhalte nur ein schwarzes Bild. Die MessageBox (siehe Quelltext unten) gibt folgendes aus:
BMP is(1024x1024) with 1bpp, 128 byte width
Auch wenn ich nur die Methode zum Abspeichern eines Screenshot anpasse und das BitBlt durch ein StretchBlt ersetze, wird nur ein vollkommen schwarzes Bitmap mit einer Größe von 1024x1024 gespeichert...
Ich nehme an, dass ich beim StretchBlt irgendwas nicht richtig mache oder beachte, aber ich weiß wirklich nicht mehr weiter, gerade auch weil ich nur sehr wenig Kenntnis über die WINAPI habe...
Ich hoffe, dass mir da jemand weiterhelfen kann...
Danke schon mal für eure Hilfe.
Ach so, mittlerweile benutze ich kein Dev-C++ mehr, sonder Code::Blocks mit MinGW, aber ich denke, das tut nix zur Sache.
Quelltext meiner angepassten Funktion:
BOOL LoadScreenshot(GLuint &texid, GLuint size) {
HBITMAP hBMP; // Handle of The Bitmap
BITMAP BMP; // Bitmap Structure
HDC hdcDesktop; // Device Context of the desktop
// from where we will copy data
HDC hdcBMP; // Device Context we will copy
// data to
HWND hwnd; // the desktop window
RECT rc; // the desktop dimensions
int Width; // the width of the desktop
int Height; // the height of the desktop
// get desktop and device context
hwnd = GetDesktopWindow();
hdcDesktop = GetDC(hwnd);
Width = rc.right - rc.left;
Height = rc.bottom - rc.top;
// get desktop dimension
GetWindowRect(hwnd, &rc);
Width = rc.right;
Height = rc.bottom;
// prepare HBITMAP
hdcBMP = CreateCompatibleDC(hdcDesktop);
hBMP = CreateCompatibleBitmap(hdcBMP, size, size);
HBITMAP hBMPTMP = (HBITMAP) SelectObject(hdcBMP, hBMP);
if (!hBMP) { // Does The Bitmap Exist?
return FALSE; // If Not Return False
}
// copy data from desktop DC to BMP DC with stretching
// to get 2^n square size
SetStretchBltMode(hdcDesktop, HALFTONE); // setup StretchBlt
StretchBlt( hdcBMP, 0, 0, size, size, // Destination
hdcDesktop, rc.left, rc.top, Width, Height, // Source
SRCCOPY // what to do
);
// Get The Object, Parameters are:
// hBMP: handle to graphics object
// sizeof(BMP): size of buffer for object information
// &BMP: buffer for object information
GetObject(hBMP, sizeof(BMP), &BMP);
char buffer[1024];
sprintf(buffer, "BMP is (%ix%i) with %ibpp, %i byte width.", BMP.bmWidth, BMP.bmHeight, BMP.bmBitsPixel, BMP.bmWidthBytes);
MessageBox(NULL, buffer, "BMP Info", MB_OK);
// switch type
GLuint type;
if(BMP.bmBitsPixel == 24) {
type = GL_BGR_EXT;
} else if(BMP.bmBitsPixel == 32) {
type = GL_BGRA_EXT;
} else {
return FALSE; // BMP is not usable
}
// Pixel Storage Mode (Word Alignment / 4 Bytes)
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_2D, texid); // Bind To The Texture ID
glTexParameteri(GL_TEXTURE_2D, // Linear Min Filter
GL_TEXTURE_MIN_FILTER, GL_LINEAR
);
glTexParameteri(GL_TEXTURE_2D, // Linear Mag Filter
GL_TEXTURE_MAG_FILTER, GL_LINEAR
);
glTexImage2D( GL_TEXTURE_2D, 0, 3,
BMP.bmWidth, BMP.bmHeight,
0, GL_BGR_EXT,
GL_UNSIGNED_BYTE,
BMP.bmBits
);
// Release desktop device context
ReleaseDC(hwnd, hdcDesktop);
// Delete device contexts no longer used
DeleteDC(hdcBMP);
// Delete The Object
DeleteObject(hBMP);
DeleteObject(hBMPTMP);
return TRUE;
}
Quelltext der Methode zum Laden einer Textur aus einer Datei
(zu googlen mit "NeHeLoadBitmap"), funktioniert wunderbar:
BOOL LoadBitmap(LPTSTR szFileName, GLuint &texid)
{
HBITMAP hBMP; // Handle of The Bitmap
BITMAP BMP; // Bitmap Structure
glGenTextures(1, &texid); // Create The Texture
hBMP = (HBITMAP) LoadImage( GetModuleHandle(NULL),
szFileName,
IMAGE_BITMAP,
0, 0,
LR_CREATEDIBSECTION | LR_LOADFROMFILE );
if (!hBMP) { // Does The Bitmap Exist?
return FALSE; // If Not Return False
}
// Get The Object, Parameters are:
// hBMP: handle to graphics object
// sizeof(BMP): size of buffer for object information
// &BMP: buffer for object information
GetObject(hBMP, sizeof(BMP), &BMP);
// Pixel Storage Mode (Word Alignment / 4 Bytes)
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_2D, texid); // Bind To The Texture ID
glTexParameteri(GL_TEXTURE_2D, // Linear Min Filter
GL_TEXTURE_MIN_FILTER, GL_LINEAR
);
glTexParameteri(GL_TEXTURE_2D, // Linear Mag Filter
GL_TEXTURE_MAG_FILTER, GL_LINEAR
);
glTexImage2D( GL_TEXTURE_2D, 0, 3,
BMP.bmWidth, BMP.bmHeight,
0, GL_BGR_EXT,
GL_UNSIGNED_BYTE,
BMP.bmBits
);
DeleteObject(hBMP); // Delete The Object
return TRUE; // Loading Was Successful
}
Quelltext der Methode zum Speichern eines Screenshots in einer Datei:
void SaveWindowBitmap(HWND hWnd, LPCTSTR lpszFile) {
/////////////////////////////////////////////////////////////////
// Bild aufnehmen
RECT rc;
::GetWindowRect(hWnd, &rc);
int nWidth = rc.right - rc.left;
int nHeight = rc.bottom - rc.top;
HWND hWndSc = ::GetDesktopWindow();
HDC hdc = ::GetDC(hWndSc);
HDC memDC = ::CreateCompatibleDC(hdc);
HBITMAP hbm = ::CreateCompatibleBitmap(hdc, nWidth, nHeight);
HBITMAP hbmOld = (HBITMAP)::SelectObject(memDC, hbm);
::BringWindowToTop(hWnd);
::BitBlt(memDC, 0, 0, nWidth, nHeight, hdc, rc.left, rc.top, SRCCOPY);
/////////////////////////////////////////////////////////////////
// ::StretchBlt(memDC, 0, 0, 1024, 1024, hdc, 0, 0, rc.left, rc.top, SRCCOPY);
// Bilddaten ermitteln
BITMAPINFO bmi;
ZeroMemory(&bmi, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = nWidth;
bmi.bmiHeader.biHeight = nHeight;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 32 * nWidth * nHeight / 8;
BYTE *pbBits = new BYTE[bmi.bmiHeader.biSizeImage];
::GetDIBits( memDC,
hbm,
0,
bmi.bmiHeader.biHeight,
pbBits,
&bmi,
DIB_RGB_COLORS
);
BITMAPFILEHEADER bfh;
bfh.bfType = ('M' << 8) + 'B';
bfh.bfSize = sizeof(BITMAPFILEHEADER)
+ bmi.bmiHeader.biSizeImage
+ sizeof(BITMAPINFOHEADER);
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
/////////////////////////////////////////////////////////////////
// Bilddaten speichern
HANDLE hfile = CreateFile( lpszFile,
GENERIC_WRITE,
0,
0,
OPEN_ALWAYS,
0,
0
);
DWORD dwWritten;
WriteFile(hfile, &bfh, sizeof(bfh), &dwWritten, NULL);
WriteFile(hfile, &bmi.bmiHeader, sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
WriteFile(hfile, pbBits, bmi.bmiHeader.biSizeImage, &dwWritten, NULL);
CloseHandle(hfile);
::SelectObject(memDC, hbmOld);
::DeleteDC(memDC);
::ReleaseDC(hWndSc,hdc);
::DeleteObject(hbm);
delete[] pbBits;
}