| Index: src/engine/NotificationWindow.h |
| diff --git a/src/engine/NotificationWindow.h b/src/engine/NotificationWindow.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f9a9e8797d400c8d61ae70af22a89b6c397e1d76 |
| --- /dev/null |
| +++ b/src/engine/NotificationWindow.h |
| @@ -0,0 +1,234 @@ |
| +#pragma once |
| +#include <atlbase.h> |
| +#include <atlwin.h> |
| +#include <atlctl.h> |
| +#include <atlimage.h> |
| +#include <AdblockPlus/JsValue.h> |
| +#include <AdblockPlus/Notification.h> |
| +#include <functional> |
| +#include <MsHtmdid.h> |
| + |
| +class IconStaticControl : public ATL::CWindow |
| +{ |
| +public: |
| + explicit IconStaticControl(HWND hWnd = nullptr) : ATL::CWindow(hWnd) |
| + { } |
| + |
| + IconStaticControl& operator=(HWND hWnd) |
| + { |
| + m_hWnd = hWnd; |
| + return *this; |
| + } |
| + |
| + HWND Create(HWND hWndParent, ATL::_U_RECT rect = nullptr, LPCTSTR szWindowName = nullptr, |
| + DWORD dwStyle = 0, DWORD dwExStyle = 0, |
| + ATL::_U_MENUorID MenuOrID = nullptr, LPVOID lpCreateParam = nullptr) |
| + { |
| + return ATL::CWindow::Create(GetWndClassName(), hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, MenuOrID.m_hMenu, lpCreateParam); |
| + } |
| + |
| + static wchar_t* GetWndClassName() |
| + { |
| + return L"STATIC"; |
| + } |
| + |
| + void SetBitmap(HBITMAP hBitmap) |
| + { |
| + ATLASSERT(::IsWindow(m_hWnd)); |
| + ::SendMessage(m_hWnd, STM_SETIMAGE, IMAGE_BITMAP, reinterpret_cast<LPARAM>(hBitmap)); |
| + } |
| +}; |
| + |
| +template<typename T> |
| +class ScopedObjectHandle |
| +{ |
| +public: |
| + explicit ScopedObjectHandle(T handle = nullptr) : m_handle(handle) |
| + { } |
| + |
| + ~ScopedObjectHandle() |
| + { |
| + if(m_handle != nullptr) |
| + { |
| + ::DeleteObject(m_handle); |
| + m_handle = nullptr; |
| + } |
| + } |
| + |
| + ScopedObjectHandle& operator=(T handle) |
| + { |
| + if(m_handle != nullptr && m_handle != handle) |
| + ::DeleteObject(m_handle); |
| + m_handle = handle; |
| + return *this; |
| + } |
| + |
| + T Detach() |
| + { |
| + T retValue = m_handle; |
| + m_handle = nullptr; |
| + return retValue; |
| + } |
| + |
| + operator T() |
| + { |
| + return m_handle; |
| + } |
| + |
| + operator bool() const |
| + { |
| + return m_handle == nullptr; |
| + } |
| +protected: |
| + T m_handle; |
| +private: |
| + ScopedObjectHandle(const ScopedObjectHandle&); |
| + ScopedObjectHandle& operator=(const ScopedObjectHandle&); |
| +}; |
| + |
| +class CFont : public ScopedObjectHandle<HFONT> |
| +{ |
| +public: |
| + explicit CFont(HFONT hFont = nullptr) : ScopedObjectHandle(hFont) |
| + { |
| + } |
| + |
| + void CreateFontIndirect(const LOGFONT* logFontArg, uint32_t dpi) |
| + { |
| + ATLASSERT(m_handle == nullptr); |
| + LOGFONT logFont = *logFontArg; |
| + logFont.lfHeight = -MulDiv(dpi, logFont.lfHeight, 72); |
| + m_handle = ::CreateFontIndirect(&logFont); |
| + } |
| +}; |
| + |
| +class CBrush : public ScopedObjectHandle<HBRUSH> |
| +{ |
| +public: |
| + explicit CBrush(HBRUSH brush = nullptr) : ScopedObjectHandle(brush) |
| + { |
| + } |
| + |
| + void CreateSolidBrush(COLORREF crColor) |
| + { |
| + ATLASSERT(m_handle == nullptr); |
| + m_handle = ::CreateSolidBrush(crColor); |
| + } |
| +}; |
| + |
| +class ScopedModule |
| +{ |
| +public: |
| + ScopedModule() |
| + : m_hModule(nullptr) |
| + { |
| + } |
| + |
| + bool Open(const wchar_t* fileName, int flags) |
| + { |
| + m_hModule = LoadLibraryEx(fileName, nullptr, flags); |
| + return m_hModule != nullptr; |
| + } |
| + |
| + ~ScopedModule() |
| + { |
| + if (m_hModule != nullptr) |
| + { |
| + FreeLibrary(m_hModule); |
| + m_hModule = nullptr; |
| + } |
| + } |
| + operator HMODULE() |
| + { |
| + return m_hModule; |
| + } |
| +private: |
| + ScopedModule(const ScopedModule&); |
| + ScopedModule& operator=(const ScopedModule&); |
| +private: |
| + HMODULE m_hModule; |
| +}; |
| + |
| +typedef ATL::CWinTraits<WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_TOOLWINDOW | WS_EX_TOPMOST> NotificationWindowStyles; |
| +enum |
| +{ |
| + // ID of HTMLDocument ActiveX control, it's used for event binding. |
| + kHTMLDocumentCtrlID = 101 |
| +}; |
| + |
| +class NotificationWindow : public ATL::CWindowImpl<NotificationWindow, ATL::CWindow, NotificationWindowStyles> |
| + , ATL::IDispEventImpl<kHTMLDocumentCtrlID, NotificationWindow, &DIID_HTMLDocumentEvents2, &LIBID_MSHTML, 4, 0> |
| +{ |
| +public: |
| + explicit NotificationWindow(const AdblockPlus::Notification& notification, const std::wstring& htmlFileDir); |
| + ~NotificationWindow(); |
| + BEGIN_MSG_MAP(NotificationWindow) |
| + if (uMsg == WM_CREATE) |
| + { |
| + SetMsgHandled(TRUE); |
| + lResult = OnCreate(reinterpret_cast<CREATESTRUCT*>(lParam)); |
| + if(IsMsgHandled()) |
| + return TRUE; |
| + } |
| + MESSAGE_HANDLER(WM_LBUTTONUP, OnClick) |
| + MESSAGE_HANDLER(WM_RBUTTONUP, OnClick) |
| + MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnCtlColor) |
| + if (uMsg == WM_SIZE) |
| + { |
| + SetMsgHandled(TRUE); |
| + OnSize(static_cast<uint32_t>(wParam), CSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam))); |
| + lResult = 0; |
| + if(IsMsgHandled()) |
| + return TRUE; |
| + } |
| + if (uMsg == WM_DESTROY) |
| + { |
| + SetMsgHandled(TRUE); |
| + OnDestroy(); |
| + lResult = 0; |
| + if(IsMsgHandled()) |
| + return TRUE; |
| + } |
| + END_MSG_MAP() |
| + |
| + BEGIN_SINK_MAP(NotificationWindow) |
| + SINK_ENTRY_EX(kHTMLDocumentCtrlID, DIID_HTMLDocumentEvents2, DISPID_HTMLDOCUMENTEVENTS2_ONCLICK, OnHTMLDocumentClick) |
| + SINK_ENTRY_EX(kHTMLDocumentCtrlID, DIID_HTMLDocumentEvents2, DISPID_HTMLDOCUMENTEVENTS2_ONSELECTSTART, OnHTMLDocumentSelectStart) |
| + END_SINK_MAP() |
| + |
| + std::function<void()> destroyed; |
| + std::function<void(const std::wstring& url)> linkClicked; |
| +private: |
| + LRESULT OnCreate(const CREATESTRUCT* createStruct); |
| + LRESULT OnCtlColor(UINT msg, WPARAM wParam, LPARAM lParam, BOOL& handled); |
| + LRESULT OnClick(UINT msg, WPARAM wParam, LPARAM lParam, BOOL& handled); |
| + void OnGetMinMaxInfo(MINMAXINFO* minMaxInfo); |
| + void OnSize(uint32_t wParam, CSize size); |
| + void OnDestroy(); |
| + |
| + void __stdcall OnHTMLDocumentClick(IHTMLEventObj* pEvtObj); |
| + void __stdcall OnHTMLDocumentSelectStart(IHTMLEventObj* pEvtObj); |
| + |
| + void OnFinalMessage(HWND) override; |
| + void LoadABPIcon(); |
| + // returns {windowX, windowY} of top left corner on the monitor |
| + POINT GetWindowCoordinates(); |
| + |
| + uint32_t DPIAware(uint32_t value) const { |
| + return MulDiv(value, m_dpi, 96); |
| + } |
| + SIZE DPIAware(SIZE value) const { |
| + return CSize(DPIAware(value.cx), DPIAware(value.cy)); |
| + } |
| + RECT DPIAware(RECT value) const { |
| + return CRect(DPIAware(value.left), DPIAware(value.top), DPIAware(value.right), DPIAware(value.bottom)); |
| + } |
| +private: |
| + uint32_t m_dpi; |
| + std::wstring m_htmlPage; |
| + CBrush m_bgColor; |
| + ATL::CAxWindow m_axIE; |
| + ATL::CImage m_iconImg; |
| + IconStaticControl m_icon; |
| + std::vector<std::wstring> m_links; |
| +}; |