Advanced Question Blitting from a SURFHANDLE into a WindowHandle (dialog box)?

jedidia

shoemaker without legs
Addon Developer
Joined
Mar 19, 2008
Messages
10,882
Reaction score
2,133
Points
203
Location
between the planets
Well, it's me and some crazy Ideas again. Thing is this: I had to write up a complete GUI architecture for IMS2 anyways, because the panel interactions will get too complex for coding everything on a special case basis, so in the long run it'll save me lots of time.

But I don't only need panels. I also need a generic editor in a dialog box. Scenario editor is capable of doing all that needs to be done, but isn't optimised for the task, and there's some additional helpers I'd like to put in.

Now the thing is this: I have a perfectly capable GUI and I know perfectly how to use it (having written it myself, after all). On the other hand I haven't used the WIN GUI in... god, it's been over a decade, and even then only sparingly.
If I could blit stuff from an orbiter texture surface into the window, that would let me use my own GUI, which would take me less time (and look nicer, too).
 

Bibi Uncle

50% Orbinaut, 50% Developer
Addon Developer
Joined
Aug 12, 2010
Messages
192
Reaction score
0
Points
0
Location
Québec, QC
You can call oapiGetSketchpad() to get the Sketchpad of your SURFHANDLE. Then, you call Sketchpad::GetDC() to get the DC. After that, you can use standard GDI to blit the texture in your win32 window.

However, Sketchpad::GetDC() doesn't work with every 3D clients. You should check if D3D9 and D3D11 clients return something from this function.

Hope it helps ;)
 

kamaz

Unicorn hunter
Addon Developer
Joined
Mar 31, 2012
Messages
2,298
Reaction score
4
Points
0
The code below copies bitmap from SURFHANDLE (inSurf) onto a Gdiplus::Graphics object and is known to work with D3D9 client.

Code:
void Ripper::MakeImage(void)
{
	CREATETIMER;
	//Log("Ripper::MakeImage starting");

	if ( scanLine == 0 ) {
		//Log("Ripper::MakeImage waiting for a new image");
		WaitForSingleObject(hNewImageEvent, 1500);
	}

	STARTTIMER;

	SURFHANDLE inSurf = surf;

	WaitForSingleObject(hSurfMutex, INFINITE);

	int x = pPanel->GetScreenRect()->X;
	int y = scanLine + pPanel->GetScreenRect()->Y;
	int w = pPanel->GetScreenRect()->Width;
	int h = scanStep;


	Gdiplus::Graphics *pGraphics = pPanel->GetGraphics();
	HDC bmpDC = pGraphics->GetHDC();
	HDC surfDC = oapiGetDC(inSurf);
	
	if (BitBlt(bmpDC, x, y, w, h, surfDC, 0, scanLine, SRCCOPY) == 0) {
		DWORD dwErr = GetLastError();
		Log("Ripper::MakeImage BitBlt() failed. GetLastError()=%d (0x%08x)", dwErr, dwErr);
	}
	oapiReleaseDC(inSurf, surfDC);
	ReleaseMutex(hSurfMutex);
	pGraphics->ReleaseHDC(bmpDC);
	pPanel->ReleaseGraphics();
	
	if ( pPanel->GetRenderer() ) {
		//pPanel->GetRenderer()->Update(pPanel->GetScreenRect());
		Gdiplus::Rect rect(x, y, w, h);
		pPanel->GetRenderer()->Update(&rect);
	}

	scanLine = scanLine + scanStep;
	if ( scanLine >= pPanel->GetScreenRect()->Height ) {
		scanLine = 0;
		SetEvent(hImageDoneEvent);
	}

	//Log("Ripper::MakeImage done in %d ms", GETTIMER);
}

This comes from Ripper.cpp in VNCMFD , you're welcome to adapt and reuse. :)
http://orbiter-forum.com/showthread.php?p=411088&postcount=93
 

Bibi Uncle

50% Orbinaut, 50% Developer
Addon Developer
Joined
Aug 12, 2010
Messages
192
Reaction score
0
Points
0
Location
Québec, QC
Be aware that oapiGetDC() function is not necessarily working with every client, as stated in the doc.
 
Top