C++的console使用windows的消息机制,定时器等

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

C++的console使用windows的消息。

大家在编写console中,估计需要使用windows消息机制 差不多是 定时器。

因此,在网上可以搜索到相关的内容。

youyulangzi的专栏 天行健,君子以自强不息

http://blog.csdn.net/youyulangzi/article/details/5841199 
 

转自博客:http://www.cnblogs.com/phinecos/archive/2008/03/08/1096691.html

作者:洞庭散人

我现在项目是一个控制台程序,用到的Win32API都是与界面无关的,今天需要加入定时器刷新的功能,由于没有消息循环,所以WM_TIMER消息应该如何处理呢?综合了下网上找到的资料,写了个简单的demo,个人以为这种在一个线程中创建定时器,再通过指定的回调函数来处理定时器触发的模式是比较好的。

感谢楼上的两位的工作,为了进一步方便后来者更好的使用。我在楼上的基础上进一步进行了封装。
可以除了定时器外,可以使用其他的消息,比如:WSAAsyncSelect 等消息。
使用定时器的代码例子为:
UINT myProcTimer(UINT _message, MSG* _data, void* _userdata)
{
	printf("WM_TIMER in work thread count/n");
	return 1;
}
int main(int argc, char* argv[])
{
	CWindowsMessageHelper* pThread = new CWindowsMessageHelper;
        ///开启线程
	pThread->start();
	///printf("start ...");
	UINT timerId = pThread->start_timer(10);
        ///用户自己增加消息处理
	pThread->addMessageHanler(WM_TIMER,  myProcTimer, NULL, timerId);
	Sleep(100);
        ///移除我们的TimerId. (如果不移除timerId, 只移除我们的消息处理函数,后面框架会自动将没有处理timer进行停止掉)
        pThread->stop_timer(timerId);
pThread->removeMessageHandler(WM_TIMER,myProcTimer);
	_getch();
        ///停止当前的线程.
	pThread->stop();
	_getch();
	delete pThread;
	return 0;
}
 
如果需要在此线程中处理业务逻辑,借用ruby 中 的 Celluloid里面的思想。
我们尽量将此逻辑放到此线程中来调用。因此我们可以用 	UINT doBusiness(WPFP_Do_Business _callbck, void* _data, UINT _bSync = 0);
来处理逻辑,其中_callback的回调函数是在新的线程中来调用的。 可以参考我们写的 start_timer 和 stop_timer 的函数。
_bSync 默认是0,意味着我们不等待_callback函数调用就返回。 如果为1,则意味着,我们需要在调用_callback之后,才返回。
希望下面的代码,能够给你带来方便。^_^ :)
 
代码:
/// CWindowsMessageHelper.hpp
#pragma warning(disable: 4786)
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <vector>
#include <map>


typedef void (*WPFP_Do_Business)(void* _data);


#define WM_DO_CHORE    (WM_USER + 200)
#define WM_DO_STOP_TIMER  (WM_DO_CHORE+1)


///处理返回非0,0表明其他handler可以继续处理.
typedef UINT (*WPFP_Process_Message)(UINT _message,MSG* _data,void* _userdata);
class CWindowsMessageHelper
{
public:
	CWindowsMessageHelper();
	~CWindowsMessageHelper();


	void start();
	void stop();
	
	UINT doBusiness(WPFP_Do_Business _callbck, void* _data);
	
	///_wParam 如果为0. 则将匹配_messageId都转发,否则只有_wParam匹配相等才转发.
	void addMessageHanler(UINT _messageId,WPFP_Process_Message _handler,void* _data, WPARAM _wParam = 0);
	void removeMessageHandler(UINT _messageId, WPFP_Process_Message _handler);


	UINT start_timer(UINT _elaseInMilliseconds);
	void stop_timer(UINT _timerId);

private:
	static DWORD CALLBACK mainThread(PVOID pvoid);
	static void  CALLBACK timeProc(HWND hWnd,UINT uMsg,UINT  idEvent,DWORD dwTime);
        static void start_timer_chore(void* _data);
	static void stop_timer_chore(void* _data);


