Hi
I have a class named "Window" that has a private vector of messages called m_windowMessages.
This class has a public method named "moveMessages" and I want it to return the private vector of messages using move semantics without messing up the private vector so that I can continue to push new messages on it after "moveMessages" returns.
But I don't know what solution to use, I find some of them buggy, I think m_windowMessages get mangled and it has to renew its internals. Could the std::tuple ble the problem, should i just use a struct?
class Window
{
public:
Window();
~Window();
bool initialize(HINSTANCE hInstance);
std::vector<std::tuple<HWND, UINT, WPARAM, LPARAM>> moveMessages();
bool postMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
private:
bool filterMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
HWND m_hWnd = nullptr;
HINSTANCE m_hInstance = nullptr;
WNDCLASSEX m_wc;
std::vector<std::tuple<HWND, UINT, WPARAM, LPARAM>> m_windowMessages;
};
Window::Window()
{
ZeroMemory(&m_wc, sizeof(WNDCLASSEX));
m_wc.lpfnWndProc = (WNDPROC)[](HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)->LRESULT // non-capture lambda
{
Window* p_Window = nullptr;
if (message == WM_NCCREATE)
{
p_Window = reinterpret_cast<Window*>(((LPCREATESTRUCT)lParam)->lpCreateParams);
if (p_Window == nullptr)
throw;
SetLastError(0);
if (SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(p_Window)) == 0 && GetLastError() != 0)
throw;
}
if ((p_Window = reinterpret_cast<Window*>(GetWindowLongPtr(hWnd, GWL_USERDATA))) == nullptr)
return DefWindowProc(hWnd, message, wParam, lParam);
if (p_Window->postMessage(hWnd, message, wParam, lParam))
return 0;
return DefWindowProc(hWnd, message, wParam, lParam);
};
}
std::vector<std::tuple<HWND, UINT, WPARAM, LPARAM>> Window::moveMessages()
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// What to do??
return std::move(m_windowMessages); // Mangles m_windowMessages causing application to be laggy
std::vector<std::tuple<HWND, UINT, WPARAM, LPARAM>> windowMessages;
std::swap(windowMessages, m_windowMessages);
return windowMessages; // Kinda laggy
return std::move(windowMessages); // App also stutters here
}
bool Window::postMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (filterMessage(hWnd, message, wParam, lParam))
{
m_windowMessages.push_back(std::make_tuple(hWnd, message, wParam, lParam));
return true;
}
return false;
}
bool Window::filterMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (hWnd != m_hWnd) return false;
// return true for messages I want keep on m_windowMessages for the caller of moveMessages() to handle later on
switch (message)
{
case WM_MOUSEMOVE: return true;
case WM_LBUTTONDOWN: return true;
case WM_LBUTTONUP: return true;
case WM_CHAR: return true;
case WM_SYSKEYUP: return true;
case WM_SYSKEYDOWN: return true;
case WM_DESTROY: return true;
case WM_SYSCOMMAND:
switch (wParam)
{
case SC_KEYMENU: return true; // Disable system menu (F10 Key)
case SC_MONITORPOWER: return true; // Disable power saving monitor shutdown
}
break;
}
return false;
}
Window MyWindow;
MyWindow.initialize(hInstance);
while(true)
{
auto newMessages = MyWindow.moveMessages();
/.../
// processing newMessages
/.../
}