鱼C论坛

 找回密码
 立即注册
查看: 3240|回复: 12

编写鱼老师五子棋拖动窗口出现问题

[复制链接]
发表于 2015-10-10 21:36:18 | 显示全部楼层 |阅读模式
1鱼币

}@小甲鱼
  1. #include <windows.h>
  2. #include<iostream>
  3. typedef struct _QPNode
  4. {
  5.         int whiteflag;
  6.         int blackflag;
  7. }*QPNode;
  8.         LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
  9. int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstantce,LPSTR lpCmdLine,int nShowCmd)
  10. {
  11.         static TCHAR zifu[]=TEXT("我是字符串");
  12.         HWND hwnd;
  13.         MSG msg;
  14.         WNDCLASS wndclass;
  15.         wndclass.cbClsExtra=0;
  16.         wndclass.cbWndExtra=0;
  17.         wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
  18.         wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
  19.         wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
  20.         wndclass.lpfnWndProc=WndProc;
  21.         wndclass.lpszClassName=TEXT("wodechuangkou2");
  22.         wndclass.style=CS_HREDRAW|CS_VREDRAW;
  23.         wndclass.hInstance=hInstance;
  24.         wndclass.lpszMenuName=NULL;
  25.         if(!RegisterClass(&wndclass))
  26.         {
  27.                 MessageBox(NULL,TEXT("buxing"),TEXT("zhenbuxing"),MB_YESNO);
  28.                 return 0;
  29.         }
  30.         hwnd=CreateWindow(
  31.                 TEXT("wodechuangkou2"),
  32.                 TEXT("我是个标题"),
  33.                 WS_OVERLAPPEDWINDOW,
  34.                 CW_USEDEFAULT,
  35.                 CW_USEDEFAULT,
  36.                 CW_USEDEFAULT,
  37.                 CW_USEDEFAULT,
  38.                 NULL,
  39.                 NULL,
  40.                 hInstance,
  41.                 NULL);
  42.         ShowWindow(hwnd,nShowCmd);
  43.         UpdateWindow(hwnd);
  44.         while(GetMessage(&msg,NULL,0,0))
  45.         {
  46.                 TranslateMessage(&msg);
  47.                 DispatchMessage(&msg);
  48.         }
  49.         return msg.wParam;

  50. }

  51. LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM  wParam,LPARAM lParam)
  52. {
  53.         HDC hdc;
  54.         PAINTSTRUCT ps;
  55.         RECT rect;
  56.         int i,j,x,y,h;
  57.         HBRUSH brush,oldbrush;
  58.         HPEN pen,oldpen;
  59.         int xbutton,ybutton;
  60.         static int cxClient,cyClient,whofirst;
  61.         static _QPNode Qipan[15][15];


  62.         switch(message)
  63.         {case 1:
  64.         for (i=0;i<15;i++)
  65.         {
  66.                 for (j=0;j<15;j++)
  67.                 {
  68.                         Qipan[i][j].whiteflag=0;
  69.                         Qipan[i][j].blackflag=0;
  70.                 }
  71.         }
  72.        
  73.         return 0;
  74.         case WM_PAINT:
  75.        
  76.                 hdc=BeginPaint (hwnd,&ps);
  77.                 GetClientRect (hwnd,&rect);
  78.                 //设置原点为中心和窗口的比值,
  79.                 SetMapMode(hdc,MM_ISOTROPIC);
  80.                 SetWindowExtEx(hdc,80,80,NULL);
  81.                 SetViewportExtEx(hdc,cxClient/2,cyClient/2,NULL);
  82.                 SetViewportOrgEx(hdc,cxClient/2,cyClient/2,NULL);
  83.                 //花棋盘
  84.                 x=-80;
  85.                 y=-80;
  86.                 for(i=1;i<16;i++)
  87.                 {
  88.                         x=x+10;
  89.                         MoveToEx(hdc,x,-70,NULL);
  90.                         LineTo(hdc,x,70);
  91.                 }

  92.                 for(i=1;i<16;i++)
  93.                 {
  94.                         y=y+10;
  95.                         MoveToEx(hdc,-70,y,NULL);
  96.                         LineTo(hdc,70,y);
  97.                 }
  98.                 //画棋盘小黑点
  99.                 brush=CreateSolidBrush(RGB(0,0,0));
  100.                 oldbrush=(HBRUSH)SelectObject(hdc,brush);

  101.                 Ellipse(hdc,39,39,41,41);
  102.                 Ellipse(hdc,-39,-39,-41,-41);
  103.                 Ellipse(hdc,-39,39,-41,41);
  104.                 Ellipse(hdc,39,-39,41,-41);
  105.                 Ellipse(hdc,-1,-1,1,1);
  106.                 SelectObject(hdc,oldbrush);
  107.                 //画棋子
  108.                 for (i=0;i<15;i++)
  109.                 {
  110.                         for (j=0;j<15;j++)
  111.                         {
  112.                                 if (Qipan[i][j].blackflag==1)
  113.                                 {
  114.                                         brush=CreateSolidBrush(RGB(0,0,0));
  115.                                         oldbrush=(HBRUSH)SelectObject(hdc,brush);
  116.                                         Ellipse(hdc,-70+(i*10)-3,-70+(j*10)-3,-70+(i*10)+3,-70+(j*10)+3);
  117.                     SelectObject(hdc,oldbrush);
  118.                                 }
  119.                                 if (Qipan[i][j].whiteflag==1)
  120.                                 {
  121.                                         brush=CreateSolidBrush(RGB(255,255,255));
  122.                                         oldbrush=(HBRUSH)SelectObject(hdc,brush);
  123.                                         Ellipse(hdc,-70+(i*10)-3,-70+(j*10)-3,-70+(i*10)+3,-70+(j*10)+3);
  124.                                         SelectObject(hdc,oldbrush);
  125.                                 }
  126.                                

  127.                         }
  128.                 }

  129.                 EndPaint (hwnd,&ps);
  130.                 return 0;
  131.         case WM_LBUTTONDOWN:
  132.                 xbutton=LOWORD(lParam);
  133.                 ybutton=HIWORD(lParam);
  134.                 if (cyClient>cxClient)
  135.                 {
  136.                         ybutton=(((double)ybutton-(double)((cyClient-cxClient)/2))/(double)(cxClient/16))+0.5-1;
  137.                         xbutton=xbutton/(double)(cxClient/16)+0.5-1;
  138.                 }else
  139.                 {
  140.                         ybutton=(double)ybutton/(double)(cyClient/16)+0.5-1;
  141.                         xbutton=((double)xbutton-(double)((cxClient-cyClient)/2))/(double)(cyClient/16)+0.5-1;
  142.                 }
  143.                 if (whofirst==0)
  144.                 {
  145.                
  146.                 if (xbutton>=0&&ybutton>=0)
  147.                 {
  148.                
  149.                         if (Qipan[xbutton][ybutton].whiteflag!=1&&Qipan[xbutton][ybutton].blackflag!=1)
  150.                         {
  151.                                 Qipan[xbutton][ybutton].whiteflag=1;
  152.                                 whofirst=1;
  153.                         }else{break;}
  154.          
  155.                 }}else
  156.                 {
  157.                         if (xbutton>=0&&ybutton>=0)
  158.                         {

  159.                                 if (Qipan[xbutton][ybutton].blackflag!=1&&Qipan[xbutton][ybutton].whiteflag!=1)
  160.                                 {
  161.                                         Qipan[xbutton][ybutton].blackflag=1;
  162.                                         whofirst=0;
  163.                                 }else{
  164.                                         break;
  165.                                 }
  166.                                
  167.                                 }

  168.                 }
  169.          InvalidateRect(hwnd,NULL,TRUE);
  170.                         return 0;

  171.         case WM_SIZE:
  172.                 cxClient=LOWORD(lParam);
  173.                 cyClient=HIWORD(lParam);
  174.                 return 0;
  175.         case WM_DESTROY:
  176.                 PostQuitMessage(0);
  177.                 return 0;
  178.                 //case WM_PAINT:

  179.         }
  180.         return DefWindowProc(hwnd,message,wParam,lParam);
  181. }