	UINT processMessage(UINT _message, MSG* _data);


	static UINT  doChores_Callback(UINT _message,MSG* _data, void* _userdata);
	static UINT do_stop_timerCallback(UINT _messge, MSG* _data, void* _userdata);
	UINT  doChores(UINT _message,MSG* _data);


	void stop_timer_imp(UINT _timerId);
	 
private:  
	WPFP_Do_Business m_do_business;
	void* m_do_business_data;
	HANDLE m_thread;
	DWORD m_threadId;
	struct InnerData
	{
		WPARAM m_wParam;
		WPFP_Process_Message m_process;
		void* m_pUserData;
	};	
	std::map<UINT, std::vector<InnerData> > m_handleMessage;
	HANDLE m_event;
};
 
 
 
/// CWindowsMessageHelper.cpp
#include "CWindowsMessageHelper.hpp"
CWindowsMessageHelper::CWindowsMessageHelper()
{
	m_do_business = NULL;
	m_thread = NULL;
	m_threadId = 0;
	addMessageHanler(WM_DO_CHORE, doChores_Callback,this);
	addMessageHanler(WM_DO_STOP_TIMER, do_stop_timerCallback,this);
	m_event = CreateEvent(NULL,TRUE,FALSE,NULL);
}


CWindowsMessageHelper::~CWindowsMessageHelper()
{
  CloseHandle(m_event);
}





UINT CWindowsMessageHelper::doBusiness(WPFP_Do_Business _callbck,void* _data,UINT _bSync)
{
	if(m_do_business) return 0;
	if(!_callbck) return 0;


	m_do_business = _callbck;
	m_do_business_data = _data;
	PostThreadMessage(m_threadId,WM_DO_CHORE, 0,0);


	if(_bSync)
	{
	  WaitForSingleObject(m_event,INFINITE);
	  ResetEvent(m_event);
	}
	return 1;
}
UINT  CWindowsMessageHelper::doChores_Callback(UINT _message, MSG* _data, void* _userdata)
{
	CWindowsMessageHelper* pThis = (CWindowsMessageHelper*) _userdata;
	return pThis->doChores(_message,_data);
}
UINT CWindowsMessageHelper::do_stop_timerCallback(UINT _messge, MSG* _data, void* _userdata)
{
	CWindowsMessageHelper* pThis = (CWindowsMessageHelper*) _userdata;
	pThis->stop_timer_imp(_data->wParam);
	return 1;
}


UINT  CWindowsMessageHelper::doChores(UINT _message, MSG* _data)
{
	WPFP_Do_Business callback = m_do_business;
	void* userData = m_do_business_data;
	m_do_business_data = NULL;
	m_do_business = NULL;
	if(callback)
	{
	 callback(userData);
	 SetEvent(m_event);
	}
	return 1;
}
struct CData_Timer
{
	CWindowsMessageHelper* m_pThis;
	UINT m_timerId;
	UINT m_idEvent;
	UINT m_elapse;


};
void CWindowsMessageHelper::start_timer_chore(void* _data)
{
	CData_Timer* pData = (CData_Timer*)_data;
	
    UINT timerId = SetTimer(NULL,pData->m_idEvent, pData->m_elapse,CWindowsMessageHelper::timeProc);
	pData->m_timerId = timerId;
}


void CWindowsMessageHelper::stop_timer_chore(void* _data)
{
	CData_Timer* pData = (CData_Timer*)_data;
	pData->m_pThis->stop_timer_imp(pData->m_timerId);
}
UINT CWindowsMessageHelper::start_timer(UINT _elaseInMilliseconds)
{
	CData_Timer timerData;
	timerData.m_elapse = _elaseInMilliseconds;
	timerData.m_idEvent = WM_USER+1;
	timerData.m_pThis = this;
	UINT timerId = 0;
	doBusiness(start_timer_chore, &timerData, 1);
	timerId = timerData.m_timerId;
	return timerId;
}


