我试图在不使用外部库的情况下构建具有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)。因此它可以无限期运行,但会在窗口外部绘制并且无法擦除。
我是编程新手,如果有人可以指出我的方向或让我知道发生了什么,我将不胜感激。 :)
答案 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
处理程序。