VC++ SDK编程 使用定时器画圆问题

时间:2022-09-03 23:34:03
题目:在屏幕中心画一个圆,圆的半径r随时间减小(每隔一秒半径减小10)
调试错误:经加断点发现,半径r并没有随时间而减小
源代码:

/*在屏幕中心画一个圆,圆的半径r随时间减小(每隔一秒半径减小10)*/

/*调试错误:经加断点发现,半径r并没有随时间而减小*/
#include<windows.h>
#include<tchar.h>
#include<math.h>
#define PI 3.1415926

BOOLEAN InitWindowClass(HINSTANCE hInstance,int nCmdShow);
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM); 

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
MSG msg;
if(!InitWindowClass(hInstance,nCmdShow))
{
MessageBox(NULL,L"创建窗口失败!",_T("创建窗口"),NULL);
return 1;
}

while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);   //将消息的虚拟键转换为字符信息
DispatchMessage(&msg);   //将参数指向的消息通过windows系统传送到指定的窗口函数
}
return(int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT ps;
HBRUSH hBrush;
HPEN hPen;
RECT clientrect;
POINT cer;  //cer为圆心
int r;  //r为圆半径

hDC=BeginPaint(hWnd,&ps);  //获取设备环境
GetClientRect(hWnd,&clientrect);

cer.x=(clientrect.left+clientrect.right)/2;
cer.y=(clientrect.top+clientrect.bottom)/2;
r=min(cer.x,cer.y)-50;

switch(message)
{
case WM_CREATE:
SetTimer(hWnd,9999,1000,NULL);
break;
case WM_TIMER:
if(wParam==9999)
InvalidateRect(hWnd,NULL,true);
break;
case WM_SIZE:
InvalidateRect(hWnd,NULL,true);
break;
case WM_PAINT:
r-=10;   //半径减小10  ?????????????????????????????????????????????????????????
hPen=CreatePen(PS_SOLID,0,RGB(0,0,0)); 
    hBrush=CreateSolidBrush(RGB(255,220,220)); 
    SelectObject(hDC,hPen);  
    SelectObject(hDC,hBrush);  

Ellipse(hDC,cer.x-r,cer.y-r,cer.x+r,cer.y+r);  //绘制圆  

DeleteObject(hPen);
DeleteObject(hBrush);
EndPaint(hWnd,&ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,message,wParam,lParam);
break;
}
return 0;
}

BOOLEAN InitWindowClass(HINSTANCE hInstance,int nCmdShow)
{
WNDCLASSEX wcex;
HWND hWnd;
TCHAR szWindowClass[]=L"窗口示例";  //窗口类名
TCHAR szTitle[]=L"ex4-6";  //窗口标题名

wcex.cbSize=sizeof(WNDCLASSEX);
wcex.style=0;
wcex.lpfnWndProc=WndProc;
wcex.cbClsExtra=0;
wcex.cbWndExtra=0;
wcex.hInstance=hInstance;
wcex.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_APPLICATION));
wcex.hCursor=LoadCursor(NULL,IDC_ARROW);
wcex.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wcex.lpszMenuName=NULL;
wcex.lpszClassName=szWindowClass;
wcex.hIconSm=LoadIcon(wcex.hInstance,MAKEINTRESOURCE(IDI_APPLICATION));

if(!RegisterClassEx(&wcex))
{
return FALSE;
}

hWnd=CreateWindow(szWindowClass,szTitle,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);

if(!hWnd)
return FALSE;

ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);

return TRUE;
}

8 个解决方案

#1


实在是很郁闷,理论上每接受一次WM_PAINT消息,半径r减10
运行的时候发现圆并没有随时间半径减小,加了断点发现r根本就没变化

#2


刚看了楼主的代码。

每一次消息进来后,
r就又变成min(cer.x,cer.y)-50;
进入后又减少10.

所以楼主看到的情况就是每次min(cer.x,cer.y)-50 - 10;

所以,我认为楼主你可以把r=min(cer.x,cer.y)-50;只初始化一次。
用个全局BOOL型bflagStart判断


    cer.x=(clientrect.left+clientrect.right)/2;
    cer.y=(clientrect.top+clientrect.bottom)/2;
if(bflagStart == TRUE)
{
    r=min(cer.x,cer.y)-50;
    bflagStart = FALSE;
}





#3


另外我建议你把r -= 10;放到

case WM_TIMER:
        if(wParam==9999)
        {
            r-= 10;
            InvalidateRect(hWnd,NULL,true);
        }
        break;

#4


  cer.x=(clientrect.left+clientrect.right)/2;
    cer.y=(clientrect.top+clientrect.bottom)/2;
    r=min(cer.x,cer.y)-50;//你的程序使r为常数啊,想变只能在初始化时执行一次。

#5


r是自动变量啊,每次进入函数要在栈上重新生成执行代码
你要么把r定义成静态变量,要么定义成全局变量。

#6


原理:楼上几位已经说得很明白了 ,就是局部变量问题

把你的r声明位置换一下,比如:

#include<windows.h>
#include<tchar.h>
#include<math.h>
#define PI 3.1415926

int r=....;

#7


这画个圆再缩小半径。。这程序编的有点长了。。。

#8


感谢各位大神。。。。
本人10.3号发完求助帖,本来想等到第二天再看的,结果把这事儿给忘了
直到今天又上MFC,才想起来一个多星期前的帖子。
现在问题已经解决,就是变量r的问题。我把r声明为全局变量,然后又借用了二楼的方法,调试成功了
再次感谢CSDN上各位codeing 牛人

#1


实在是很郁闷,理论上每接受一次WM_PAINT消息,半径r减10
运行的时候发现圆并没有随时间半径减小,加了断点发现r根本就没变化

#2


刚看了楼主的代码。

每一次消息进来后,
r就又变成min(cer.x,cer.y)-50;
进入后又减少10.

所以楼主看到的情况就是每次min(cer.x,cer.y)-50 - 10;

所以,我认为楼主你可以把r=min(cer.x,cer.y)-50;只初始化一次。
用个全局BOOL型bflagStart判断


    cer.x=(clientrect.left+clientrect.right)/2;
    cer.y=(clientrect.top+clientrect.bottom)/2;
if(bflagStart == TRUE)
{
    r=min(cer.x,cer.y)-50;
    bflagStart = FALSE;
}





#3


另外我建议你把r -= 10;放到

case WM_TIMER:
        if(wParam==9999)
        {
            r-= 10;
            InvalidateRect(hWnd,NULL,true);
        }
        break;

#4


  cer.x=(clientrect.left+clientrect.right)/2;
    cer.y=(clientrect.top+clientrect.bottom)/2;
    r=min(cer.x,cer.y)-50;//你的程序使r为常数啊,想变只能在初始化时执行一次。

#5


r是自动变量啊,每次进入函数要在栈上重新生成执行代码
你要么把r定义成静态变量,要么定义成全局变量。

#6


原理:楼上几位已经说得很明白了 ,就是局部变量问题

把你的r声明位置换一下,比如:

#include<windows.h>
#include<tchar.h>
#include<math.h>
#define PI 3.1415926

int r=....;

#7


这画个圆再缩小半径。。这程序编的有点长了。。。

#8


感谢各位大神。。。。
本人10.3号发完求助帖,本来想等到第二天再看的,结果把这事儿给忘了
直到今天又上MFC,才想起来一个多星期前的帖子。
现在问题已经解决,就是变量r的问题。我把r声明为全局变量,然后又借用了二楼的方法,调试成功了
再次感谢CSDN上各位codeing 牛人