windows API 画正弦曲线,并添加一沿线走的动态圆
Windows API画正弦曲线画动态圆定时器函数
·
今天呢,主要写的是一个在窗口中画一个正弦曲线。
然后呢,让一个圆绕着这条曲线走起来,是一个动态的。
这里呢,有一个很重要的函数就是 定时器 SetTimer函数。
下边是一个关于这个函数的一些具体介绍(来自百度百科)
SetTimer函数的原型
UINT_PTR SetTimer(
HWND hWnd, // 窗口句柄
UINT_PTR nIDEvent, // 定时器ID,多个定时器时,可以通过该ID判断是哪个定时器
UINT nElapse, // 时间间隔,单位为毫秒
TIMERPROC lpTimerFunc // 回调函数
);
返回值:
类型:UINT_PTR
如果函数成功,hWnd参数为0,则返回新建立的时钟编号,可以把这个时钟编号传递给KillTimer来销毁时钟.
如果函数成功,hWnd参数为非0,则返回一个非零的整数,可以把这个非零的整数传递给KillTimer来销毁时钟.
如果函数失败,返回值是零.若想获得更多的错误信息,调用GetLastError函数.
例如
SetTimer(m_hWnd,1,1000,NULL); //一个1秒触发一次的定时器
在MFC程序中SetTimer被封装在CWnd类中,调用就不用指定窗口句柄了
于是SetTimer函数的原型变为:
UINT SetTimer(UINT nIDEvent,UINT nElapse,void(CALLBACK EXPORT *lpfnTimer)(HWND,UINT ,YINT ,DWORD))
当使用SetTimer函数的时候,就会生成一个定时器,函数中nIDEvent指的是定时器的标识,也就是名字。
第三个参数是一个回调函数,在这个函数里,放入你想要做的事情的代码,你可以将它设定为NULL,也就是使用系统默认的回调函数,系统默认的是OnTimer函数。
这个函数怎么生成的呢?
你需要在需要计时器的类的生成OnTimer函数:在ClassWizard里,选择需要计时器的类,添加WM_TIMER消息映射,就自动生成OnTimer函数了。
然后在函数里添加代码,让代码实现功能。每隔一段时间就会自动执行一次。
例:
SetTimer(NULL,1,1000,NULL);
NULL 默认是主进程调用
1:计时器的名称;
1000:时间间隔,单位是毫秒;
NULL:使用OnTimer函数。
当不需要计时器的时候调用KillTimer(nIDEvent);
例如:KillTimer(1);
下边就是具体代码:
/**************************************************************************************
* 问题:在一个windows窗口中画一个正弦曲线,有一个圆心在线上的圆动态绕线前进
* 编辑者:李文顺
* 步骤:
* 1、注册窗口类 (RegisterClassEx)
* 2、创建窗口 (CreateWindowsEx)
* 3、在桌面显示窗口 (ShowWindows)
* 4、更新窗口客户区 (UpdataWindows)
* 5、进入无限循环的消息获取和处理的循环。
* GetMessage ,获取消息
* TranslateMessage ,转换键盘消息
* DispatchMessage ,将消息发送到相应的窗口函数
**************************************************************************************/
#include <windows.h>
#include <math.h>
#include <string.h>
#define IDT_TIMER1 1 //定时器标识
#define SEGMENTS 500 //取点数(在一个周期内取500个点)
#define PI 3.141215926 //圆周率
//函数申明
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
//全局变量
char titleName[]="你随意"; //窗口标题
//图形界面程序的入口
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
//定义存储窗口属性的结构体,12个参数
WNDCLASSEX wcex;
//设置窗口的属性
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW; //从这个窗口派生出的窗口具有的风格
wcex.lpfnWndProc = (WNDPROC)WndProc; //窗口消息处理函数指针
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = NULL; //窗口左上角图标的句柄
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = titleName; //该窗口类的名称
wcex.hIconSm = NULL; //小图标句柄
//注册窗口
::RegisterClassEx(&wcex);
HWND hWnd;
//创建窗口
hWnd = ::CreateWindow(titleName, titleName, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)return FALSE; //创建窗口失败,返回
//显示窗口
::ShowWindow(hWnd, nCmdShow);
//刷新窗口客户区
::UpdateWindow(hWnd);
//循环获取\处理消息
MSG msg;
while(::GetMessage(&msg,0,0,0))
{
::TranslateMessage(&msg); //转换键盘消息
::DispatchMessage(&msg); //将消息发送到相应的窗口函数
}
return (int)msg.wParam;
}
//窗口消息处理函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
//全局变量定义
static int index;
static char sztest[56];
static s_cxClient,s_cyClient;
static int rad;
//窗口句柄定义
HDC hdc;
RECT rect;
PAINTSTRUCT ps;
POINT pt[SEGMENTS];
int i;
//找出500个坐标点
for(i=0;i<SEGMENTS;i++)
{
pt[i].x = s_cxClient/4 + s_cxClient/2*i/SEGMENTS;
pt[i].y = s_cyClient/4 + (int)((s_cyClient/4)*(1-sin(2*PI*i/SEGMENTS)));
}
switch(message)
{
case WM_CREATE: //窗口被创建时的消息
//创建一个定时器,画动态圆用
if(::SetTimer(hWnd,IDT_TIMER1,10,NULL)==0)
{
::MessageBox(hWnd,"定时器安装失败!","03Timer",MB_OK);
}
return 0;
case WM_SIZE: //每次窗口的大小被改变时的消息
{
::GetClientRect(hWnd,&rect); //获取窗口客户区的大小
s_cxClient = rect.right - rect.left;
s_cyClient = rect.bottom - rect.top;
rad=s_cxClient/50;
}
return 0;
case WM_TIMER: //定时器时间到消息
{
hdc=GetDC(hWnd);
if(::IsIconic(hWnd))return 0;
//文字信息显示
wsprintf(sztest,"测试:%d rad: %d",index,rad);
::TextOut(hdc,10,10,sztest,strlen(sztest));
//画笔设置
HPEN hPenWhite = (HPEN)::CreatePen(PS_SOLID,2,RGB(250,250,250)); //自定义白色线
HPEN hPenBlue = (HPEN)::CreatePen(PS_SOLID,2,RGB(0,0,250)); //自定义蓝色线
HPEN hPenBlack = (HPEN)::GetStockObject(BLACK_PEN); //预定义黑色线
//消除上次圆圈痕迹
HPEN hOldPen3 = (HPEN)::SelectObject(hdc,hPenWhite);
::Ellipse(hdc,pt[index].x-rad,pt[index].y-rad,pt[index].x+rad,pt[index].y+rad);
if(index==SEGMENTS)index=0;
else index++;
//画圆
HPEN hOldPen1 = (HPEN)::SelectObject(hdc,hPenBlue);
::Ellipse(hdc,pt[index].x-rad,pt[index].y-rad,pt[index].x+rad,pt[index].y+rad);
//画正弦波
HPEN hOldPen2 = (HPEN)::SelectObject(hdc,hPenBlack);
::Polyline(hdc,pt,SEGMENTS);
}
return 0;
case WM_PAINT:
hdc = ::BeginPaint(hWnd,&ps); //使无效的客户区变得有效,并取得环境设备
//画正弦曲线
::Polyline(hdc,pt,SEGMENTS);
::EndPaint(hWnd,&ps); //释放环境变量句柄,和::BeginPaint 配套使用
break;
case WM_CLOSE:
{
::KillTimer(hWnd,IDT_TIMER1);
::DestroyWindow(hWnd);
}
return 0;
case WM_DESTROY:
::PostQuitMessage(0); //该函数向消息队列中插入一条 WM_QUIT 消息,由 GetMessage 函数捕获返回 0 而退出程序
break;
}
return ::DefWindowProc(hWnd,message,wParam,lParam);
}
/*
Ellipse()画椭圆弧函数
功能: 函数ellipse()使用当前绘图色画一椭圆弧。
用法: 该函数调用方式为void ellipse(int x,int y,int startangle,int endangle,int xradius,int yradius);
说明: 参数x,y为椭圆中心坐标,startangle和endangle为给定的起始角和终止角,xradius与yradius为椭圆的x轴半径
与y轴半径,如果startangle为0 ,endangle等于360度,那么画出的是个完整的椭圆。
ellipse()函数不同于arc()和circle()函数,屏显纵横比不能自动调节。
若需要的是成比例的半径而不是特定的像素距离,则y轴距离必须调节为yradius*aspectratio(y轴半径乘以纵横比)。
*/
更多推荐
已为社区贡献1条内容
所有评论(0)