GDI和DirectX渲染

时间:2016-04-08 13:56:16

标签: c++ winapi directx gdi

我有两个窗口,父窗口,我在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事件上的窗口上绘制,但结果相同。

2 个答案:

答案 0 :(得分:0)

我的代码几乎都有。我告诉你我是如何创建窗口的,我还有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);

答案 1 :(得分:0)

在子窗口中,覆盖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;
}