在Console无图形界面程序使用SetTimer

文章讨论了在Windows开发中UpdateData函数用于控件与成员变量数据同步的原理,以及无界面程序如何利用SetTimer和消息循环实现定时任务。通过创建定时器并在回调函数中获取和显示时间来说明其实现过程。
摘要由CSDN通过智能技术生成
UpdateData(true);将控件的值赋值给成员变量
UpdateData(false);将成员变量的值赋值给控件
UpdateData;用来刷新当前对话框
也就是说:当你使用了ClassWizard建立了控件和变量之间的联系后:当你修改了变量的值,而希望对话框控件更新显示,就应该在修改变量后调用UpdateData(FALSE);如果你希望知道用户在对话框中到底输入了什么,就应该在访问变量前调用UpdateData(TRUE)。

-----------------------------------------------------------------------------------------

在Windows开发中免不了一些场景中是无界面的程序。但是我们又需要使用Windows API中的定时器SetTimer来进行定时处理一些任务。


我们都知道Windows是消息驱动的,那定时器SetTimer的超时也是通过消息来驱动的,Console进程主线程没有消息的循环分发,Windows是不会调用我们的超时回调函数的。


这种情况下,我们需要如何处理呢?

我们可以主动在当前线程中添加一个消息循环,来使当前线程中的消息分发下去,从而使定时器可以正常的运行。

在Demo中我创建了一个定时器,设置超时时间为3s,在超时回调函数中,获取当前时间并输出,可以比较清晰的看到执行的结果。
 

#include <iostream>
#include <windows.h>

VOID CALLBACK TimerProc(HWND hwnd, UINT message, UINT iTimerID, DWORD dwTimer)
{
	//获取系统时间
	SYSTEMTIME time;
	GetLocalTime(&time);
	char dateTimeStr[200] = { 0 };
	sprintf_s(dateTimeStr, "%d-%02d-%02d %02d:%02d:%02d", time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond);

	std::cout << dateTimeStr << std::endl;
}

int main()
{
	UINT_PTR uTimerID = SetTimer(NULL, 0, 1000, TimerProc);// 3000三秒, TimerProc);

	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0))
	{
		DispatchMessage(&msg);
	}

	KillTimer(NULL, uTimerID);

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用SetTimer函数和线程函数编写的贪吃蛇C语言程序的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <windows.h> // 定义界面大小 const int WIDTH = 30; const int HEIGHT = 20; // 定义蛇的长度和位置 const int INIT_LENGTH = 3; int snakeX[100] = {0}; int snakeY[100] = {0}; int snakeLength = INIT_LENGTH; // 定义食物的位置 int foodX = 0; int foodY = 0; // 定义蛇的运动方向 const int DIR_UP = 1; const int DIR_DOWN = 2; const int DIR_LEFT = 3; const int DIR_RIGHT = 4; int direction = DIR_RIGHT; // 定义游戏是否结束 int gameOver = 0; // 定义互斥锁 HANDLE mutex; // 定义绘制界面函数 void draw() { // 清空控制台输出 system("cls"); // 输出上边界 for (int i = 0; i < WIDTH; i++) { printf("#"); } printf("\n"); // 输出中间部分 for (int i = 0; i < HEIGHT; i++) { printf("#"); for (int j = 0; j < WIDTH - 2; j++) { if (i == foodY && j == foodX) { printf("*"); // 输出食物 } else { int flag = 0; for (int k = 0; k < snakeLength; k++) { if (i == snakeY[k] && j == snakeX[k]) { printf("o"); // 输出蛇 flag = 1; break; } } if (flag == 0) { printf(" "); // 输出空格 } } } printf("#\n"); } // 输出下边界 for (int i = 0; i < WIDTH; i++) { printf("#"); } printf("\n"); } // 定义更新蛇的位置函数 void updateSnake() { // 上锁 WaitForSingleObject(mutex, INFINITE); // 更新蛇的位置 for (int i = snakeLength - 1; i > 0; i--) { snakeX[i] = snakeX[i - 1]; snakeY[i] = snakeY[i - 1]; } switch (direction) { case DIR_UP: snakeY[0]--; break; case DIR_DOWN: snakeY[0]++; break; case DIR_LEFT: snakeX[0]--; break; case DIR_RIGHT: snakeX[0]++; break; } // 判断是否吃到食物 if (snakeX[0] == foodX && snakeY[0] == foodY) { snakeLength++; foodX = rand() % (WIDTH - 2) + 1; foodY = rand() % (HEIGHT - 2) + 1; } // 判断是否碰到墙壁或自身 if (snakeX[0] < 0 || snakeX[0] >= WIDTH - 2 || snakeY[0] < 0 || snakeY[0] >= HEIGHT || snakeLength > 100) { gameOver = 1; } for (int i = 1; i < snakeLength; i++) { if (snakeX[0] == snakeX[i] && snakeY[0] == snakeY[i]) { gameOver = 1; break; } } // 解锁 ReleaseMutex(mutex); } // 定义更新方向函数 void updateDirection(int dir) { // 上锁 WaitForSingleObject(mutex, INFINITE); // 更新方向 switch (dir) { case 'w': if (direction != DIR_DOWN) { direction = DIR_UP; } break; case 's': if (direction != DIR_UP) { direction = DIR_DOWN; } break; case 'a': if (direction != DIR_RIGHT) { direction = DIR_LEFT; } break; case 'd': if (direction != DIR_LEFT) { direction = DIR_RIGHT; } break; } // 解锁 ReleaseMutex(mutex); } // 定义定时器回调函数 VOID CALLBACK timerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { // 更新蛇的位置 updateSnake(); // 绘制界面 draw(); // 判断游戏是否结束 if (gameOver == 1) { KillTimer(NULL, idEvent); printf("Game Over!\n"); } } // 定义线程函数 DWORD WINAPI threadProc(LPVOID lpParameter) { while (1) { char ch = _getch(); updateDirection(ch); } } // 主函数 int main() { // 初始化互斥锁 mutex = CreateMutex(NULL, FALSE, NULL); // 初始化随机数种子 srand((unsigned)time(NULL)); // 初始化蛇的位置 for (int i = 0; i < INIT_LENGTH; i++) { snakeX[i] = INIT_LENGTH - i - 1; snakeY[i] = 0; } // 初始化食物的位置 foodX = rand() % (WIDTH - 2) + 1; foodY = rand() % (HEIGHT - 2) + 1; // 创建定时器 UINT_PTR timerID = SetTimer(NULL, 0, 100, timerProc); // 创建线程 HANDLE thread = CreateThread(NULL, 0, threadProc, NULL, 0, NULL); // 等待线程结束 WaitForSingleObject(thread, INFINITE); // 关闭互斥锁 CloseHandle(mutex); return 0; } ``` 该程序使用SetTimer函数创建定时器和CreateThread函数创建线程,实现了贪吃蛇的基本功能。其中,定时器回调函数timerProc用于更新蛇的位置和绘制界面,线程函数threadProc用于监听键盘输入并更新蛇的运动方向。程序使用互斥锁对共享资源进行保护,确保线程安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值