/
WinMessageWindow.cpp
149 lines (130 loc) · 4.24 KB
/
WinMessageWindow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/**********************************************************\
Original Author: Richard Bateman (taxilian)
Created: Jan 5, 2011
License: Dual license model; choose one of two:
New BSD License
http://www.opensource.org/licenses/bsd-license.php
- or -
GNU Lesser General Public License, version 2.1
http://www.gnu.org/licenses/lgpl-2.1.html
Copyright 2010 Richard Bateman, Firebreath development team
\**********************************************************/
#include "win_targetver.h"
#include "win_common.h"
#include <boost/lexical_cast.hpp>
#include <boost/bind.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include "AsyncFunctionCall.h"
#include "logging.h"
#include "../precompiled_headers.h" // On windows, everything above this line in PCH
#include <ShlGuid.h>
#include <string>
#include "WinMessageWindow.h"
// thanks http://blogs.msdn.com/b/oldnewthing/archive/2004/10/25/247180.aspx
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)
class WindowsClassRegistration
{
ATOM m_atom;
DWORD m_err;
const wchar_t* m_className;
public:
WindowsClassRegistration(const wchar_t* classname)
: m_err(0)
, m_className(classname)
{
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = &FB::WinMessageWindow::_WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = HINST_THISCOMPONENT;
wc.lpszMenuName = NULL;
wc.lpszClassName = m_className;
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hIconSm = NULL;
wc.hbrBackground = NULL;
m_atom = ::RegisterClassEx(&wc);
if (!m_atom) {
m_err = ::GetLastError();
}
}
~WindowsClassRegistration()
{
if (0 == m_err) {
UnregisterClass(MAKEINTATOM(m_atom), HINST_THISCOMPONENT);
}
}
ATOM atom() const
{
if (m_err) {
std::stringstream ss;
ss << "Could not register window class, error:" << m_err;
throw std::runtime_error(ss.str());
}
return m_atom;
}
};
static boost::recursive_mutex _windowMapMutex;
static std::map<HWND, FB::WinMessageWindow*> _windowMap;
static WindowsClassRegistration _winclass(L"FBEventWindow");
FB::WinMessageWindow::WinMessageWindow() {
DWORD err(0);
static int count(0);
std::wstring winName = L"FireBreathEventWindow" + boost::lexical_cast<std::wstring>(count);
++count;
HWND messageWin = CreateWindowEx(
WS_OVERLAPPED,
MAKEINTATOM(_winclass.atom()),
winName.c_str(),
0,
0, 0, 0, 0,
HWND_MESSAGE, NULL, HINST_THISCOMPONENT, NULL);
if (!messageWin) {
err = ::GetLastError();
throw std::runtime_error("Could not create Message Window");
}
_windowMap[messageWin] = this;
m_hWnd = messageWin;
boost::recursive_mutex::scoped_lock _l(_windowMapMutex);
winProc = boost::bind(&FB::WinMessageWindow::DefaultWinProc, this, _1, _2, _3, _4, _5);
}
LRESULT CALLBACK FB::WinMessageWindow::_WinProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT lres = S_OK;
FB::WinMessageWindow* self(NULL);
{
boost::recursive_mutex::scoped_lock _l(_windowMapMutex);
if (_windowMap.find(hWnd) != _windowMap.end())
self = _windowMap[hWnd];
}
if (!self || !self->winProc(hWnd, uMsg, wParam, lParam, lres)) {
return DefWindowProc(hWnd, uMsg, wParam, lParam);
} else {
return lres;
}
}
HWND FB::WinMessageWindow::getHWND()
{
return m_hWnd;
}
FB::WinMessageWindow::~WinMessageWindow()
{
boost::recursive_mutex::scoped_lock _l(_windowMapMutex);
_windowMap.erase(m_hWnd);
::DestroyWindow(m_hWnd);
}
bool FB::WinMessageWindow::DefaultWinProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lResult )
{
if (uMsg == WM_ASYNCTHREADINVOKE) {
FBLOG_TRACE("PluginWindow", "Running async function call");
FB::AsyncFunctionCall *evt = static_cast<FB::AsyncFunctionCall*>((void*)lParam);
evt->func(evt->userData);
delete evt;
lResult = S_OK;
return true;
}
return false;
}