OLD | NEW |
(Empty) | |
| 1 #pragma once |
| 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 |