在Direct3D(DirectX)应用程序中禁用alt-enter

8
我正在阅读《DirectX 10游戏编程入门》来学习一些DirectX,并尝试完成提出的练习(对于那些有这本书的人来说是第4章)。
其中一个练习要求使用IDXGIFactory::MakeWindowAssociation禁用Alt+Enter功能(切换全屏模式)。
然而,它仍然会切换到全屏模式,我不明白为什么。这是我的代码:
HR(D3D10CreateDevice(
        0,                 //default adapter
        md3dDriverType,
        0,                 // no software device
        createDeviceFlags, 
        D3D10_SDK_VERSION,
        &md3dDevice) );

IDXGIFactory *factory;
HR(CreateDXGIFactory(__uuidof(IDXGIFactory), (void **)&factory));
HR(factory->CreateSwapChain(md3dDevice, &sd, &mSwapChain));
factory->MakeWindowAssociation(mhMainWnd, DXGI_MWA_NO_ALT_ENTER);
ReleaseCOM(factory);

MakeWindowAssociation返回一个HRESULT,因此在调用它时也要使用HR()进行包装,以查看是否由于某种原因而失败。(只是一句旁注,我认为它实际上并没有失败) - Daniel Dimovski
@Danial:已经尝试过了,没有运气。不过我打算开始悬赏,就当玩笑一样。 - Andreas Bonini
2个回答

13

我认为问题出在这里。

由于您是自己创建设备的(而不是通过工厂),因此对您创建的工厂进行的任何调用都不会改变任何内容。

因此,您可以选择:

a)更早地创建工厂并通过它来创建设备

或者

b)通过以下代码检索实际用于创建设备的工厂。

IDXGIDevice * pDXGIDevice;
HR( md3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&pDXGIDevice) );

IDXGIAdapter * pDXGIAdapter;
HR( pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter) );

IDXGIFactory * pIDXGIFactory;
pDXGIAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&pIDXGIFactory);

在 SwapChain 创建之后,通过该工厂调用函数。

pIDXGIFactory->MakeWindowAssociation(mhMainWnd, DXGI_MWA_NO_ALT_ENTER);

MSDN: IDXGIFactory


我已经尝试过了(我已经谷歌搜索了一段时间); 不幸的是它不起作用。 所有的调用都成功了,但是alt tab仍然最大化了窗口。 - Andreas Bonini
奇怪的是,我试了一下你的代码,并且使用创建该设备的工厂时它对我有效。如果我的回答有些不清楚,这里是重写后的代码链接:http://pastebin.com/sz2YzdZf - Daniel Dimovski
使用您在pastebin上发布的完全相同的代码,按alt-enter仍会最大化窗口。这是我使用的确切代码:http://koper.wowpanda.net/directx-code.rar - Andreas Bonini
我试过你的代码,当我用DXGI_MWA_NO_WINDOW_CHANGES替换DXGI_MWA_NO_ALT_ENTER时,它对我有效。这个函数似乎非常不可靠,并且依赖于用于创建设备和/或交换链的函数。 - Daniel Dimovski

1

我有同样的问题,而且

b) 通过下面的代码检索实际用于创建设备的工厂。

这对我也没有帮助,可能是因为我有很多Direct3D10窗口,但IDXGIFactory::MakeWindowAssociation只记住了一个。但在WM_SETFOCUS或WM_ACTIVATE上调用该函数也没有帮助,原因未知。

所以我找到的一种方法是使用低级键盘钩子:参见SetWindowsHookEx,参数为WH_KEYBOARD_LL。稍后,您可以通过已经按下(VK_LMENU|VK_RMENU|VK_MENU)条件下的VK_RETURN虚拟码来捕获Alt+Enter。在识别到这种情况后,只需返回1而不是调用CallNextHookEx函数。


不要忘记只为您的窗口执行此操作,因为默认情况下钩子将安装在整个系统中。
  1. 例如,当您的进程变为活动状态时安装钩子,并在其停用时卸载(请参阅WM_ACTIVATEAPP消息)。
  2. 或者,在钩子中检查前景窗口是否为您的窗口(请参阅GetForegroundWindow WinAPI函数)。
- dev_null
每次创建新设备时调用MakeWindowAssociation()会起作用吗?或者为每个设备创建一个IDXGIFactory? - Daniel Dimovski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接