C Winapi FillRect()崩溃(多个rects)
C++ WinApi Fillrect() crashes (multiple rects)
我试图习惯于winapi,并决定为我编程的sudoku-generator制作GUI。它应该动态调整到用户选择的Windowsize。到目前为止,一切都按照直觉的方式工作,但是如果WM_PAINT-MSG在短时间内经常发送(例如更改窗口的大小),则程序崩溃。
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
stringstream ss; //not used
RECT rect;
int w;
int h;
HBRUSH coluns=CreateSolidBrush(RGB(50,120,180));
HBRUSH colsel=CreateSolidBrush(RGB(80,150,220));
HBRUSH colmso=CreateSolidBrush(RGB(50,70,190));
switch (message)
{
case WM_SIZE: //
{
GetWindowRect(hwnd,&rect);
menu.wndw=rect.right-rect.left; //menu is a class to store important information
menu.wndh=rect.bottom-rect.top;
h=menu.wndh;
w=menu.wndw;
for(int i=1;i<10;i++)
{
for(int j=1;j<10;j++)
{
menu.feld[i][j].SetSpace((w/4)+((i-1)*(w/20))+i+(2*((i-1)/3)),(h/4)+((j-1)*(h/20))+j+(2*((j-1)/3)),(w/4)+((i)*(w/20))+i+(2*((i-1)/3)),(h/4)+((j)*(h/20))+j+(2*((j-1)/3)));
}
} //feld is a class wich exists in a 10x10 array with the 0s not being used
InvalidateRect(hwnd,NULL, TRUE);
}
break;
case WM_PAINT:
{
RECT re;
w=menu.wndw;
h=menu.wndh;
hdc = BeginPaint(hwnd,&ps);
re.left=(w/4)-4;
re.top=(h/4)-4;
re.right=(w/4)+9*(w/20)+18;
re.bottom=(h/4)+9*(h/20)+18;
FillRect(hdc,&re,CreateSolidBrush(RGB(0,0,0)));
for(int i=1;i<10;i++)
{
for(int j=1;j<10;j++)
{
re=menu.feld[i][j].GetSpace();
if(menu.feld[i][j].GetSelect()==uns)
if(FillRect(hdc,&re,coluns)==0)
MessageBox(hwnd, "fail","fail",0);
if(menu.feld[i][j].GetSelect()==mso)
if(FillRect(hdc,&re,colmso)==0)
MessageBox(hwnd, "fail","fail",0);
if(menu.feld[i][j].GetSelect()==sel)
if(FillRect(hdc,&re,colsel)==0)
MessageBox(hwnd, "fail","fail",0);
}
}
EndPaint(hwnd, &ps);
}
break;
http://www.pic-upload.de/view-22113118/unbenannt.png.html这是执行程序的外观。
现在如前所述,如果您以许多小步骤更改Windowsize,则程序将崩溃。在调用MW_PAINT MSG之后,窗口将窗口冻结,其中1个是白色的,而不是所需的颜色(随机的颜色,每次不同)。我的假设是我需要发布某种资源,因为MBY堆栈会溢出或SMTH,但是我真的不知道我的程序泄漏了。
如果有人能帮助我,我会非常感激。
您每次执行窗口过程都会创建三个刷子。这些手柄永远不会整理。然后在WM_PAINT
处理程序内部创建一个将您传递给FillRect
的刷子,因此永远无法销毁它。
因此,每次执行窗口过程时,您都会泄漏三个手柄(发生了很多事情),每次处理WM_PAINT
时都会再泄漏。简而言之,您的程序像筛子一样泄漏!
创建窗口时,您应该考虑创建这些刷子,并在窗口被破坏时将其销毁。或者,也许在WM_PAINT
处理程序中创建它们,并在使用它们后立即将其销毁。但是,由于它们具有恒定的颜色,因此最好一劳永逸地创建4刷刷子。
您正在泄露GDI
资源作为成员 David Heffernan 所说。
这是如何在该示例中对WM_COMMAND
处理程序正确使用刷子的示例。
如果您不使用库存GDI对象您必须在使用它们后删除它们。
这是一个简单的示例,它在WM_PAINT
处理程序中用红色刷子填充窗口:
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPain( hdc, &ps );
HBRUSH hbrRedBrush = CreateSolidBrush( RGB( 255, 0, 0 ) );
RECT r;
GetClientRect( hWnd, &r );
FillRect( hdc, &r, hbrRedBrush );
DeleteObject( hbrRedBrush ); //you must delete GDI object!
EndPaint( hWnd, &ps );
}
return 0L;
在您的情况下,我将制作4个 static
刷子,然后对我的代码进行稍作重新处理,并在WM_CLOSE
处理程序中添加适当的清理。以下是建议的更改:
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
// add static before HBRUSH
static HBRUSH coluns=CreateSolidBrush(RGB(50,120,180));
static HBRUSH colsel=CreateSolidBrush(RGB(80,150,220));
static HBRUSH colmso=CreateSolidBrush(RGB(50,70,190));
static HBRUSH BlackBrush = CreateSolidBrush(RGB(0,0,0));
switch (message)
{
// this is the problematic handler
case WM_PAINT:
{
//the changed part
FillRect( hdc, &re, BlackBrush );
}
break;
case WM_CLOSE:
{
DeleteObject( BlackBrush );
DeleteObject( coluns );
DeleteObject( colsel );
DeleteObject( colmso );
// other clean up code
}
break;
重要说明:
这次您使用了FillRect
API,但是下次您可能会加载> 的其他内容,从您完成将HDC
恢复到原始状态之后。
您这样做:
HBITMAP bmpOld = (HBITMAP)SelectObject( hdc, myBitmap );
// bmpOld stores the original state of the device context
// you do something with myBitmap
// then you return device context into original state
// by selecting the original value, bmpOld, back into device context
SelectObject( hdc, oldBmp );
DeleteObject( myBitmap );
再次,请注意上述MSDN
中的WM_COMMAND
处理程序,以查看他们是如何做到的。
这是一个出色的Win32
API教程的链接。
最后,我建议您此工具用于检测GDI
泄漏。
如果您还有其他疑问,请发表评论,我会尽快回复。
最好的问候和祝你好运!
- 处理多个异常集合的C++方法
- 尝试通过多个向量访问变量时,向量下标超出范围
- Ardunio UNO解决了多个重叠的定时器循环
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 基于多个条件处理地图中的所有元素
- 为多个会话保留XPtr
- IPC使用多个管道和分支进程来运行Python程序
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- Visual Studio 2019:插入多个C++风格的单行注释
- 扩展光电二极管探测器以支持多个传感器
- 是否可以使用winusb同时与多个相同的usb设备进行通信
- boost::asio如何生成多个协同程序,然后加入它们
- 使用命名空间时出现多个定义错误
- 我需要将多个函数组合为一个函数
- 用于矢量处理的多个线程
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- MPI突然停止了对多个核心的操作
- 在C++中,如何通过几种类型从元组中选择多个元素
- C Winapi FillRect()崩溃(多个rects)