复制代码

求科普!不知道问题所在
捕获1.PNG

最佳答案

查看完整内容

OK,找到原因了! 原因是每次调用 brush = CreateSolidBrush(RGB(0, 0, 0)); 都会创建一个新的画刷,但在程序结束前并没有被释放掉……因此,多次触发 WM_PAINT 消息调用 CreateSolidBrush() 创建新画刷的结果便是占用了所有的资源(内存泄漏),brush 存放最后一次成功创建的画刷,也就是后边的 brush = CreateSolidBrush(RGB(255, 255, 255)); 因此全部都变成白色的了…… 修改方案: 望采纳!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-10 21:36:19 | 显示全部楼层
OK,找到原因了!

原因是每次调用 brush = CreateSolidBrush(RGB(0, 0, 0)); 都会创建一个新的画刷,但在程序结束前并没有被释放掉……因此,多次触发 WM_PAINT 消息调用 CreateSolidBrush() 创建新画刷的结果便是占用了所有的资源(内存泄漏),brush 存放最后一次成功创建的画刷,也就是后边的 brush = CreateSolidBrush(RGB(255, 255, 255)); 因此全部都变成白色的了……

修改方案:


  1. ……
  2.             for (j = 0; j<15; j++)
  3.             {
  4.                 if (Qipan[i][j].blackflag==1)
  5.                 {
  6.                     brush = CreateSolidBrush(RGB(0, 0, 0));
  7.                     oldbrush = (HBRUSH)SelectObject(hdc, brush);
  8.                     Ellipse(hdc, -70+(i*10)-3, -70+(j*10)-3, -70+(i*10)+3, -70+(j*10)+3);
  9.                     SelectObject(hdc, oldbrush);
  10.                     DeleteObject(brush);
  11.                 }
  12.                 if (Qipan[i][j].whiteflag==1)
  13.                 {
  14.                     brush = CreateSolidBrush(RGB(255, 255, 255));
  15.                     oldbrush = (HBRUSH)SelectObject(hdc, brush);
  16.                     Ellipse(hdc, -70+(i*10)-3, -70+(j*10)-3, -70+(i*10)+3, -70+(j*10)+3);
  17.                     SelectObject(hdc, oldbrush);
  18.                     DeleteObject(brush);
  19.                 }
  20. ……
复制代码


望采纳!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-10-10 21:37:37 | 显示全部楼层
程序开始挺正常的 用鼠标拖动窗口大小就这样子了  ,大侠指点
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-10-10 21:39:08 | 显示全部楼层
来回多拖动几次,就是点右下角的边不放手来回拖动
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-10-10 21:59:03 | 显示全部楼层
大虾们们 不用非要找原因,大概说说这个情况一般会哪里出现问题,是代码逻辑 还是操作系统的bug ,新手不懂,求指点
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-10-10 22:29:18 | 显示全部楼层
问题解决了,把 brush=CreateSolidBrush(RGB(0,0,0));
                oldbrush=(HBRUSH)SelectObject(hdc,brush);
改成SelectObject(hdc,GetStockObject(BLACK_BRUSH));
就好了 可是为什么呢, 能科普吗@小甲鱼
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-11 02:07:53 | 显示全部楼层
我足足拖了2两分钟才发现问题……就是棋子都变成白色了是吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-11 02:17:57 | 显示全部楼层
y290176346 发表于 2015-10-10 22:29
问题解决了,把 brush=CreateSolidBrush(RGB(0,0,0));
                oldbrush=(HBRUSH)SelectObject(hd ...

根据这个实验了一下,改成这样棋子非常多的情况下,快速拖动,会出现所有棋子均为黑色……
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-11 02:27:41 | 显示全部楼层
小甲鱼 发表于 2015-10-11 02:26
OK,找到原因了!

原因是每次调用 brush = CreateSolidBrush(RGB(0, 0, 0)); 都会创建一个新的画刷,但 ...

对了,更好的办法是一开始就创建两个 static 的画刷(白色和黑色),需要的时候就选入设备环境即可。总是创建、释放,创建、释放,创建、释放的过程也是很浪费资源的……
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-10-11 09:17:11 | 显示全部楼层
感谢鱼老师,可是你每天都3点钟睡觉吗? 对身体可不好,视频中看到你提过这个释放画刷,或者是画笔,但是没有这个DeleteObject函数的功能概念,经过思考总结下,HPEN 或者是HBRUSH 这个类型是句柄,句柄相当于一个特殊的指针,这个类型的变量只是指向了这个创建的画刷,每次调用WM_paint消息,就无限的创建,变量只是改变的一个画刷 或画笔的把柄,但是是指的画刷依然存在,越建越多,然后内存存不下了 就出问题了 !可以这么理解吗,还有不会设置提问题的答案,不知道这么设置!我找找
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-11 12:00:29 | 显示全部楼层
y290176346 发表于 2015-10-11 09:17
感谢鱼老师,可是你每天都3点钟睡觉吗? 对身体可不好,视频中看到你提过这个释放画刷,或者是画笔,但是没 ...

你没有回复到小甲鱼老师, 你只是回复到了你的帖子下
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-10-11 17:04:29 | 显示全部楼层
小甲鱼 发表于 2015-10-11 02:27
对了,更好的办法是一开始就创建两个 static 的画刷(白色和黑色),需要的时候就选入设备环境即可。总是 ...

感谢鱼老师,可是你每天都3点钟睡觉吗? 对身体可不好,视频中看到你提过这个释放画刷,或者是画笔,但是没有这个DeleteObject函数的功能概念,经过思考总结下,HPEN 或者是HBRUSH 这个类型是句柄,句柄相当于一个特殊的指针,这个类型的变量只是指向了这个创建的画刷,每次调用WM_paint消息,就无限的创建,变量只是改变的一个画刷 或画笔的把柄,但是是指的画刷依然存在,越建越多,然后内存存不下了 就出问题了 !可以这么理解吗,还有不会设置提问题的答案,不知道这么设置!我找找
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-10-11 17:34:26 | 显示全部楼层
y290176346 发表于 2015-10-11 17:04
感谢鱼老师,可是你每天都3点钟睡觉吗? 对身体可不好,视频中看到你提过这个释放画刷,或者是画笔,但是 ...

是这么一回事,程序初始化的时候会发送 WM_CREATE 消息,可以在这里边初始化需要的画刷和画笔~
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-25 22:07

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表