Archived

This topic is now archived and is closed to further replies.

Fresh

How to copy a surface to the clipboard as a bitmap?

Recommended Posts

I hate to post large chunks of code, but this is fairly simple so here goes....:
int
CDirectXEngine::CopySurfaceToClipboard(LPDIRECTDRAWSURFACE lpdds) {
	HBITMAP bitmap;
	
	if (!lpdds) {
		g_ErrorLog.ProcessError(0, "Null surface passed to CDirectXEngine::CopySurfaceToClipboard.", 0);
		return (0);
	}

	//OpenClipboard();

	ZeroMemory(&ddsd, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);

	if (!LockSurface(lpdds, &ddsd)) {
		g_ErrorLog.ProcessError(0, "Error Locking Surface in CDirectXEngine::CopySurfaceToClipboard.", 0);
		return (0);
	}

	int width = ddsd.dwWidth;
	int height = ddsd.dwHeight;
	char buf[128];

	sprintf(buf, "Height: %d, Width: %d", height, width);
	g_Console.Message(buf);

	
	UnlockSurface(lpdds, &ddsd);

	HDC hsurfacedc, hbitmapdc;
	
	lpdds->GetDC(&hsurfacedc);
	if (!hsurfacedc) {
		g_ErrorLog.ProcessError(NULL, "CDirectXEngine::CopySurfaceToClipboard: Error using lpdds->GetDC", 0);
		return (0);
	}

	hbitmapdc = CreateCompatibleDC(hsurfacedc);
	if (!hbitmapdc) {
		lpdds->ReleaseDC(hsurfacedc);
		g_ErrorLog.ProcessError(NULL, "CDirectXEngine::CopySurfaceToClipboard: Error using lpdds->GetDC", 0);
		return (0);
	}

	bitmap = (HBITMAP)CreateCompatibleBitmap(hbitmapdc, width, height);
	if (!bitmap) {
		DeleteDC(hbitmapdc);
		lpdds->ReleaseDC(hsurfacedc);
		g_ErrorLog.ProcessError(NULL, "CDirectXEngine::CopySurfaceToClipboard: CreateCompatibleBitmap gave NULL bitmap.", 0);
		return (0);
	}

	SelectObject(hbitmapdc, bitmap);
	
	if (!BitBlt(hbitmapdc, 0, 0, width, height, hsurfacedc, 0, 0, SRCCOPY)) {
		DeleteDC(hbitmapdc);
		lpdds->ReleaseDC(hsurfacedc);
		DeleteObject(bitmap);
		g_ErrorLog.ProcessError(NULL, "CDirectXEngine::CopySurfaceToClipboard: Could not BitBlt surface to bitmap.", 0);
		return (0);
	}

	if (OpenClipboard(NULL)) {
		g_ErrorLog.Log("CDirectXEngine::CopySurfaceToClipboard: Opened the clipboard...");
		SetClipboardData(CF_BITMAP, bitmap);
		CloseClipboard();
	}

	DeleteDC(hbitmapdc);
	lpdds->ReleaseDC(hsurfacedc);
	DeleteObject(bitmap);

	return (1);
}
 
Now that doesn''t work...so where exactly am I being stupid? (Or rather, where am I being stupid that is causing this to fail ). r. "The mere thought hadn''t even begun to speculate about the slightest possibility of traversing the eternal wasteland that is my mind..."

Share this post


Link to post
Share on other sites
I don''t think I can help you much with the clipboard issue but you might want to look into the GetSurfaceDesc function which would be a little faster than LockSurface for getting the width and height.

Share this post


Link to post
Share on other sites
Ah, good point. Does anybody know about the clipboard bit then?
r.

"The mere thought hadn''t even begun to speculate about the slightest possibility of traversing the eternal wasteland that is my mind..."

Share this post


Link to post
Share on other sites
Ok, I''ve replaced the clipboard bit with this:


if (OpenClipboard(main_window_handle)) {
g_ErrorLog.Log("CDirectXEngine::CopySurfaceToClipboard: Opened the clipboard...");
if (EmptyClipboard()) {
g_ErrorLog.Log("CDirectXEngine::CopySurfaceToClipboard: Emptied the clipboard...");
if (SetClipboardData(CF_BITMAP, bitmap))
g_ErrorLog.Log("CDirectXEngine::CopySurfaceToClipboard: SetClipboardData returned handle...");
}
CloseClipboard();
}


Anything obviously wrong there?
r.

"The mere thought hadn''t even begun to speculate about the slightest possibility of traversing the eternal wasteland that is my mind..."

Share this post


Link to post
Share on other sites
Ok, I got it working, but it doesn''t work if I call the final DeleteObject(bitmap), presumably because that deletes the data I''m trying to pass. The question is then, suppose somebody runs my program, copies their data to the clipboard, then exits the program - the bitmap object is still sitting around in memory taking up space? How do I make that object get rid of itself when it''s no longer needed? I can do some checks in my program so that if the copy to clipboard function is called twice, it will delete the old bitmap it copied, but what if the user exits the program - how do I ensure the bitmap object is deleted then when the user no longer needs it ?
r.

"The mere thought hadn''t even begun to speculate about the slightest possibility of traversing the eternal wasteland that is my mind..."

Share this post


Link to post
Share on other sites