void CWindowsMessageHelper::stop_timer(UINT _timerId)
{
	CData_Timer timerData;
	timerData.m_pThis = this;
	timerData.m_timerId = _timerId;
	doBusiness(stop_timer_chore, &_timerId,1);
}
void CWindowsMessageHelper::stop_timer_imp(UINT _timerId)
{
  KillTimer(NULL,_timerId);
}
void CWindowsMessageHelper::start()
{
	HANDLE hand = CreateThread(NULL,0,CWindowsMessageHelper::mainThread, this,0,&m_threadId);
	WaitForSingleObject(m_event,INFINITE);
	ResetEvent(m_event);
	m_thread = hand;
}
void CWindowsMessageHelper::stop()
{
  PostThreadMessage(m_threadId, WM_QUIT,0,0);
}
void CWindowsMessageHelper::timeProc(HWND hWnd,UINT uMsg,UINT  idEvent,DWORD dwTime)
{
	DWORD threadId = GetCurrentThreadId();
	///用户没有截获此消息,我们停止此定时器.
	PostThreadMessage(threadId, WM_DO_STOP_TIMER, idEvent,dwTime);
}




void CWindowsMessageHelper::addMessageHanler(UINT _messageId,WPFP_Process_Message _handler, void* _data, WPARAM _wParam)
{
	InnerData innerData = {_wParam, _handler, _data};
	if(_handler == NULL) return;
	std::vector<InnerData>& vec = m_handleMessage[_messageId];
	std::vector<InnerData>::iterator iter = vec.begin();
	std::vector<InnerData>::iterator iterEnd = vec.end();
	while(iter != iterEnd)
	{
	  if(iter->m_process == _handler)
	  {
		///替换.
		*iter = innerData;
		return;
	  }
	  iter++;
	}
	vec.push_back(innerData);
}
void CWindowsMessageHelper::removeMessageHandler(UINT _messageId, WPFP_Process_Message _handler)
{
	std::vector<InnerData>& vec = m_handleMessage[_messageId];
	std::vector<InnerData>::iterator iter = vec.begin();
	std::vector<InnerData>::iterator iterEnd = vec.end();
	while(iter != iterEnd)
	{
		if(iter->m_process == _handler)
		{
			vec.erase(iter);
			return;
		}
		iter++;
	}
}
UINT CWindowsMessageHelper::processMessage(UINT _messageId, MSG* _data)
{
	UINT ret = 0;
	
	std::vector<InnerData>& vec = m_handleMessage[_messageId];
	std::vector<InnerData>::iterator iter = vec.begin();
	std::vector<InnerData>::iterator iterEnd = vec.end();
	while(iter != iterEnd)
	{
		WPFP_Process_Message& call = iter->m_process;
		if(_data->wParam == iter->m_wParam || iter->m_wParam == 0)
		{
			ret = call(_messageId, _data,iter->m_pUserData);		
		}
		if(ret != 0 ) break;
		iter++;
	}
	return ret;
}


DWORD CALLBACK CWindowsMessageHelper::mainThread(PVOID pvoid)
{
	CWindowsMessageHelper* pThread = (CWindowsMessageHelper*)pvoid;
	MSG msg;
	SetEvent(pThread->m_event);
	
	//PeekMessage(&msg,NULL,WM_USER,WM_USER,PM_NOREMOVE);
	BOOL bRet;
	while ((bRet = GetMessage(&msg,NULL,0,0))!=0)
	{
		if (bRet == -1)
		{
			printf("Error:the thread will quit,error id is %d/n",GetLastError());
			break;
		}
		else
		{
			TranslateMessage(&msg);
			if(pThread->processMessage(msg.message,&msg) == 0)
			{
			  DispatchMessage(&msg);
			}
		}
	}
	printf("thread end here/n");
	return 0;
}

如果需要转帖,请注明原始链接: http://blog.csdn.net/wu4long/article/details/7324965 

 

