[基本上,我是通过使用DXGI_SWAP_CHAIN_DESC
在GetCurrentProcess
处设置伪造的HWND,但是如果我在下一个字段中选择了false,那为什么还要紧呢?
我的问题是,为什么我的程序在笔记本电脑上不显示蓝屏或黑屏。这是纯C语言中的代码:
#define COBJMACROS
#include <Windows.h>
#include <d3d11.h>
#include <dxgi.h>
#include <stdbool.h>
#ifdef _DEBUG
#define D3DFLAGS D3D11_CREATE_DEVICE_DEBUG
#endif
#define STRINGIFY(x) L#x
#define TOSTRING(x) STRINGIFY(x)
__declspec(thread) HRESULT lasthresult;
#define DIAG MessageBox(0,TOSTRING(__LINE__),L"", MB_ICONERROR), exit(lasthresult)
#define CHECK_HRESULT(fname, ...) ((lasthresult=fname(__VA_ARGS__)) != S_OK ? DIAG : 0)
#define CHECK_HRESULT_INTERFACE(This, fname, ...) ((lasthresult=(This)->lpVtbl->fname(This, __VA_ARGS__)) != S_OK ? DIAG : 0)
((WinMain))()
{
IDXGIFactory1* pFact; IDXGIAdapter* pAdapter;
IDXGIOutput* pOutput; UINT numModes; DXGI_MODE_DESC* pOurMode = 0;
CHECK_HRESULT(CreateDXGIFactory1, &IID_IDXGIFactory1, &pFact);
CHECK_HRESULT_INTERFACE(pFact, EnumAdapters, 0, &pAdapter);
CHECK_HRESULT_INTERFACE(pAdapter, EnumOutputs, 0, &pOutput);
CHECK_HRESULT_INTERFACE(pOutput, GetDisplayModeList, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &numModes, 0);
DXGI_MODE_DESC* displayDescs = _alloca(numModes * sizeof * displayDescs);
CHECK_HRESULT_INTERFACE(pOutput, GetDisplayModeList, DXGI_FORMAT_R8G8B8A8_UNORM, 0, &numModes, displayDescs);
for (UINT mode = 0; mode < numModes; ++mode)
if (displayDescs[mode].Width == 1920 && displayDescs[mode].Height == 1080) pOurMode = displayDescs + mode;
if (pOurMode == 0) DIAG;
IDXGISwapChain* pchain; ID3D11Device* pdevice; ID3D11DeviceContext* pcontext;
CHECK_HRESULT(D3D11CreateDeviceAndSwapChain, pAdapter, D3D_DRIVER_TYPE_UNKNOWN, 0, D3DFLAGS, 0, 0, D3D11_SDK_VERSION, (DXGI_SWAP_CHAIN_DESC[1]) {
*pOurMode, { 1,0 }, DXGI_USAGE_BACK_BUFFER, 2, GetCurrentProcess(), false, DXGI_SWAP_EFFECT_DISCARD, 0,
},& pchain, &pdevice, 0, &pcontext);
ID3D11Texture2D* pBackBuffer; ID3D11RenderTargetView* g_pRenderTargetView;
//CHECK_HRESULT_INTERFACE(pchain, GetBuffer, 0, &IID_ID3D11Texture2D, &pBackBuffer);
const D3D11_TEXTURE2D_DESC textDesc[1] = { {.Width = 1920, .Height = 1080, .MipLevels = 1, .ArraySize = 1,
.Format = DXGI_FORMAT_R8G8B8A8_UNORM, .SampleDesc.Count = 1, .Usage = D3D11_USAGE_DEFAULT, .BindFlags = D3D11_BIND_RENDER_TARGET, .CPUAccessFlags = D3D11_CPU_ACCESS_WRITE,} };
CHECK_HRESULT_INTERFACE(pdevice, CreateTexture2D, textDesc, 0, &pBackBuffer);
CHECK_HRESULT_INTERFACE(pdevice, CreateRenderTargetView, pBackBuffer, 0, &g_pRenderTargetView);
//ID3D11DeviceContext_OMSetRenderTargets(pcontext, 1, &g_pRenderTargetView, 0);
const D3D11_VIEWPORT viewports[1] = { {.Width = 1920, .Height = 1080, .MinDepth = 0.0f, .MaxDepth = 1.0f,} };
ID3D11DeviceContext_RSSetViewports(pcontext, 1, viewports);
const float deepblue[] = { 0.0f, 0.0f, 0.0f, 1.0f };
ID3D11DeviceContext_ClearRenderTargetView(pcontext, g_pRenderTargetView, deepblue);
Sleep(1000);
}
GetCurrentProcess
返回当前过程对象的伪句柄,并且(在当前Windows版本中)为整数值-1。它不指向任何内容,在需要进程句柄的任何上下文(GetProcessTimes
,GetProcessMitigationPolicy
等)之外没有任何意义。重要的是,这不是窗口句柄,并且绝不能转换为窗口句柄。甚至进程的完全限定句柄也不能转换为窗口句柄-这两个对象由Windows操作系统的不同部分管理。
进程句柄是由Windows操作系统的核心组件NT内核创建和管理的。它们代表了内核执行进程切换,管理句柄表和组织线程所需的所有属性。没有内核,无法创建进程句柄。
窗口句柄由用户空间中的User32 DLL创建和管理。用户模式组件和NT内核之间存在一些合作,但是它非常有限-大多数交互发生在User32.dll和Win32k.sys之间。窗口句柄可以不与内核交互而存在,但是可能确实处于内核模式(这是实现定义)中的某些状态。
这意味着您已经破坏了DXGI_SWAP_CHAIN_DESC
结构的合同之一-您的窗口句柄(HWND
)无效。因为没有窗口句柄,所以DXGI不会显示任何内容,也不会显示任何内容给用户。即使您的交换链仅在全屏模式下使用,窗口句柄也是required。
要解决此问题,请使用CreateWindow
或CreateWindowEx
创建一个窗口,并将函数返回的HWND传递给交换链描述符。