GDI 和 DirectX 渲染
Posted
技术标签:
【中文标题】GDI 和 DirectX 渲染【英文标题】:GDI and DirectX rendering 【发布时间】:2016-07-29 19:53:32 【问题描述】:我有两个窗口,一个是由 D3D11 渲染的父窗口,另一个是我想在父窗口上移动的子窗口。
这是我如何创建窗口的代码:
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = 0;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)0;
wcex.lpszMenuName = 0;
wcex.lpszClassName = L"Parent";
wcex.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
if(!RegisterClassEx(&wcex))
return E_FAIL;
if(!(hWnd = CreateWindowEx(WS_EX_COMPOSITED,L"Parent",L"WINDOW",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
WS_VISIBLE,
CW_USEDEFAULT,CW_USEDEFAULT,
WIDTH,HEIGHT,
NULL,NULL,
hInstance,NULL)))
return E_FAIL;
和子窗口
wcex2.cbSize = sizeof(WNDCLASSEX);
wcex2.style = 0;
wcex2.lpfnWndProc = WndProc2;
wcex2.cbClsExtra = 0;
wcex2.cbWndExtra = 0;
wcex2.hInstance = hInstance;
wcex2.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wcex2.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex2.hbrBackground = (HBRUSH)0;
wcex2.lpszMenuName = 0;
wcex2.lpszClassName = L"Child";
wcex2.hIconSm = LoadIcon(NULL,IDI_APPLICATION);
if(!RegisterClassEx(&wcex2))
return E_FAIL;
if(!(chilWnd = CreateWindowEx(0, wcex2.lpszClassName, NULL,
WS_CHILD|WS_CLIPSIBLINGS,
0,0,
200, 100,
hWnd,NULL,
hInstance,0)))
return FALSE;
这是子窗口的 WndProc
case WM_LBUTTONDOWN:
dragWindow = true;
SetCapture(hWnd);
break;
case WM_LBUTTONUP:
ReleaseCapture();
dragWindow = false;
break;
case WM_MOUSEMOVE:
if (dragWindow == true)
RECT mainWindowRect;
POINT pos;
int windowWidth, windowHeight;
pos.x = (int)(short) LOWORD(lp);
pos.y = (int)(short) HIWORD(lp);
GetWindowRect(hWnd,&mainWindowRect);
windowHeight = mainWindowRect.bottom - mainWindowRect.top;
windowWidth = mainWindowRect.right - mainWindowRect.left;
ClientToScreen(hWnd, &pos);
HDWP hdwp = BeginDeferWindowPos(1);
DeferWindowPos(hdwp,
hWnd,
HWND_TOP,
pos.x,
pos.y,
windowWidth,
windowHeight,
SWP_NOZORDER);
EndDeferWindowPos(hdwp);
LockWindowUpdate(hWnd);
RedrawWindow(hWnd, 0, 0, RDW_UPDATENOW);
LockWindowUpdate(NULL);
....
case WM_PAINT:
hdc = BeginPaint(hWnd, &Ps);
FillRect( hdc, &r, (HBRUSH)GetStockObject(GRAY_BRUSH));
EndPaint(hWnd, &Ps);
如果没有 LockWindowUpdate() 函数,我在移动它时会有子窗口跟踪。 所以最终结果是我移动它时子窗口是黑色的。我还能做什么? 我尝试了 GDI 双缓冲,即在 WM_MOUSEMOVE 事件上绘制屏幕外缓冲区 并在 WM_PAINT 事件的窗口上绘制,但结果相同。
【问题讨论】:
在子进程中你可以添加case WM_NCHITTEST: return HTCAPTION;
这将移动窗口(删除WM_MOUSEMOVE/LBUTTONUP/DOWN
)也尝试将WS_EX_COMPOSITED
更改为零
我添加了case WM_NCHITTEST: return HTCAPTION;
并删除了WM_MOUSEMOVE/LBUTTONUP/DOWN
,但是当我移动它时,我有子窗口的痕迹,就像旧位置一样。
不应有任何尾随行。更新您的问题以显示您在做什么。
【参考方案1】:
我的代码几乎所有内容。我向你展示了我是如何创建窗口的,我也有 DirectX 渲染循环:
bool done = false;
MSG msg;
while(!done)
if(PeekMessage(&msg,0,0,0,PM_REMOVE))
if(msg.message == WM_QUIT)
done = true;
else
TranslateMessage(&msg);
DispatchMessage(&msg);
else
Render();
所以在这个 Render() 函数中,我只是清除渲染目标和翻转缓冲区。没有别的了。
D3DXCOLOR color(0.5f,0.5f,0.85f,1.0f);
pDevContext->ClearRenderTargetView(pRenderTarget,color);
pSwapChain->Present(1,0);
【讨论】:
这不是答案。您应该更新您的问题并将其删除。上面的代码也不是一个完整的程序。请参阅帮助部分***.com/help/mcve【参考方案2】:在子窗口中,覆盖WM_NCHITTEST
移动,覆盖WM_WINDOWPOSCHANGING
强制重绘:
LRESULT CALLBACK ChildProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (message)
case WM_WINDOWPOSCHANGING: Render(); break;
case WM_NCHITTEST: return HTCAPTION;
return DefWindowProc(hWnd, message, wParam, lParam);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
if (msg == WM_DESTROY)
PostQuitMessage(0);
return 0;
return DefWindowProc(hWnd, msg, wParam, lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
HWND hWnd;
WNDCLASSEX wc = sizeof(WNDCLASSEX) ;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"WindowClass";
RegisterClassEx(&wc);
hWnd = CreateWindow(wc.lpszClassName, L"appName",
WS_CLIPCHILDREN | WS_VISIBLE | WS_OVERLAPPEDWINDOW,
0, 0, 800, 600, NULL, NULL, hInstance, NULL);
//initialize Direct3D
initD3D(hWnd, 800, 600);
wc.lpfnWndProc = ChildProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszClassName = L"child";
RegisterClassEx(&wc);
CreateWindow(wc.lpszClassName, 0,
WS_BORDER | WS_VISIBLE | WS_CHILD,
0, 0, 300, 200, hWnd, 0, 0, 0);
MSG msg = 0 ;
while (msg.message != WM_QUIT)
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
TranslateMessage(&msg);
DispatchMessage(&msg);
else
Render();
// clean up Direct3D
cleanD3D();
return msg.wParam;
【讨论】:
我覆盖WM_NCHITTEST
来移动,覆盖WM_WINDOWPOSCHANGING
来强制重绘,是的,痕迹消失了,但是当我移动子窗口时,边缘正在切割,子窗口变得越来越小四边形.
没有调整大小的代码,所以没有理由让子窗口变小。你做错了什么,或者你的 Direct3D 代码中有什么东西我猜不出来。
我更新了我有完整代码的帖子link以上是关于GDI 和 DirectX 渲染的主要内容,如果未能解决你的问题,请参考以下文章
DirectX 12和DirectX 11选哪个,有什么区别
DirectX11第二篇 DirectX11渲染管线(2016.05.09更新)