Visual C++ 2010经典教程:MFC、C++/CLI与遗留系统维护实战指南 C++作为高性能系统开发的核心语言,其与操作系统底层的紧密交互能力是许多关键应用的基础。在Windows平台开发中,微软基础类库(MFC)通过封装Win32 API和消息映射机制,为构建桌面应用程序提供了系统化的框架方案,这一设计思想深刻影响了后续UI框架的演进。对于需要维护金融、工业控制等领域的遗留系统,或深入理解Windows桌面开发原理的工程师而言,掌握特定历史版本的技术栈具有重要工程价值。C++/CLI技术作为连接原生代码与.NET生态的桥梁,在混合编程场景中仍发挥着独特作用。本文围绕Visual 阅读详情

相关推荐

Visual C++实战开发:从环境搭建到项目构建的完整指南

C++作为高性能计算和系统级编程的核心语言,其编译链接机制是理解软件从源码到可执行文件的关键。在Windows平台,Visual C++工具链(包括编译器cl.exe、链接器link.exe)是实现这一过程的标准环境,它不仅支撑着底层系统开发,也是许多现代开发工具(如Node.js的node-gyp、Python的C扩展)的基础依赖。掌握Visual C++有助于解决常见的构建问题,例如“error MSB3428”这类因环境配置导致的编译失败,并理解Microsoft Visual C++ Redistr

weixin_33801856的博客 653

是时候全面了解一下window.console了!

