LRESULT函数之前的HWND的GetDC()

时间:2018-07-18 02:00:59

标签: c++ winapi

我试图在不使用外部库的情况下构建具有3d渲染功能的软件。我对GetDC()和ReleaseDC()有点困惑。如果我在LRESULT()循环后编写以下代码,该程序将运行几秒钟,然后冻结。 (我为BitBlt()创建了两个用于双缓冲的DC)

for

但是,根据此链接about SetPixel() crashing after a time,我应该将GetDC()移出循环。但是,我一定做错了,因为如果我这样做...

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {

   HDC hdc = GetDC(hWnd);
   HDC memdc = CreateCompatibleDC(hdc);
   HBITMAP membmp = CreateCompatibleBitmap(hdc, width, height);
   SelectObject(memdc, membmp);

   ...
   switch (message) {
   ...
   }
}

...我意识到我无法在LRESULT循环之外使用SelectObject()。实际上,我希望Visual Studio甚至不在LRESULT循环之前就与GetDC(hWnd)一起使用,因为它是在循环的第一行中创建的。因此,可悲的是,我唯一的选择似乎是用NULL替换hWnd。

HDC hdc = GetDC(hWnd);
HDC memdc = CreateCompatibleDC(hdc);
HBITMAP membmp = CreateCompatibleBitmap(hdc, width, height);


LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    TCHAR greeting[] = _T("program_name");
    PAINTSTRUCT ps;
    SelectObject(memdc, membmp);

...
}

现在我不能再清除窗口,因为它依赖于InvalidateRect(hWnd,NULL,TRUE)。因此它可以无限期运行,但会在窗口外部绘制并且无法擦除。

我是编程新手,如果有人可以指出我的方向或让我知道发生了什么,我将不胜感激。 :)

2 个答案:

答案 0 :(得分:1)

如果您是编程和c ++的新手,则应该首先学习该语言的基础知识,而不是从开始使用WinAPI开始。

“ LRESULT()循环”也不是循环,而是由message loop调用的回调函数。

关于您的问题:您的应用程序在收到WM_PAINT消息时应绘制其Windows内容。

答案 1 :(得分:1)

您的代码设置有误。尝试以下方法:

HDC hmemdc = NULL;
HBITMAP membmp = NULL;
HBITMAP oldbmp = NULL;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_CREATE: {
            HDC hdc = GetDC(hWnd);
            membmp = CreateCompatibleBitmap(hdc, width, height);
            memdc = CreateCompatibleDC(hdc);
            oldbmp = (HBITMAP) SelectObject(memdc, membmp);
            ReleaseDC(hWnd, hdc);
            break;
        }

        case WM_DESTROY: {
            SelectObject(memdc, oldbmp);
            DeleteDC(memdc); memdc = NULL;
            DeleteObject(membmp); membmp = NULL;
            break;
        }

        case WM_ERASEBKGND: {
            return 1;
        }

        case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            BitBlt(hdc, 0, 0, width, height, memdc, 0, 0, SRCCOPY);
            EndPaint(hWnd, &ps);
            break;
        }

        ...
    }

    return DefWindowProcc(hWnd, message, wParam, lParam);
}

然后,您可以根据需要将3D图像简单地绘制到hmemdc / membmp中,并在需要向操作系统发出需要重新绘制窗口的信号时调用InvalidateRect()最新的位图。

但是,如果要为窗口使用内存位图,则可以考虑改用UpdateLayeredWindow(),并完全摆脱WM_PAINT / WM_ERASEBKGND处理程序。

>