Left: | ||
Right: |
OLD | NEW |
---|---|
(Empty) | |
1 #pragma once | |
Oleksandr
2015/08/10 09:13:34
Nit: We try to use GNU style guards in the new cod
sergei
2015/08/17 13:12:53
Done.
| |
2 #include <atlbase.h> | |
3 #include <atlwin.h> | |
4 #include <atlctl.h> | |
5 #include <atlimage.h> | |
6 #include <AdblockPlus/JsValue.h> | |
7 #include <AdblockPlus/Notification.h> | |
8 #include <functional> | |
9 #include <MsHtmdid.h> | |
10 | |
11 class IconStaticControl : public ATL::CWindow | |
12 { | |
13 public: | |
14 explicit IconStaticControl(HWND hWnd = nullptr) : ATL::CWindow(hWnd) | |
15 { } | |
16 | |
17 IconStaticControl& operator=(HWND hWnd) | |
18 { | |
19 m_hWnd = hWnd; | |
20 return *this; | |
21 } | |
22 | |
23 HWND Create(HWND hWndParent, ATL::_U_RECT rect = nullptr, LPCTSTR szWindowName = nullptr, | |
24 DWORD dwStyle = 0, DWORD dwExStyle = 0, | |
25 ATL::_U_MENUorID MenuOrID = nullptr, LPVOID lpCreateParam = nullptr) | |
26 { | |
27 return ATL::CWindow::Create(GetWndClassName(), hWndParent, rect.m_lpRect, sz WindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); | |
28 } | |
29 | |
30 static wchar_t* GetWndClassName() | |
31 { | |
32 return L"STATIC"; | |
33 } | |
34 | |
35 void SetBitmap(HBITMAP hBitmap) | |
36 { | |
37 ATLASSERT(::IsWindow(m_hWnd)); | |
38 ::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_BITMAP, reinterpret_cast<LPARAM>(h Bitmap)); | |
39 } | |
40 }; | |
41 | |
42 template<typename T> | |
43 class ScopedObjectHandle | |
44 { | |
45 public: | |
46 explicit ScopedObjectHandle(T handle = nullptr) : m_handle(handle) | |
47 { } | |
48 | |
49 ~ScopedObjectHandle() | |
50 { | |
51 if(m_handle != nullptr) | |
52 { | |
53 ::DeleteObject(m_handle); | |
54 m_handle = nullptr; | |
55 } | |
56 } | |
57 | |
58 ScopedObjectHandle& operator=(T handle) | |
59 { | |
60 if(m_handle != nullptr && m_handle != handle) | |
61 ::DeleteObject(m_handle); | |
62 m_handle = handle; | |
63 return *this; | |
64 } | |
65 | |
66 T Detach() | |
67 { | |
68 T retValue = m_handle; | |
69 m_handle = nullptr; | |
70 return retValue; | |
71 } | |
72 | |
73 operator T() | |
74 { | |
75 return m_handle; | |
76 } | |
77 | |
78 operator bool() const | |
79 { | |
80 return m_handle == nullptr; | |
81 } | |
82 protected: | |
83 T m_handle; | |
84 private: | |
85 ScopedObjectHandle(const ScopedObjectHandle&); | |
86 ScopedObjectHandle& operator=(const ScopedObjectHandle&); | |
87 }; | |
88 | |
89 class CBrush : public ScopedObjectHandle<HBRUSH> | |
90 { | |
91 public: | |
92 explicit CBrush(HBRUSH brush = nullptr) : ScopedObjectHandle(brush) | |
93 { | |
94 } | |
95 | |
96 void CreateSolidBrush(COLORREF crColor) | |
97 { | |
98 ATLASSERT(m_handle == nullptr); | |
99 m_handle = ::CreateSolidBrush(crColor); | |
100 } | |
101 }; | |
102 | |
103 class ScopedModule | |
104 { | |
105 public: | |
106 ScopedModule() | |
107 : m_hModule(nullptr) | |
108 { | |
109 } | |
110 | |
111 bool Open(const wchar_t* fileName, int flags) | |
112 { | |
113 m_hModule = LoadLibraryEx(fileName, nullptr, flags); | |
114 return m_hModule != nullptr; | |
115 } | |
116 | |
117 ~ScopedModule() | |
118 { | |
119 if (m_hModule != nullptr) | |
120 { | |
121 FreeLibrary(m_hModule); | |
122 m_hModule = nullptr; | |
123 } | |
124 } | |
125 operator HMODULE() | |
126 { | |
127 return m_hModule; | |
128 } | |
129 private: | |
130 ScopedModule(const ScopedModule&); | |
131 ScopedModule& operator=(const ScopedModule&); | |
132 private: | |
133 HMODULE m_hModule; | |
134 }; | |
135 | |
136 class DpiAwareness { | |
137 public: | |
138 DpiAwareness() : m_dpi(96) | |
139 { | |
140 } | |
141 protected: | |
142 uint32_t DPIAware(uint32_t value) const { | |
143 return MulDiv(value, m_dpi, 96); | |
144 } | |
145 SIZE DPIAware(SIZE value) const { | |
146 return CSize(DPIAware(value.cx), DPIAware(value.cy)); | |
147 } | |
148 RECT DPIAware(RECT value) const { | |
149 return CRect(DPIAware(value.left), DPIAware(value.top), DPIAware(value.right ), DPIAware(value.bottom)); | |
150 } | |
151 uint32_t m_dpi; | |
152 }; | |
153 | |
154 enum | |
155 { | |
156 // ID of HTMLDocument ActiveX control, it's used for event binding. | |
157 kHTMLDocumentCtrlID = 101 | |
158 }; | |
159 | |
160 class NotificationWindow : public ATL::CWindowImpl<NotificationWindow> | |
161 , ATL::IDispEventImpl<kHTMLDocumentCtrlID, NotificationWindow, &DIID_HTMLDocum entEvents2, &LIBID_MSHTML, 4, 0> | |
162 , protected DpiAwareness | |
163 { | |
164 public: | |
165 explicit NotificationWindow(const AdblockPlus::Notification& notification, con st std::wstring& htmlFileDir); | |
166 ~NotificationWindow(); | |
167 BEGIN_MSG_MAP(NotificationWindow) | |
168 if (uMsg == WM_CREATE) | |
169 { | |
170 SetMsgHandled(TRUE); | |
171 lResult = OnCreate(reinterpret_cast<CREATESTRUCT*>(lParam)); | |
172 if(IsMsgHandled()) | |
173 return TRUE; | |
174 } | |
175 MESSAGE_HANDLER(WM_LBUTTONUP, OnClick) | |
176 MESSAGE_HANDLER(WM_RBUTTONUP, OnClick) | |
177 MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnCtlColor) | |
178 if (uMsg == WM_SIZE) | |
179 { | |
180 SetMsgHandled(TRUE); | |
181 OnSize(static_cast<uint32_t>(wParam), CSize(GET_X_LPARAM(lParam), GET_Y_LP ARAM(lParam))); | |
182 lResult = 0; | |
183 if(IsMsgHandled()) | |
184 return TRUE; | |
185 } | |
186 if (uMsg == WM_DESTROY) | |
187 { | |
188 SetMsgHandled(TRUE); | |
189 OnDestroy(); | |
190 lResult = 0; | |
191 if(IsMsgHandled()) | |
192 return TRUE; | |
193 } | |
194 END_MSG_MAP() | |
195 | |
196 BEGIN_SINK_MAP(NotificationWindow) | |
197 SINK_ENTRY_EX(kHTMLDocumentCtrlID, DIID_HTMLDocumentEvents2, DISPID_HTMLDOCU MENTEVENTS2_ONCLICK, OnHTMLDocumentClick) | |
198 SINK_ENTRY_EX(kHTMLDocumentCtrlID, DIID_HTMLDocumentEvents2, DISPID_HTMLDOCU MENTEVENTS2_ONSELECTSTART, OnHTMLDocumentSelectStart) | |
199 END_SINK_MAP() | |
200 | |
201 void SetOnClick(const std::function<void()>& callback) | |
202 { | |
203 m_onClickCallback = callback; | |
204 } | |
205 void SetOnLinkClicked(const std::function<void(const std::wstring& url)>& call back) | |
206 { | |
207 m_onLinkClickedCallback = callback; | |
208 } | |
209 void SetOnClose(const std::function<void()>& callback) | |
210 { | |
211 m_onCloseCallback = callback; | |
212 } | |
213 private: | |
214 LRESULT OnCreate(const CREATESTRUCT* createStruct); | |
215 LRESULT OnCtlColor(UINT msg, WPARAM wParam, LPARAM lParam, BOOL& handled); | |
216 LRESULT OnClick(UINT msg, WPARAM wParam, LPARAM lParam, BOOL& handled); | |
217 void OnSize(uint32_t wParam, CSize size); | |
218 void OnDestroy(); | |
219 | |
220 void __stdcall OnHTMLDocumentClick(IHTMLEventObj* pEvtObj); | |
221 void __stdcall OnHTMLDocumentSelectStart(IHTMLEventObj* pEvtObj); | |
222 | |
223 void LoadABPIcon(); | |
224 private: | |
225 std::wstring m_htmlPage; | |
226 CBrush m_bgColor; | |
227 ATL::CAxWindow m_axIE; | |
228 ATL::CImage m_iconImg; | |
229 IconStaticControl m_icon; | |
230 std::vector<std::wstring> m_links; | |
231 std::function<void()> m_onClickCallback; | |
232 std::function<void()> m_onCloseCallback; | |
233 std::function<void(const std::wstring& url)> m_onLinkClickedCallback; | |
234 }; | |
235 | |
236 typedef ATL::CWinTraits<WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_TOOL WINDOW | WS_EX_TOPMOST> NotificationBorderWindowStyles; | |
237 class NotificationBorderWindow : public ATL::CWindowImpl<NotificationBorderWindo w, ATL::CWindow, NotificationBorderWindowStyles> | |
238 , protected DpiAwareness | |
239 { | |
240 public: | |
241 DECLARE_WND_CLASS_EX(/*generate class name*/nullptr, CS_DROPSHADOW, WHITE_BRUS H); | |
242 NotificationBorderWindow(const AdblockPlus::Notification& notification, const std::wstring& htmlFileDir); | |
243 BEGIN_MSG_MAP(NotificationWindow) | |
244 if (uMsg == WM_CREATE) | |
245 { | |
246 SetMsgHandled(TRUE); | |
247 lResult = OnCreate(reinterpret_cast<CREATESTRUCT*>(lParam)); | |
248 if(IsMsgHandled()) | |
249 return TRUE; | |
250 } | |
251 MESSAGE_HANDLER(WM_LBUTTONUP, OnClick) | |
252 MESSAGE_HANDLER(WM_RBUTTONUP, OnClick) | |
253 if (uMsg == WM_SIZE) | |
254 { | |
255 SetMsgHandled(TRUE); | |
256 OnSize(static_cast<uint32_t>(wParam), CSize(GET_X_LPARAM(lParam), GET_Y_LP ARAM(lParam))); | |
257 lResult = 0; | |
258 if(IsMsgHandled()) | |
259 return TRUE; | |
260 } | |
261 END_MSG_MAP() | |
262 void SetOnDestroyed(const std::function<void()>& callback) | |
263 { | |
264 m_onDestroyedCallback = callback; | |
265 } | |
266 void SetOnLinkClicked(const std::function<void(const std::wstring& url)>& call back) | |
267 { | |
268 m_content.SetOnLinkClicked(callback); | |
269 } | |
270 private: | |
271 LRESULT OnCreate(const CREATESTRUCT* createStruct); | |
272 void OnSize(uint32_t wParam, CSize size); | |
273 LRESULT OnClick(UINT msg, WPARAM wParam, LPARAM lParam, BOOL& handled); | |
274 | |
275 void OnFinalMessage(HWND) override; | |
276 | |
277 // returns {windowX, windowY} of top left corner on the monitor | |
278 POINT GetWindowCoordinates(); | |
279 private: | |
280 // m_content is used as a holder of all children and we need it to have a bord er. | |
281 // It seems the most correct way to have a border to set WS_POPUPWINDOW style | |
282 // and paint the border in WM_NCPAINT but it simply does not work here. | |
283 NotificationWindow m_content; | |
284 std::function<void()> m_onDestroyedCallback; | |
285 }; | |
OLD | NEW |