0
\$\begingroup\$

I've got a Direct3D 9 application which normally runs full-screen. The user is able to select a display adapter to determine which screen it is shown on.

I also offer a Windowed mode which launches on the Primary display - but the user can move it if they wish.

I want to offer a Windowed maximised no border (slight performance hit but it avoids alt-tab issues). The problem is, since the user can't drag the window now, I need to make sure it opens on the appropriate display.

How can I determine the desktop bounds managed by a given adapter index?

Device = New Direct3D9.Device(D3D9,
             Settings.Display.Adapter, //Only applies if PresentParams.Windowed = False
             Direct3D9.DeviceType.Hardware,
             Window.Handle,
             Direct3D9.CreateFlags.HardwareVertexProcessing,
             PresentParams);
\$\endgroup\$
  • \$\begingroup\$ You are going about this all wrong. Enumerate your dimensions by attached display (output) devices and not adapters. There are a number of ways to approach this, and every suggestion I would give you has already been mentioned in the answers on this question on Stack Overflow. I would prefer the GetDesktopWindow (...) approach personally, but this is not the most portable approach and has issues in Windows 8. \$\endgroup\$ – Andon M. Coleman Oct 6 '13 at 23:44
  • \$\begingroup\$ @AndonM.Coleman Thanks for the tip - I was using D3D9.EnumerateAdapterModes(i, Direct3D9.Format.X8R8G8B8, j) to enumerate full-screen modes. It seems the linked solution is the Win32 equivalent but for the current mode? Are you saying this is wrong for full-screen too or that I should swap to the windows Api if I'm windowed. If the latter, is there no way to get a single identifier I can use both when full screen and windowed? (Purely to make display selection consistent for the user) \$\endgroup\$ – Basic Oct 7 '13 at 7:09
  • \$\begingroup\$ @Basic you may have figured out the answer by now but while windowed the adapter format must match that of the current display mode(ie. the same as the desktop). The adapter can't render in more than one mode at a time. You can try and find a device combo that satisfies both windowed and fullscreen modes...Check out the DirectX SDK, specifically: DXUTEnum.cpp. Run the 'SimpleSample' sample for Direct3D and click 'change device'...follow the code... \$\endgroup\$ – P. Avery Aug 10 '14 at 3:50
  • \$\begingroup\$ @P.Avery I ended up fudging this by guesstimating the adapter order and although I get it right most of the time, I've found a couple of edge-cases where it fails. Your solution seems like it does what I need. If you'd care to post that as an answer, I'll accept. Thanks for taking the time to comment. \$\endgroup\$ – Basic Aug 10 '14 at 8:25
1
\$\begingroup\$

The desktop bounds, or 'WorkingArea' of the adapter can be found using the Screen(System.Windows.Forms.Screen) class. First you must have the handle of the device window(System.Windows.Forms.Form) displayed on the adapter. Then you can get the working area like this:

// get the adapter monitor
Screen adapterMonitor = Screen.FromHandle(GetForm().Handle);

// get the working area(System.Windows.Forms.Rectangle)
Rectangle workingArea = adapterMonitor.WorkingArea;

Screen.FromHandle(): Retrieves a Screen for the display that contains the largest portion of the object referred to by the specified handle. (From MSDN)

Also, the Direct3D9 object has a function that returns the handle(IntPtr) of the adapter monitor. I haven't worked with multiple monitors yet so I couldn't say that this method will work well but here is code for SlimDX:

// get the index for the desired adapter
int adapterOrdinal = ?

// you should have this function somewhere in order to retrieve your Direct3D9 object
SlimDX.Direct3D9.Direct3D d3d9 = GetDirect3D9();

// get adapter monitor handle
IntPtr ptr = d3d9.GetAdapterMonitor(adapterOrdinal);

You'll need to compare the monitor handle returned to the list of screens found on the system. Screen.AllScreens is a list of all screens.

As for the adapter mode comments above you should see the DirectX SDK and check out the DXUT classes, especially DXUTenum.cpp. This class is necessary for an application. It will enumerate all adapter display modes and build a collection of 'combinations' that can be used. Display Modes have specific capabilities. Certain modes cannot go fullscreen. Certain modes require a particular back buffer format for use with the adapter format. Certain depth/stencil buffer formats conflict with multisample types...and so on. Were you to try and create a device using improper settings the API will throw an exception...or return 'Invalid Call'. DXUT is very useful and is a great tool for avoiding conflicts.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.