我正在尝试在不使用外部库的情况下构建具有3d渲染功能的软件。我有点混淆了GetDC()和ReleaseDC()。如果我在LRESULT()循环之后编写以下代码,程序会运行几秒钟,然后就会死机。(我已经用BitBlt()为双缓冲创建了两个dc)
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) {
...
}
}
但是,根据这个链接about SetPixel() crashing after a time,我应该将GetDC()移到循环之外。但是,我一定是做错了,因为如果我这么做了.
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);
...
}
..。我意识到我不能在LRESULT循环之外使用SelectObject()。事实上,在LRESULT循环之前,visual studio甚至不会使用GetDC(hWnd),因为它是在循环的第一行创建的。所以,不幸的是,我唯一的选择似乎是将hWnd替换为NULL。
HDC hdc = GetDC(NULL);
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)。因此,它可以无限运行,但会在窗口外绘制,并且不能擦除。
我是编程新手,如果有人能给我指明方向或让我知道发生了什么,我将不胜感激。:)
发布于 2018-07-18 10:27:54
如果您是编程和c++的新手,那么应该首先学习该语言的基础知识,而不是从使用WinAPI开始。
您的"LRESULT()循环“也不是一个循环,而是一个由message loop调用的回调函数。
关于您的问题:当您的应用程序接收到WM_PAINT时,它应该绘制它的窗口内容。
发布于 2018-07-19 06:35:09
您的代码设置完全错误。试着这样做:
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
处理程序。
https://stackoverflow.com/questions/51392505
复制相似问题