提问人:Nitron_707 提问时间:7/9/2023 最后编辑:Eric PostpischilNitron_707 更新时间:7/9/2023 访问量:110
在交互式 GUI 代码中使用回调函数
Use of callback functions in interactive GUI code
问:
我正在开发一个 GUI 系统并使用 https://github.com/stevenlovegrove/Pangolin,我使用回调函数来注册按键事件。
例如。
// register the function using the funcPtr
pangolin::RegisterKeyPressCallback(' ', funcPtr);
while(!pangolin::ShouldQuit()){
// ...some code...
// Run till window is closed
// ...some code...
}
这里基于穿山甲代码,它实现并使用了一个全局,它存储了函数指针,定义为RegisterKeyPressCallback
context
__thread PangolinGl* context = 0;
问题和场景 - 我们在回调函数中注册我们的 functionPtr,while 循环开始。
在我按的中间。
我想知道是否有后台线程始终在运行并侦听运行 while 循环的线程,以便当我按下暂停键时,它会检测到按键。RegisterKeyPressCallback
while loop
pause
一般来说,我想知道,在像上面这样的实时交互式用例中,我们传入一个指向回调函数的函数指针一次,并且是否有并行运行的后台线程,以便它可以检测事件。
答:
不,键盘输入没有单独的线程检查。相反,每个操作系统都有自己的处理窗口和键盘事件的实现。特别是在 Windows 上,代码必须注册一个窗口类,该类指示用于处理窗口消息事件的回调字段。查看 Windows 消息循环,其中窗口的每次迭代循环都会调用 GetMessage/PeekMessage 和 DispatchMessage 以进行事件处理。
在 Pangolin/components/pango_window/src/display_win.cpp 中,类和键盘回调函数在你之前注册,库的用户可以看到实际的窗口。
void WinWindow::RegisterThisClass(HMODULE hCurrentInst)
{
WNDCLASSA wndClass;
wndClass.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WinWindow::WndProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = hCurrentInst;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = className;
if(!RegisterClassA(&wndClass)) {
std::cerr << "RegisterClass() failed" << std::endl;
CheckWGLDieOnError();
}
}
函数 ProcessEvents 是实际消息循环发生的位置。
void WinWindow::ProcessEvents()
{
static bool needs_init = true;
if(needs_init) {
RECT cRect;
GetClientRect(hWnd, &cRect);
ResizeSignal(WindowResizeEvent({cRect.right, cRect.bottom}));
needs_init = false;
}
MSG msg;
while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT) {
CloseSignal();
break;
}
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
}
具体来说,这是处理Windows消息的内容。WndProc 刚刚返回wndClass.lpfnWndProc = WinWindow::WndProc;
LRESULT WinWindow::HandleWinMessages(UINT message, WPARAM wParam, LPARAM lParam)
WinWindow::HandleWinMessages
然后检查窗口是否处理了键盘消息。如果是这样,库将执行检查以查看按下了哪个键,以及用户是否为该特定键注册了函数回调。并执行回调。
case WM_KEYDOWN:
case WM_KEYUP:
{
unsigned char key = GetPangoKey(wParam, lParam);
if(key > 0) {
KeyboardSignal(KeyboardEvent({
afLastMousePos[0], afLastMousePos[1],
KeyModifierBitmask(),
(unsigned char)key, message == WM_KEYDOWN
}));
}
return 0;
}
keyboardSignal(KeyboardEvent({
是完成实际按键操作的地方。
请记住,我给出的概述是特定于 Windows 的。OSX、Unix、GNU都有自己的实现,我想穿山甲会逐案处理。
评论