Taskbar aero preview not working with DX9 fullscreen mode

Started by
2 comments, last by beefsteak 10 years, 8 months ago

Hi folks,

I've written a 2D game client in C++ using DirectX/D3D 9.
In case you want to try, you can get it here: http://darkfire-rpg.com/download.html

By default, the game runs in fullscreen mode, at a resolution of 800x600.

When the user leaves the application while running, for example using the alt-tab keys, the application is reduced to the taskbar.

In this state, when the user hovers with the cursor over the taskbar icon, a thumbnail and preview image of the application should be displayed. That's a feature of the "windows desktop manager", also known as "aero effect". In my case, these preview images are always blank and I couldn't find a good way to fix that. (Please note that the problem is limited entirely to the fullscreen mode - in window mode the preview images work perfectly.)

[attachment=17143:taskbar_preview_blank.jpg]

When the application is moved to the background (while in fullscreen mode), the device object I am using (IDirect3DDevice9) goes into the state of a "lost device" (D3DERR_DEVICELOST). In that state I cannot execute any drawing operation. Only after the application is activated again by the user (returning into the foreground), the application is able to "reset" the device and continue drawing. I suspect this might be the root of the problem: As the application is unable to draw while in the background, the preview images which supposedly reflect the current "screen" state, are also blank.

If that was true, how to fix it? - the behaviour of the device cannot be changed in that regard. I experimented with a mechanism that would automatically switch the application to window mode while in the background. That produced lots of unwanted side effects however, leaving the impression of a bad hack.

I also experimented with the windows desktop manager api. Using it allows for example to set a static bitmap for the thumbnail preview in the taskbar. Unfortunately, the windows desktop manager api is not available on windows XP, so when using and linking it, the application won't run on XP anymore.

Did anyone else run into this problem?

What is the proper solution?

Advertisement

A also pondered about the device- and window-class configurations I am using: Maybe some special setting
I am using in fullscreen mode causes incompatibility issues with the windows desktop manager?

In case it matters I have posted my configurations below:


// window style for window-mode: title bar, close box, minimize box
const DWORD Window::WIN_STYLE_WINDOWED = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;

// window style for fullscreen: no titlebar, popup style
const DWORD Window::WIN_STYLE_FULLSCREEN = WS_POPUP | WS_VISIBLE;

Window::Window(HINSTANCE hInstance, WNDPROC messageHandler, LPCTSTR title, int width, int height, bool pFullscreen):
window(NULL),
activeCursor(NULL),
fullscreen(pFullscreen)
{
	// start with default cursor
	activeCursor = DfCursor::C_DEFAULT;

	// define window class properties
	windowClass.style = NULL;
	windowClass.lpfnWndProc = messageHandler;
	windowClass.cbClsExtra = 0;
	windowClass.cbWndExtra = 0;
	windowClass.hInstance = hInstance;
	windowClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APP_ICON));
	windowClass.hCursor = activeCursor == NULL ? NULL : activeCursor->getWinCursor();
	windowClass.hbrBackground = NULL;
	windowClass.lpszMenuName = NULL;
	windowClass.lpszClassName = title;
	RegisterClass(&windowClass);

	// calculate correct window size and position
	RECT clientRect;
	calculatePosition(width, height, fullscreen, &clientRect);

	window = CreateWindow(windowClass.lpszClassName,
			title,
			fullscreen ? WIN_STYLE_FULLSCREEN : WIN_STYLE_WINDOWED,
			clientRect.left, clientRect.top,
			clientRect.right - clientRect.left, clientRect.bottom - clientRect.top,
			GetDesktopWindow(), NULL, windowClass.hInstance, NULL);

	if (window == NULL) {
		throw (TEXT("Window Constructor: Failed to create a new window!"));
	}
}

DfGraphicsManager::DfGraphicsManager(ResourceManager *resourceManager, HWND window, int width, int height, bool fullscreen):
resourceManager(resourceManager),
context(NULL),
device(NULL),
desiredScreenResolutionX(width),
desiredScreenResolutionY(height) {
	context = Direct3DCreate9(D3D_SDK_VERSION);

	if (context == NULL) throw(TEXT("D3DManager Constructor: Failed to create a Direct3D Context!"));

	parameters.BackBufferWidth = width; parameters.BackBufferHeight = height;
	parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
	parameters.BackBufferCount = 1;
	parameters.MultiSampleType = D3DMULTISAMPLE_NONE;
	parameters.MultiSampleQuality = 0;
	parameters.SwapEffect = D3DSWAPEFFECT_FLIP; // flip between front and back buffer
	parameters.hDeviceWindow = window;
	parameters.Windowed = !fullscreen;
	parameters.EnableAutoDepthStencil = true;
	parameters.AutoDepthStencilFormat = D3DFMT_D16;
	parameters.Flags = NULL;
	parameters.FullScreen_RefreshRateInHz = 0;
	parameters.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

	// create the device.
	HRESULT result = context->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
		D3DCREATE_MIXED_VERTEXPROCESSING, &parameters, &device);
	errorCheck(result, TEXT("D3DManager Constructor: Failed to create device!\r\n"));

	// for a 2D application: turn off z-buffer, culling and lightning
	device->SetRenderState(D3DRS_ZENABLE, false);
	device->SetRenderState(D3DRS_LIGHTING, FALSE);
	device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
}

I am not sure, can you try with CreateWindowEx and set layered flag WS_EX_LAYERED and see if that works?

And this might be of interest.

The flag WS_EX_LAYERED didn't change much. For some reason, with WS_EX_LAYERED the preview is not entirely blank anymore, but rather showing an empty (white) window including borders and title bar.

The function DwmSetIconicLivePreviewBitmap is part of the WDM api, which I'd rather not use due to Windows XP support. Using it would allow for some workarounds probably.

This topic is closed to new replies.

Advertisement