目录一、常用函数1. console.assert(value, [...message])2. console.clear()3. console.count([label])4. console.countReset([label])5. console.debug(data, [...args])6. console.dir(obj)7. console.dirxml(...data)8. console.error(data, [...args])9. console.group([...label

夕山雨的博客 5187

C语言图形界面开发:使用ACLLib与Dev C++快速入门

图形用户界面(GUI)是提升软件交互体验的关键技术,其核心原理基于事件驱动模型,通过消息循环响应用户操作。在C语言开发中,实现GUI常面临学习曲线陡峭、配置复杂等挑战。ACLLib作为一款轻量级图形库,专为C语言教学和快速原型设计而生,它封装了底层Windows GDI绘图与消息处理机制,提供简洁的API接口,极大降低了图形编程门槛。结合Dev C++这一轻量级IDE,开发者无需复杂配置即可快速搭建开发环境,将命令行程序改造为图形化应用。本文以计算器项目为例,演示如何利用ACLLib的事件处理与绘图功能,实

aome1470的博客 352

WaitForSingleObject 和 setevent

最近涉及到开线程关管线程的问题,专门有一个帖子。学到不少,下面是帖子网址 http://topic.csdn.net/u/20090812/20/0379085f-7145-4bac-81bf-742114335d69.html 把学到的整理一下。       (摘)  WaitForSingleObject的用法   WaitFor

4115

C++编程中的消息机制

消息映射: BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()宏定义这个消息映射的边界。 BEGIN_MESSAGE_MAP()宏有两个参数,第一个参数为定义消息映射的当前类名,第二个参数提供一个到该基类的连接,以查找消息处理程序。如果在定义消息映射的

timebomb的专栏 9970

VC++游戏杆编程——使用消息响应方式

Windows使用VC++对游戏杆编程,不采用传统的轮询方式,使用自定义消息响应游戏杆事件。例程使用MFC对话框,joySetCapture()函数实现。

weixin_48341920的博客 774

C++中SetConsoleCtrlHandler 处理控制台消息

SetConsoleCtrlHandler 处理控制台消息 一、如何处理所有的控制台消息。    第一步,首先要安装一个事件钩子,也就是说要建立一个回调函数。调用Win32 API,原型如下: BOOL SetConsoleCtrlHandler( PHANDLER_ROUTINE HandlerRoutine, // 回调函数 BOOL Add // 表示添加还

menghuangxiao的专栏 3971

上位机定时器管理实战:单一定时器与任务调度机制详解

在上位机开发中,定时器是实现周期性数据采集、界面刷新、心跳上报与超时检测等基础功能的核心组件。然而,多Timer滥用常导致UI卡顿、逻辑混乱和不可维护等问题。本文从定时器类型与工作原理入手,对比System.Windows.Forms.Timer、System.Threading.Timer、System.Timers.Timer及Task.Delay的适用场景,剖析多任务定时管理中的典型陷阱。针对“多动症”程序结构,提出“单一定时器 + 任务调度表”的设计模式,通过统一调度循环、防重入标志、异常隔离及Be

weixin_34236869的博客 578

C++五子棋实战:从零构建Windows图形界面游戏

C++作为一门经典的面向对象编程语言,是学习计算机科学和软件开发的基石。其核心原理在于通过类、对象、继承和多态等机制组织代码,实现高内聚、低耦合的软件设计。掌握C++不仅能深入理解内存管理、数据结构和算法,更能为开发高性能桌面应用奠定基础。在工程实践中,Visual Studio作为强大的集成开发环境,为Windows平台下的C++开发提供了开箱即用的编译、调试和项目管理支持。结合Windows GDI图形设备接口,开发者可以高效实现图形界面的绘制与用户交互。本文以双人对战五子棋这一经典项目为具体应用场景,

weixin_33798152的博客 441

Windows.h入门指南:从API原理到窗口程序实战

应用程序编程接口(API)是操作系统为开发者提供的功能调用集合,它定义了软件与系统交互的标准方式。在Windows平台,Win32 API作为最底层的原生接口,其核心头文件Windows.h封装了系统调用的数据类型、函数和消息机制。理解这套API的原理,能帮助开发者构建高性能、深度集成的原生应用,尤其在桌面软件、系统工具和游戏开发领域价值显著。通过掌握窗口句柄、消息循环等核心机制,开发者可以深入事件驱动架构的本质,为使用高级框架打下坚实基础。本文以Windows.h为切入点,解析其数据结构与消息机制,并通过

weixin_33736832的博客 281

C++实战:Windows API打造高效鼠标连点器,从原理到防检测技巧

在自动化脚本和桌面应用开发领域,系统级输入模拟是一项基础且关键的技术。其核心原理是通过程序调用操作系统提供的底层API,模拟键盘或鼠标等硬件设备的输入事件,从而实现自动化操作。这项技术的工程价值在于能够提升重复性任务的效率,并作为学习系统编程的实践入口。常见的应用场景包括自动化测试、辅助工具开发以及合法的办公流程简化。本文聚焦于使用C++Windows API实现一个高性能的鼠标连点器,深入探讨了SendInput函数、多线程同步以及全局热键注册等核心机制。针对实际开发中可能遇到的稳定性问题,文章还分享了

weixin_33913332的博客 447

C++俄罗斯方块实战:基于Win32 API与GDI的完整游戏开发教程

游戏开发是计算机图形学与软件工程的重要实践领域,其核心在于将数据逻辑、用户交互与实时渲染有机结合。理解游戏循环、状态管理与碰撞检测等基础原理,是掌握实时交互系统设计的关键。这些技术不仅用于娱乐产品,在模拟训练、数据可视化等工业场景也有广泛应用。本文通过一个经典的俄罗斯方块项目,具体展示了如何运用C++面向对象思想,结合Windows API与GDI绘图技术,从零构建一个功能完整的图形应用程序。项目深入剖析了Win32消息机制、GDI双缓冲绘图等底层实现,并详细解释了方块旋转的“墙踢”机制与高效的碰撞检测算法

weixin_33842304的博客 436

ROS 2 日志调试神器:rqt_console 可视化分析实战指南

日志是 ROS 2 系统运行状态的核心反馈机制,本质是带时间戳、等级、节点名和元数据的结构化事件流,而非终端文本回显。其原理基于 rclcpp/rclpy 内置的日志后端异步发布机制,支持纳秒级时序追踪与跨进程捕获。技术价值在于突破命令行日志的时间断裂、信噪混杂与上下文缺失三大瓶颈,提供实时过滤、正则高亮、上下文展开及离线回放能力。典型应用场景包括节点通信异常定位、状态流转验证、多节点时序对齐及教学可视化。本文聚焦 rqt_console 这一关键 GUI 工具,结合 turtlesim 碰撞故障复现,详解

weixin_30512043的博客 321

C/C++图形编程入门:EasyX库环境搭建与核心功能详解

图形编程是计算机科学中可视化数据、构建交互界面的基础技术,其核心原理在于通过程序指令控制像素点阵形成图像。在C/C++生态中,EasyX图形库通过封装Windows GDI接口,将复杂的底层绘图操作简化为直观函数调用,极大降低了图形编程的入门门槛,为算法可视化、教学演示及简单游戏开发提供了高效工具。本文以环境配置与核心功能为切入点,详细解析了在Visual Studio中安装EasyX的步骤,并深入探讨了双缓冲动画、消息循环等关键技术,帮助开发者快速掌握图形窗口创建、基本图形绘制、图像处理及交互逻辑实现,为

weixin_34122604的博客 381

MFC应用集成CEF实现C++与JavaScript双向通信实战指南

在现代桌面应用开发中,混合架构正成为连接传统原生应用与前沿Web技术的关键桥梁。其核心原理在于通过嵌入式浏览器框架,在原生应用窗口中渲染Web内容,并建立进程间通信机制,实现不同技术栈间的无缝交互。这种架构的技术价值在于,既能保留原生应用的高性能与系统深度集成能力,又能充分利用Web技术生态的丰富性、开发效率与跨平台潜力。典型的应用场景包括为遗留桌面软件嵌入现代化Web界面、构建数据可视化看板,以及实现需要复杂交互的业务系统。本文聚焦于在经典的MFC框架中,通过集成Chromium Embedded Fra

weixin_33845881的博客 458

Visual C++游戏源码深度解析:从贪吃蛇到DirectX的底层开发实践

游戏开发的核心在于理解其底层运行机制,其中游戏循环(Game Loop)是实现实时交互的基础架构,它遵循输入、更新、渲染的经典模式,确保逻辑与显示的协同。在Windows平台,Visual C++工具链与运行时库构成了原生开发的重要基石,通过手动管理内存、优化CPU指令周期,开发者能深入掌控性能细节。这种底层控制能力在高性能需求的工业仿真、嵌入式图形界面等场景中尤为关键。本文以经典贪吃蛇项目为例,剖析其状态管理、数据结构选择(如deque)及从控制台到DirectX的渲染演进,并探讨如何通过高精度计时器实现

weixin_30596735的博客 336

Windows API 函数

Windows API函数手册》摘要 本文档是Windows平台开发的权威参考手册,全面收录774个核心API函数,涵盖系统管理、进程线程、窗口消息、文件操作、图形处理等12大功能模块。手册采用结构化编排,主要特点包括: 编码规范 详细区分多字节(char)与宽字符(wchar_t)编码体系 提供LPSTR/LPCWSTR等字符串指针类型的完整解析 说明UTF-8与GBK编码转换的实际应用场景 核心功能模块 窗口创建:完整展示从注册类到消息循环的窗口生命周期 文件操作:覆盖CreateFile/ReadF

gqk01的博客 842

从MFC到现代C++17:游戏服务器跨平台重构实战与架构演进

在现代软件开发中,服务器架构的演进是提升系统性能和可维护性的关键。从传统的单体架构到现代的异步事件驱动模型,技术栈的升级往往涉及核心设计理念的转变。以C++为例,从早期的MFC框架迁移到现代C++17标准,不仅是语法层面的更新,更是对内存安全、并发模型和跨平台能力的系统性重构。这种重构的技术价值在于能够显著提升服务器的并发处理能力、降低资源消耗,并实现Linux与Windows环境的无缝部署。在实际应用场景中,游戏服务器尤其需要高性能的网络通信和稳定的服务运行,因此采用Boost.Asio等异步I/O库结合

weixin_33889245的博客 476
上一篇: windows编译ruby1.9.3版本
下一篇: rails3 部署方案
wu4long
博客等级 码龄25年 13粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值