y290176346 发表于 2015-10-10 21:36:18

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


}@小甲鱼 #include <windows.h>
#include<iostream>
typedef struct _QPNode
{
        int whiteflag;
        int blackflag;
}*QPNode;
        LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstantce,LPSTR lpCmdLine,int nShowCmd)
{
        static TCHAR zifu[]=TEXT("我是字符串");
        HWND hwnd;
        MSG msg;
        WNDCLASS wndclass;
        wndclass.cbClsExtra=0;
        wndclass.cbWndExtra=0;
        wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
        wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
        wndclass.lpfnWndProc=WndProc;
        wndclass.lpszClassName=TEXT("wodechuangkou2");
        wndclass.style=CS_HREDRAW|CS_VREDRAW;
        wndclass.hInstance=hInstance;
        wndclass.lpszMenuName=NULL;
        if(!RegisterClass(&wndclass))
        {
                MessageBox(NULL,TEXT("buxing"),TEXT("zhenbuxing"),MB_YESNO);
                return 0;
        }
        hwnd=CreateWindow(
                TEXT("wodechuangkou2"),
                TEXT("我是个标题"),
                WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                CW_USEDEFAULT,
                NULL,
                NULL,
                hInstance,
                NULL);
        ShowWindow(hwnd,nShowCmd);
        UpdateWindow(hwnd);
        while(GetMessage(&msg,NULL,0,0))
        {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
        }
        return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAMwParam,LPARAM lParam)
{
        HDC hdc;
        PAINTSTRUCT ps;
        RECT rect;
        int i,j,x,y,h;
        HBRUSH brush,oldbrush;
        HPEN pen,oldpen;
        int xbutton,ybutton;
        static int cxClient,cyClient,whofirst;
        static _QPNode Qipan;


        switch(message)
        {case 1:
        for (i=0;i<15;i++)
        {
                for (j=0;j<15;j++)
                {
                        Qipan.whiteflag=0;
                        Qipan.blackflag=0;
                }
        }
       
        return 0;
        case WM_PAINT:
       
                hdc=BeginPaint (hwnd,&ps);
                GetClientRect (hwnd,&rect);
                //设置原点为中心和窗口的比值,
                SetMapMode(hdc,MM_ISOTROPIC);
                SetWindowExtEx(hdc,80,80,NULL);
                SetViewportExtEx(hdc,cxClient/2,cyClient/2,NULL);
                SetViewportOrgEx(hdc,cxClient/2,cyClient/2,NULL);
                //花棋盘
                x=-80;
                y=-80;
                for(i=1;i<16;i++)
                {
                        x=x+10;
                        MoveToEx(hdc,x,-70,NULL);
                        LineTo(hdc,x,70);
                }

                for(i=1;i<16;i++)
                {
                        y=y+10;
                        MoveToEx(hdc,-70,y,NULL);
                        LineTo(hdc,70,y);
                }
                //画棋盘小黑点
                brush=CreateSolidBrush(RGB(0,0,0));
                oldbrush=(HBRUSH)SelectObject(hdc,brush);

                Ellipse(hdc,39,39,41,41);
                Ellipse(hdc,-39,-39,-41,-41);
                Ellipse(hdc,-39,39,-41,41);
                Ellipse(hdc,39,-39,41,-41);
                Ellipse(hdc,-1,-1,1,1);
                SelectObject(hdc,oldbrush);
                //画棋子
                for (i=0;i<15;i++)
                {
                        for (j=0;j<15;j++)
                        {
                                if (Qipan.blackflag==1)
                                {
                                        brush=CreateSolidBrush(RGB(0,0,0));
                                        oldbrush=(HBRUSH)SelectObject(hdc,brush);
                                        Ellipse(hdc,-70+(i*10)-3,-70+(j*10)-3,-70+(i*10)+3,-70+(j*10)+3);
                  SelectObject(hdc,oldbrush);
                                }
                                if (Qipan.whiteflag==1)
                                {
                                        brush=CreateSolidBrush(RGB(255,255,255));
                                        oldbrush=(HBRUSH)SelectObject(hdc,brush);
                                        Ellipse(hdc,-70+(i*10)-3,-70+(j*10)-3,-70+(i*10)+3,-70+(j*10)+3);
                                        SelectObject(hdc,oldbrush);
                                }
                               

                        }
                }

                EndPaint (hwnd,&ps);
                return 0;
        case WM_LBUTTONDOWN:
                xbutton=LOWORD(lParam);
                ybutton=HIWORD(lParam);
                if (cyClient>cxClient)
                {
                        ybutton=(((double)ybutton-(double)((cyClient-cxClient)/2))/(double)(cxClient/16))+0.5-1;
                        xbutton=xbutton/(double)(cxClient/16)+0.5-1;
                }else
                {
                        ybutton=(double)ybutton/(double)(cyClient/16)+0.5-1;
                        xbutton=((double)xbutton-(double)((cxClient-cyClient)/2))/(double)(cyClient/16)+0.5-1;
                }
                if (whofirst==0)
                {
               
                if (xbutton>=0&&ybutton>=0)
                {
               
                        if (Qipan.whiteflag!=1&&Qipan.blackflag!=1)
                        {
                                Qipan.whiteflag=1;
                                whofirst=1;
                        }else{break;}
       
                }}else
                {
                        if (xbutton>=0&&ybutton>=0)
                        {

                                if (Qipan.blackflag!=1&&Qipan.whiteflag!=1)
                                {
                                        Qipan.blackflag=1;
                                        whofirst=0;
                                }else{
                                        break;
                                }
                               
                                }

                }
       InvalidateRect(hwnd,NULL,TRUE);
                        return 0;

        case WM_SIZE:
                cxClient=LOWORD(lParam);
                cyClient=HIWORD(lParam);
                return 0;
        case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
                //case WM_PAINT:

        }
        return DefWindowProc(hwnd,message,wParam,lParam);
}
求科普!不知道问题所在

