[英]PollEvent() in Win32
I'm trying to mimic SFML's PollEvent(Event &event)
function in Windows. 我正在尝试模仿Windows中SFML的
PollEvent(Event &event)
函数。 It seems far more complicated that I imagined. 似乎比我想象的要复杂得多。 Note that I already encapsulated the window procedure function in my class.
请注意,我已经将窗口过程函数封装在类中。
There could be many "window events" in my program - WindowMoved
, WindowResized
etc. 我的程序中可能有很多“窗口事件”
WindowMoved
, WindowResized
等。
My first attempt was to have a private data member in the class, defined as WindowEvent *_lastWindowEvent
. 我的第一次尝试是在类中有一个私有数据成员,定义为
WindowEvent *_lastWindowEvent
。 This variable will be set if PeekMessage()
returns a non-zero value, just before DispatchMessage()
is called. 如果在调用
DispatchMessage()
之前PeekMessage()
返回非零值,则将设置此变量。 Then, winProc()
will edit _lastWindowEvent
, depending on the message it will receive. 然后,
winProc()
将根据收到的消息编辑_lastWindowEvent
。 The drawback here is that I noticed that winProc()
may be called with a MSG parameter regardless of DispatchMessage()
, like with the WM_SETCURSOR
message. 此处的缺点是,我注意到无论与
DispatchMessage()
一样,均可使用MSG参数调用winProc()
DispatchMessage()
,就像WM_SETCURSOR
消息一样。
Then I thought about having instead a std::queue<WindowEvent>
in my class, when winProc()
continuously pushes WindowEvent
s to it. 然后,我想到了当
winProc()
不断将WindowEvent
推入类时,在我的类中添加了std::queue<WindowEvent>
。 The problem here is that sometimes the window procedure function keeps getting messages and won't return. 这里的问题是,有时窗口过程函数会不断获取消息,并且不会返回。 This happens when I drag-move the window (then the
WM_MOVING
message is continuously called, along with other messages). 当我拖动窗口时会发生这种情况(然后连续调用
WM_MOVING
消息以及其他消息)。 The code after DispatchMessage()
will not run until I release my mouse. 在释放鼠标之前,
DispatchMessage()
之后的代码将无法运行。 This also happens when resizing the window. 调整窗口大小时也会发生这种情况。
Did I grasp anything wrong? 我有什么错吗? How do you think such PollEvent function can be implemented?
您如何看待这样的PollEvent函数?
Given that PollEvent is primarily for a game loop style design, you can probably poll for what you need while simultaneously servicing the Windows event loop: 鉴于PollEvent主要用于游戏循环样式设计,因此您可以在服务Windows事件循环的同时轮询所需内容:
class Window
{
HWND _hwnd; // Win32 handle to the window
RECT _lastWindowSize; // last known window size
POINT _lastMousePos; // last known mouse position on window
BYTE _lastKeyboardState[256]; // last known key state
std::list<Event> _events; // unprocessed events
public:
bool PollEvent(Event* pEvent);
};
bool Window::PollEvent(Event* pEvent)
{
// return any previously queued events
if (_events.size() > 0)
{
*pEvent = _events.pop_front();
return true;
}
// process 1 windows event message
if (PeekMessage(&msg, _hWnd, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.msg == WM_QUIT)
{
*pEvent = EXIT_EVENT; // special handling for WM_QUIT
return true;
}
}
// -----------------------------------------
// poll keyboard state
BYTE kbState[256];
GetKeyboardState(kbState);
bool isKeyboardEvent = false;
if (memcmp(_lastKeyboardState, kbState, 256) != 0)
{
// not shown
// compute diff of kbState and _lastKeyboardState
// generate a keyboard event and add to the queue
Event kbevt;
kbevt.type = KeyEvent;
kbevt.code = <computed code based on diff above>
_events.push_back(kbevt);
}
memcpy(_lastKeyboardState, kbState, 256);
// -----------------------------------------
// -----------------------------------------
// poll window size changes
RECT rectWindowSize;
int width, height, oldwidth, oldheight;
GetClientRect(&rectWindowSize);
width = rectWindowSize.right - rectWindowSize.left;
height = rectWindowSize.bottom - rectWindowSize.top;
oldwidth = _lastWindowSize.right - _lastWindowSize.left;
oldheight = _lastWindowSize.bottom - _lastWindowSize.top;
if ((width != oldwidth) || (height != oldheight))
{
Event sizeEvent;
sizeEvent.type = SizeEvent;
sizeEvent.width = width;
sizeEvent.height = height;
_events.push_back(kbevt);
}
_lastWindowSize = rectWindowSize;
// -----------------------------------------
// not shown - computing mouse position, joystick position, text stuff
// if at least one event was queued - return it now
if (_events.size() > 0)
{
*pEvent = _events.pop_front();
return true;
}
return false;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.