将数据传递给 Windows 控制台控制处理程序
Posted
技术标签:
【中文标题】将数据传递给 Windows 控制台控制处理程序【英文标题】:Passing Data to Windows Console Control Handler 【发布时间】:2012-01-31 15:07:03 【问题描述】:我正在编写一个简单的游戏引擎,但在处理 Windows 控制台事件时遇到了问题;具体来说,我不知道如何将自定义数据传递给回调处理程序。
我首先调用这段代码来指定我的回调函数:
SetConsoleCtrlHandler((PHANDLER_ROUTINE)WindowsSystemManager::ConsoleControlHandler, true);
我的静态成员回调函数定义为:
bool WINAPI WindowsSystemManager::ConsoleControlHandler(DWORD controlType)
if(controlType == CTRL_CLOSE_EVENT)
MessageBox(NULL, L"Close Event Captured", L"Close Event Captured", NULL);
return true;
一切正常 - 当我单击控制台中的关闭按钮时,会弹出此 MessageBox。唯一的问题是,我需要在此类关闭(以及其他清理)时调用将日志缓冲区刷新到日志文件的代码,并且 Logger 实例是我的 WindowsSystemManager 中的成员。
我已经成功地使用 SetWindowLongPtr 和 GetWindowLongPtr 处理了将自定义数据传递给窗口句柄的类似问题,但我找不到任何有关如何使用控制台控制处理程序执行此类操作的信息。有什么想法吗?
编辑:我根据 MSalters 的建议得到了这个功能。控制台控制处理程序的最终代码在这里:
bool WINAPI WindowsSystemManager::ConsoleControlHandler(DWORD controlType)
BerserkEngine* engine = (BerserkEngine*)GetWindowLongPtr(GetConsoleWindow(), GWLP_USERDATA);
if(controlType == CTRL_CLOSE_EVENT)
engine->~BerserkEngine();
PostQuitMessage(0);
return true;
我在 WindowsSystemManager 构造函数中设置此自定义数据指针的位置:
SetWindowLongPtr(GetConsoleWindow(), GWL_USERDATA, (LONG_PTR)this->engine);
【问题讨论】:
您是否使用此功能从程序中的任何位置捕获 CTRL_CLOSE_EVENT ?请参考我现在关注的问题***.com/questions/40464545/… 【参考方案1】:我不确定你为什么需要这个。您可以有多个窗口,但只能有一个控制台。
但是,GetConsoleWindow
将为您提供控制台HWND
,您可以在该控制台上调用SetWindowLongPtr
。不是很干净(你不应该在你不管理的窗口上这样做),但它可能只是工作。
【讨论】:
也许我不够清楚 - 只有一个控制台,只有一个窗口。我需要做的就是从我的控制台控制处理程序中访问 Logger 实例。您概述的方法应该有效,因为我不知道您可以检索控制台窗口的句柄。但是你说我不应该在我不管理的窗口上这样做是什么意思? 由于只有一个控制台,您可能只有一个 Logger。改为使其成为单例,然后您不必通过它。至于SetWindowLongPtr
,你只有sizeof(LONG_PTR)
字节可用于GWLP_USERDATA
,这些字节是为窗口类创建者(即CSRSS)保留的。
嗯,我会考虑让它成为一个单例,这样会更有意义。但是,到目前为止,一切正常 - 不过我会研究 CSRSS!谢谢
"你可能会调用 SetWindowLongPtr" >> 恐怕这不是真的。您不能在控制台 HWND 上调用 SetWindowLongPtr
。原因是窗口过程驻留在另一个进程中(Vista及之前的CRSS,Win7/Win2k8SP2及更高版本的conhost.exe)
@Abel: SetWindowLongPtr
不使用窗口过程。它会影响窗口内存。文档指出,可以为另一个进程的窗口调用它,只要它处于相同的 UIPI 级别。以上是关于将数据传递给 Windows 控制台控制处理程序的主要内容,如果未能解决你的问题,请参考以下文章