小甲鱼 发表于 2015-10-10 21:36:19

OK,找到原因了!

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

修改方案:


……
            for (j = 0; j<15; j++)
            {
                if (Qipan.blackflag==1)
                {
                  brush = CreateSolidBrush(RGB(0, 0, 0));
                  oldbrush = (HBRUSH)SelectObject(hdc, brush);
                  Ellipse(hdc, -70+(i*10)-3, -70+(j*10)-3, -70+(i*10)+3, -70+(j*10)+3);
                  SelectObject(hdc, oldbrush);
                  DeleteObject(brush);
                }
                if (Qipan.whiteflag==1)
                {
                  brush = CreateSolidBrush(RGB(255, 255, 255));
                  oldbrush = (HBRUSH)SelectObject(hdc, brush);
                  Ellipse(hdc, -70+(i*10)-3, -70+(j*10)-3, -70+(i*10)+3, -70+(j*10)+3);
                  SelectObject(hdc, oldbrush);
                  DeleteObject(brush);
                }
……


望采纳!

y290176346 发表于 2015-10-10 21:37:37

程序开始挺正常的 用鼠标拖动窗口大小就这样子了,大侠指点

y290176346 发表于 2015-10-10 21:39:08

来回多拖动几次,就是点右下角的边不放手来回拖动

y290176346 发表于 2015-10-10 21:59:03

大虾们们 不用非要找原因,大概说说这个情况一般会哪里出现问题,是代码逻辑 还是操作系统的bug ,新手不懂,求指点

y290176346 发表于 2015-10-10 22:29:18

问题解决了,把 brush=CreateSolidBrush(RGB(0,0,0));
                oldbrush=(HBRUSH)SelectObject(hdc,brush);
改成SelectObject(hdc,GetStockObject(BLACK_BRUSH));
就好了 可是为什么呢, 能科普吗@小甲鱼

小甲鱼 发表于 2015-10-11 02:07:53

我足足拖了2两分钟才发现问题……就是棋子都变成白色了是吗?

小甲鱼 发表于 2015-10-11 02:17:57

y290176346 发表于 2015-10-10 22:29
问题解决了,把 brush=CreateSolidBrush(RGB(0,0,0));
                oldbrush=(HBRUSH)SelectObject(hd ...

根据这个实验了一下,改成这样棋子非常多的情况下,快速拖动,会出现所有棋子均为黑色……

小甲鱼 发表于 2015-10-11 02:27:41

小甲鱼 发表于 2015-10-11 02:26
OK,找到原因了!

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

对了,更好的办法是一开始就创建两个 static 的画刷(白色和黑色),需要的时候就选入设备环境即可。总是创建、释放,创建、释放,创建、释放的过程也是很浪费资源的……

y290176346 发表于 2015-10-11 09:17:11

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

康小泡 发表于 2015-10-11 12:00:29

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

你没有回复到小甲鱼老师, 你只是回复到了你的帖子下

y290176346 发表于 2015-10-11 17:04:29

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

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

小甲鱼 发表于 2015-10-11 17:34:26

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

是这么一回事,程序初始化的时候会发送 WM_CREATE 消息,可以在这里边初始化需要的画刷和画笔~
页: [1]
查看完整版本: 编写鱼老师五子棋拖动窗口出现问题