Merge feature/html -> master
This commit is contained in:
commit
2c477fb6ca
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -14,3 +14,6 @@
|
||||
path = deps/HDiffPatch
|
||||
url = https://github.com/sisong/HDiffPatch.git
|
||||
branch = master
|
||||
[submodule "deps/GSL"]
|
||||
path = deps/GSL
|
||||
url = https://github.com/Microsoft/GSL.git
|
||||
|
1
deps/GSL
vendored
Submodule
1
deps/GSL
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 0f68d133fa6fd2973951b8aaab481e34bbfd2cf4
|
19
deps/premake/gsl.lua
vendored
Normal file
19
deps/premake/gsl.lua
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
gsl = {
|
||||
source = path.join(dependencies.basePath, "GSL"),
|
||||
}
|
||||
|
||||
function gsl.import()
|
||||
gsl.includes()
|
||||
end
|
||||
|
||||
function gsl.includes()
|
||||
includedirs {
|
||||
path.join(gsl.source, "include")
|
||||
}
|
||||
end
|
||||
|
||||
function gsl.project()
|
||||
|
||||
end
|
||||
|
||||
table.insert(dependencies, gsl)
|
115
src/launcher/html/doc_host_ui_handler.cpp
Normal file
115
src/launcher/html/doc_host_ui_handler.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../html_frame.hpp"
|
||||
|
||||
doc_host_ui_handler::doc_host_ui_handler(html_frame* frame): frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::QueryInterface(REFIID riid, LPVOID* ppvObj)
|
||||
{
|
||||
auto client_site = this->frame_->get_client_site();
|
||||
if (client_site)
|
||||
{
|
||||
return client_site->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG doc_host_ui_handler::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG doc_host_ui_handler::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::ShowContextMenu(DWORD /*dwID*/, POINT* /*ppt*/, IUnknown* /*pcmdtReserved*/,
|
||||
IDispatch* /*pdispReserved*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::ShowUI(DWORD /*dwID*/, IOleInPlaceActiveObject* /*pActiveObject*/,
|
||||
IOleCommandTarget* /*pCommandTarget*/,
|
||||
IOleInPlaceFrame* /*pFrame*/, IOleInPlaceUIWindow* /*pDoc*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::HideUI()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::UpdateUI()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::EnableModeless(BOOL /*fEnable*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::OnDocWindowActivate(BOOL /*fActivate*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::OnFrameWindowActivate(BOOL /*fActivate*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::ResizeBorder(LPCRECT /*prcBorder*/, IOleInPlaceUIWindow* /*pUIWindow*/,
|
||||
BOOL /*fRameWindow*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::TranslateAcceleratorA(LPMSG /*lpMsg*/, const GUID* pguidCmdGroup, DWORD /*nCmdID*/)
|
||||
{
|
||||
pguidCmdGroup = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::GetOptionKeyPath(LPOLESTR* /*pchKey*/, DWORD /*dw*/)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::GetDropTarget(IDropTarget* /*pDropTarget*/, IDropTarget** /*ppDropTarget*/)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::GetExternal(IDispatch** ppDispatch)
|
||||
{
|
||||
*ppDispatch = this->frame_->get_html_dispatch();
|
||||
return (*ppDispatch) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::FilterDataObject(IDataObject* /*pDO*/, IDataObject** ppDORet)
|
||||
{
|
||||
*ppDORet = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE doc_host_ui_handler::TranslateUrl(DWORD /*dwTranslate*/, OLECHAR __RPC_FAR* /*pchURLIn*/,
|
||||
OLECHAR __RPC_FAR* __RPC_FAR* ppchURLOut)
|
||||
{
|
||||
*ppchURLOut = nullptr;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT doc_host_ui_handler::GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo)
|
||||
{
|
||||
pInfo->cbSize = sizeof(DOCHOSTUIINFO);
|
||||
pInfo->dwFlags = DOCHOSTUIFLAG_NO3DBORDER | DOCHOSTUIFLAG_DPI_AWARE | DOCHOSTUIFLAG_SCROLL_NO;
|
||||
pInfo->dwDoubleClick = DOCHOSTUIDBLCLK_DEFAULT;
|
||||
|
||||
return S_OK;
|
||||
}
|
47
src/launcher/html/doc_host_ui_handler.hpp
Normal file
47
src/launcher/html/doc_host_ui_handler.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class doc_host_ui_handler final : public IDocHostUIHandler
|
||||
{
|
||||
public:
|
||||
doc_host_ui_handler(html_frame* frame);
|
||||
virtual ~doc_host_ui_handler() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public: // IDocHostUIHandler interface
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObj) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE ShowContextMenu(
|
||||
DWORD dwID,
|
||||
POINT __RPC_FAR * ppt,
|
||||
IUnknown __RPC_FAR * pcmdtReserved,
|
||||
IDispatch __RPC_FAR * pdispReserved) override;
|
||||
HRESULT STDMETHODCALLTYPE ShowUI(
|
||||
DWORD dwID,
|
||||
IOleInPlaceActiveObject __RPC_FAR * pActiveObject,
|
||||
IOleCommandTarget __RPC_FAR * pCommandTarget,
|
||||
IOleInPlaceFrame __RPC_FAR * pFrame,
|
||||
IOleInPlaceUIWindow __RPC_FAR * pDoc) override;
|
||||
HRESULT STDMETHODCALLTYPE GetHostInfo(DOCHOSTUIINFO __RPC_FAR * pInfo) override;
|
||||
HRESULT STDMETHODCALLTYPE HideUI() override;
|
||||
HRESULT STDMETHODCALLTYPE UpdateUI() override;
|
||||
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override;
|
||||
HRESULT STDMETHODCALLTYPE OnDocWindowActivate(BOOL fActivate) override;
|
||||
HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(BOOL fActivate) override;
|
||||
HRESULT STDMETHODCALLTYPE ResizeBorder(LPCRECT prcBorder, IOleInPlaceUIWindow __RPC_FAR * pUIWindow,
|
||||
BOOL fRameWindow) override;
|
||||
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpMsg, const GUID __RPC_FAR * pguidCmdGroup, DWORD nCmdID)
|
||||
override;
|
||||
HRESULT STDMETHODCALLTYPE GetOptionKeyPath(LPOLESTR __RPC_FAR * pchKey, DWORD dw) override;
|
||||
HRESULT STDMETHODCALLTYPE GetDropTarget(IDropTarget __RPC_FAR * pDropTarget,
|
||||
IDropTarget __RPC_FAR *__RPC_FAR * ppDropTarget) override;
|
||||
HRESULT STDMETHODCALLTYPE GetExternal(IDispatch __RPC_FAR *__RPC_FAR * ppDispatch) override;
|
||||
HRESULT STDMETHODCALLTYPE TranslateUrl(DWORD dwTranslate, OLECHAR __RPC_FAR * pchURLIn,
|
||||
OLECHAR __RPC_FAR *__RPC_FAR * ppchURLOut) override;
|
||||
HRESULT STDMETHODCALLTYPE FilterDataObject(IDataObject __RPC_FAR * pDO, IDataObject __RPC_FAR *__RPC_FAR * ppDORet)
|
||||
override;
|
||||
};
|
37
src/launcher/html/html_argument.cpp
Normal file
37
src/launcher/html/html_argument.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_argument.hpp"
|
||||
|
||||
html_argument::html_argument(VARIANT* val) : value_(val)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool html_argument::is_empty() const
|
||||
{
|
||||
return this->value_ == nullptr || this->value_->vt == VT_EMPTY;
|
||||
}
|
||||
|
||||
bool html_argument::is_string() const
|
||||
{
|
||||
if(this->is_empty()) return false;
|
||||
return this->value_->vt == VT_BSTR;
|
||||
}
|
||||
|
||||
bool html_argument::is_number() const
|
||||
{
|
||||
if(this->is_empty()) return false;
|
||||
return this->value_->vt == VT_I4;
|
||||
}
|
||||
|
||||
std::string html_argument::get_string() const
|
||||
{
|
||||
if(!this->is_string()) return {};
|
||||
std::wstring wide_string(this->value_->bstrVal);
|
||||
return std::string(wide_string.begin(), wide_string.end());
|
||||
}
|
||||
|
||||
int html_argument::get_number() const
|
||||
{
|
||||
if(!this->is_number()) return 0;
|
||||
return this->value_->intVal;
|
||||
}
|
18
src/launcher/html/html_argument.hpp
Normal file
18
src/launcher/html/html_argument.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
class html_argument final
|
||||
{
|
||||
public:
|
||||
html_argument(VARIANT* val);
|
||||
|
||||
bool is_empty() const;
|
||||
|
||||
bool is_string() const;
|
||||
bool is_number() const;
|
||||
|
||||
std::string get_string() const;
|
||||
int get_number() const;
|
||||
|
||||
private:
|
||||
VARIANT* value_;
|
||||
};
|
61
src/launcher/html/html_dispatch.cpp
Normal file
61
src/launcher/html/html_dispatch.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../html_frame.hpp"
|
||||
|
||||
html_dispatch::html_dispatch(html_frame* frame) : frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::QueryInterface(const IID& riid, LPVOID* ppvObj)
|
||||
{
|
||||
if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) ||
|
||||
!memcmp(&riid, &IID_IDispatch, sizeof(GUID)))
|
||||
{
|
||||
*ppvObj = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppvObj = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG html_dispatch::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG html_dispatch::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::GetTypeInfoCount(UINT* pctinfo)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo)
|
||||
{
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::GetIDsOfNames(const IID& riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
|
||||
{
|
||||
for(unsigned int i = 0; i < cNames; ++i)
|
||||
{
|
||||
std::wstring wide_name(rgszNames[i]);
|
||||
std::string name(wide_name.begin(), wide_name.end());
|
||||
|
||||
rgDispId[i] = this->frame_->get_callback_id(name);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT html_dispatch::Invoke(DISPID dispIdMember, const IID& riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
|
||||
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
|
||||
{
|
||||
html_frame::callback_params params(pDispParams, pVarResult);
|
||||
this->frame_->invoke_callback(dispIdMember, ¶ms);
|
||||
return S_OK;
|
||||
}
|
24
src/launcher/html/html_dispatch.hpp
Normal file
24
src/launcher/html/html_dispatch.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class html_dispatch final : public IDispatch
|
||||
{
|
||||
public:
|
||||
html_dispatch(html_frame* frame);
|
||||
virtual ~html_dispatch() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public: // IDispatch interface
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT* pctinfo) override;
|
||||
HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) override;
|
||||
HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId)
|
||||
override;
|
||||
HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
|
||||
VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) override;
|
||||
};
|
77
src/launcher/html/ole_client_site.cpp
Normal file
77
src/launcher/html/ole_client_site.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../html_frame.hpp"
|
||||
|
||||
ole_client_site::ole_client_site(html_frame* frame): frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::QueryInterface(REFIID riid, LPVOID* ppvObject)
|
||||
{
|
||||
if (!memcmp(&riid, &IID_IUnknown, sizeof(GUID)) ||
|
||||
!memcmp(&riid, &IID_IOleClientSite, sizeof(GUID)))
|
||||
{
|
||||
*ppvObject = this;
|
||||
this->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!memcmp(&riid, &IID_IOleInPlaceSite, sizeof(GUID)))
|
||||
{
|
||||
auto in_place_site = this->frame_->get_in_place_site();
|
||||
in_place_site->AddRef();
|
||||
*ppvObject = in_place_site;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (!memcmp(&riid, &IID_IDocHostUIHandler, sizeof(GUID)))
|
||||
{
|
||||
auto ui_handler = this->frame_->get_ui_handler();
|
||||
ui_handler->AddRef();
|
||||
*ppvObject = ui_handler;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*ppvObject = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG ole_client_site::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG ole_client_site::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::SaveObject()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::GetMoniker(DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker** /*ppmk*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::GetContainer(LPOLECONTAINER* ppContainer)
|
||||
{
|
||||
*ppContainer = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::ShowObject()
|
||||
{
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::OnShowWindow(BOOL /*fShow*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_client_site::RequestNewObjectLayout()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
24
src/launcher/html/ole_client_site.hpp
Normal file
24
src/launcher/html/ole_client_site.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class ole_client_site final : public IOleClientSite
|
||||
{
|
||||
public:
|
||||
ole_client_site(html_frame* frame);
|
||||
virtual ~ole_client_site() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public:
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObject) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE SaveObject() override;
|
||||
HRESULT STDMETHODCALLTYPE GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk) override;
|
||||
HRESULT STDMETHODCALLTYPE GetContainer(LPOLECONTAINER FAR* ppContainer) override;
|
||||
HRESULT STDMETHODCALLTYPE ShowObject() override;
|
||||
HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL fShow) override;
|
||||
HRESULT STDMETHODCALLTYPE RequestNewObjectLayout() override;
|
||||
};
|
82
src/launcher/html/ole_in_place_frame.cpp
Normal file
82
src/launcher/html/ole_in_place_frame.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../html_frame.hpp"
|
||||
|
||||
ole_in_place_frame::ole_in_place_frame(html_frame* frame): frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::QueryInterface(REFIID /*riid*/, LPVOID* /*ppvObj*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
ULONG ole_in_place_frame::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG ole_in_place_frame::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::GetWindow(HWND* lphwnd)
|
||||
{
|
||||
*lphwnd = this->frame_->get_window();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::ContextSensitiveHelp(BOOL /*fEnterMode*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::GetBorder(LPRECT /*lprectBorder*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::RequestBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::SetBorderSpace(LPCBORDERWIDTHS /*pborderwidths*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::SetActiveObject(IOleInPlaceActiveObject* /*pActiveObject*/, LPCOLESTR /*pszObjName*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::SetMenu(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::RemoveMenus(HMENU /*hmenuShared*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::SetStatusText(LPCOLESTR /*pszStatusText*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::EnableModeless(BOOL /*fEnable*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_frame::TranslateAcceleratorA(LPMSG /*lpmsg*/, WORD /*wID*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
30
src/launcher/html/ole_in_place_frame.hpp
Normal file
30
src/launcher/html/ole_in_place_frame.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class ole_in_place_frame final : public IOleInPlaceFrame
|
||||
{
|
||||
public:
|
||||
ole_in_place_frame(html_frame* frame);
|
||||
virtual ~ole_in_place_frame() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public: // IOleInPlaceFrame interface
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override;
|
||||
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override;
|
||||
HRESULT STDMETHODCALLTYPE GetBorder(LPRECT lprectBorder) override;
|
||||
HRESULT STDMETHODCALLTYPE RequestBorderSpace(LPCBORDERWIDTHS pborderwidths) override;
|
||||
HRESULT STDMETHODCALLTYPE SetBorderSpace(LPCBORDERWIDTHS pborderwidths) override;
|
||||
HRESULT STDMETHODCALLTYPE SetActiveObject(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR pszObjName) override;
|
||||
HRESULT STDMETHODCALLTYPE InsertMenus(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths) override;
|
||||
HRESULT STDMETHODCALLTYPE SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND hwndActiveObject) override;
|
||||
HRESULT STDMETHODCALLTYPE RemoveMenus(HMENU hmenuShared) override;
|
||||
HRESULT STDMETHODCALLTYPE SetStatusText(LPCOLESTR pszStatusText) override;
|
||||
HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable) override;
|
||||
HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG lpmsg, WORD wID) override;
|
||||
};
|
105
src/launcher/html/ole_in_place_site.cpp
Normal file
105
src/launcher/html/ole_in_place_site.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../html_frame.hpp"
|
||||
|
||||
ole_in_place_site::ole_in_place_site(html_frame* frame) : frame_(frame)
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
|
||||
{
|
||||
auto client_site = this->frame_->get_client_site();
|
||||
if (client_site)
|
||||
{
|
||||
return client_site->QueryInterface(riid, ppvObj);
|
||||
}
|
||||
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG ole_in_place_site::AddRef()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG ole_in_place_site::Release()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::GetWindow(HWND* lphwnd)
|
||||
{
|
||||
*lphwnd = this->frame_->get_window();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::ContextSensitiveHelp(BOOL /*fEnterMode*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::CanInPlaceActivate()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnInPlaceActivate()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnUIActivate()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::GetWindowContext(LPOLEINPLACEFRAME* lplpFrame, LPOLEINPLACEUIWINDOW* lplpDoc,
|
||||
LPRECT /*lprcPosRect*/, LPRECT /*lprcClipRect*/,
|
||||
LPOLEINPLACEFRAMEINFO lpFrameInfo)
|
||||
{
|
||||
*lplpFrame = this->frame_->get_in_place_frame();
|
||||
*lplpDoc = nullptr;
|
||||
|
||||
lpFrameInfo->fMDIApp = FALSE;
|
||||
lpFrameInfo->hwndFrame = this->frame_->get_window();
|
||||
lpFrameInfo->haccel = nullptr;
|
||||
lpFrameInfo->cAccelEntries = 0;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::Scroll(SIZE /*scrollExtent*/)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnUIDeactivate(BOOL /*fUndoable*/)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnInPlaceDeactivate()
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::DiscardUndoState()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::DeactivateAndUndo()
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT ole_in_place_site::OnPosRectChange(LPCRECT lprcPosRect)
|
||||
{
|
||||
IOleInPlaceObject* in_place = nullptr;
|
||||
if (!this->frame_->get_browser_object()->QueryInterface(IID_IOleInPlaceObject, reinterpret_cast<void**>(&in_place)))
|
||||
{
|
||||
in_place->SetObjectRects(lprcPosRect, lprcPosRect);
|
||||
in_place->Release();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
32
src/launcher/html/ole_in_place_site.hpp
Normal file
32
src/launcher/html/ole_in_place_site.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
class html_frame;
|
||||
|
||||
class ole_in_place_site final : public IOleInPlaceSite
|
||||
{
|
||||
public:
|
||||
ole_in_place_site(html_frame* frame);
|
||||
virtual ~ole_in_place_site() = default;
|
||||
|
||||
private:
|
||||
html_frame* frame_;
|
||||
|
||||
public: // IOleInPlaceSite interface
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID FAR* ppvObj) override;
|
||||
ULONG STDMETHODCALLTYPE AddRef() override;
|
||||
ULONG STDMETHODCALLTYPE Release() override;
|
||||
HRESULT STDMETHODCALLTYPE GetWindow(HWND FAR* lphwnd) override;
|
||||
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode) override;
|
||||
HRESULT STDMETHODCALLTYPE CanInPlaceActivate() override;
|
||||
HRESULT STDMETHODCALLTYPE OnInPlaceActivate() override;
|
||||
HRESULT STDMETHODCALLTYPE OnUIActivate() override;
|
||||
HRESULT STDMETHODCALLTYPE GetWindowContext(LPOLEINPLACEFRAME FAR* lplpFrame, LPOLEINPLACEUIWINDOW FAR* lplpDoc,
|
||||
LPRECT lprcPosRect, LPRECT lprcClipRect,
|
||||
LPOLEINPLACEFRAMEINFO lpFrameInfo) override;
|
||||
HRESULT STDMETHODCALLTYPE Scroll(SIZE scrollExtent) override;
|
||||
HRESULT STDMETHODCALLTYPE OnUIDeactivate(BOOL fUndoable) override;
|
||||
HRESULT STDMETHODCALLTYPE OnInPlaceDeactivate() override;
|
||||
HRESULT STDMETHODCALLTYPE DiscardUndoState() override;
|
||||
HRESULT STDMETHODCALLTYPE DeactivateAndUndo() override;
|
||||
HRESULT STDMETHODCALLTYPE OnPosRectChange(LPCRECT lprcPosRect) override;
|
||||
};
|
256
src/launcher/html_frame.cpp
Normal file
256
src/launcher/html_frame.cpp
Normal file
@ -0,0 +1,256 @@
|
||||
#include <std_include.hpp>
|
||||
#include "html_frame.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
|
||||
html_frame::callback_params::callback_params(DISPPARAMS* params, VARIANT* res) : result(res)
|
||||
{
|
||||
for (auto i = params->cArgs; i > 0; --i)
|
||||
{
|
||||
auto param = ¶ms->rgvarg[i - 1];
|
||||
this->arguments.emplace_back(param);
|
||||
}
|
||||
}
|
||||
|
||||
html_frame::html_frame() : in_place_frame_(this), in_place_site_(this), ui_handler_(this), client_site_(this),
|
||||
html_dispatch_(this)
|
||||
{
|
||||
if (OleInitialize(nullptr) != S_OK)
|
||||
{
|
||||
throw std::runtime_error("Unable to initialize the OLE library");
|
||||
}
|
||||
|
||||
set_browser_feature("FEATURE_BROWSER_EMULATION", 11000);
|
||||
set_browser_feature("FEATURE_GPU_RENDERING", 1);
|
||||
}
|
||||
|
||||
html_frame::~html_frame()
|
||||
{
|
||||
OleUninitialize();
|
||||
}
|
||||
|
||||
void html_frame::object_deleter(IUnknown* object)
|
||||
{
|
||||
if (object)
|
||||
{
|
||||
object->Release();
|
||||
}
|
||||
}
|
||||
|
||||
HWND html_frame::get_window() const
|
||||
{
|
||||
return this->window_;
|
||||
}
|
||||
|
||||
std::shared_ptr<IOleObject> html_frame::get_browser_object() const
|
||||
{
|
||||
return this->browser_object_;
|
||||
}
|
||||
|
||||
ole_in_place_frame* html_frame::get_in_place_frame()
|
||||
{
|
||||
return &this->in_place_frame_;
|
||||
}
|
||||
|
||||
ole_in_place_site* html_frame::get_in_place_site()
|
||||
{
|
||||
return &this->in_place_site_;
|
||||
}
|
||||
|
||||
doc_host_ui_handler* html_frame::get_ui_handler()
|
||||
{
|
||||
return &this->ui_handler_;
|
||||
}
|
||||
|
||||
ole_client_site* html_frame::get_client_site()
|
||||
{
|
||||
return &this->client_site_;
|
||||
}
|
||||
|
||||
html_dispatch* html_frame::get_html_dispatch()
|
||||
{
|
||||
return &this->html_dispatch_;
|
||||
}
|
||||
|
||||
std::shared_ptr<IWebBrowser2> html_frame::get_web_browser() const
|
||||
{
|
||||
if (!this->browser_object_) return {};
|
||||
|
||||
IWebBrowser2* web_browser = nullptr;
|
||||
if (this->browser_object_->QueryInterface(IID_IWebBrowser2, reinterpret_cast<void**>(&web_browser)) || !web_browser)
|
||||
return {};
|
||||
|
||||
return std::shared_ptr<IWebBrowser2>(web_browser, object_deleter);
|
||||
}
|
||||
|
||||
std::shared_ptr<IDispatch> html_frame::get_dispatch() const
|
||||
{
|
||||
const auto web_browser = this->get_web_browser();
|
||||
if (!web_browser) return {};
|
||||
|
||||
IDispatch* dispatch = nullptr;
|
||||
if (web_browser->get_Document(&dispatch) || !dispatch) return {};
|
||||
|
||||
return std::shared_ptr<IDispatch>(dispatch, object_deleter);
|
||||
}
|
||||
|
||||
std::shared_ptr<IHTMLDocument2> html_frame::get_document() const
|
||||
{
|
||||
const auto dispatch = this->get_dispatch();
|
||||
if (!dispatch) return {};
|
||||
|
||||
IHTMLDocument2* document = nullptr;
|
||||
if (dispatch->QueryInterface(IID_IHTMLDocument2, reinterpret_cast<void**>(&document)) || !document) return {};
|
||||
|
||||
return std::shared_ptr<IHTMLDocument2>(document, object_deleter);
|
||||
}
|
||||
|
||||
void html_frame::initialize(const HWND window)
|
||||
{
|
||||
if (this->window_) return;
|
||||
this->window_ = window;
|
||||
|
||||
this->create_browser();
|
||||
this->initialize_browser();
|
||||
}
|
||||
|
||||
void html_frame::create_browser()
|
||||
{
|
||||
LPCLASSFACTORY class_factory = nullptr;
|
||||
if (CoGetClassObject(CLSID_WebBrowser, CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, nullptr, IID_IClassFactory,
|
||||
reinterpret_cast<void **>(&class_factory)) || !class_factory)
|
||||
{
|
||||
throw std::runtime_error("Unable to get the class factory");
|
||||
}
|
||||
|
||||
IOleObject* browser_object = nullptr;
|
||||
class_factory->CreateInstance(nullptr, IID_IOleObject, reinterpret_cast<void**>(&browser_object));
|
||||
class_factory->Release();
|
||||
|
||||
if (!browser_object)
|
||||
{
|
||||
throw std::runtime_error("Unable to create browser object");
|
||||
}
|
||||
|
||||
this->browser_object_ = std::shared_ptr<IOleObject>(browser_object, [](IOleObject* browser_object)
|
||||
{
|
||||
if (browser_object)
|
||||
{
|
||||
browser_object->Close(OLECLOSE_NOSAVE);
|
||||
object_deleter(browser_object);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void html_frame::initialize_browser()
|
||||
{
|
||||
this->browser_object_->SetClientSite(this->get_client_site());
|
||||
this->browser_object_->SetHostNames(L"Hostname", nullptr);
|
||||
|
||||
RECT rect;
|
||||
GetClientRect(this->get_window(), &rect);
|
||||
OleSetContainedObject(this->browser_object_.get(), TRUE);
|
||||
|
||||
this->browser_object_->DoVerb(OLEIVERB_SHOW, nullptr, this->get_client_site(), -1, this->get_window(), &rect);
|
||||
this->resize(rect.right, rect.bottom);
|
||||
}
|
||||
|
||||
void html_frame::set_browser_feature(const std::string& feature, DWORD value)
|
||||
{
|
||||
const auto registry_path = R"(SOFTWARE\Microsoft\Internet Explorer\Main\FeatureControl\)" + feature;
|
||||
|
||||
HKEY key = nullptr;
|
||||
if (RegOpenKeyExA(
|
||||
HKEY_CURRENT_USER, registry_path.data(), 0,
|
||||
KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
|
||||
return;
|
||||
|
||||
const utils::nt::module self;
|
||||
const auto name = self.get_name();
|
||||
RegSetValueExA(key, name.data(), 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
|
||||
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
void html_frame::resize(const DWORD width, const DWORD height) const
|
||||
{
|
||||
auto web_browser = this->get_web_browser();
|
||||
if (web_browser)
|
||||
{
|
||||
web_browser->put_Left(0);
|
||||
web_browser->put_Top(0);
|
||||
web_browser->put_Width(width);
|
||||
web_browser->put_Height(height);
|
||||
}
|
||||
}
|
||||
|
||||
bool html_frame::load_url(const std::string& url) const
|
||||
{
|
||||
auto web_browser = this->get_web_browser();
|
||||
if (!web_browser) return false;
|
||||
|
||||
std::wstring wide_url(url.begin(), url.end());
|
||||
|
||||
VARIANT my_url;
|
||||
VariantInit(&my_url);
|
||||
my_url.vt = VT_BSTR;
|
||||
my_url.bstrVal = SysAllocString(wide_url.data());
|
||||
|
||||
const auto _ = gsl::finally([&my_url]() { VariantClear(&my_url); });
|
||||
if (!my_url.bstrVal) return false;
|
||||
|
||||
return SUCCEEDED(web_browser->Navigate2(&my_url, nullptr, nullptr, nullptr, nullptr));
|
||||
}
|
||||
|
||||
bool html_frame::load_html(const std::string& html) const
|
||||
{
|
||||
if (!this->load_url("about:blank")) return false;
|
||||
|
||||
const auto document = this->get_document();
|
||||
if (!document) return false;
|
||||
|
||||
SAFEARRAYBOUND safe_array_bound = {1, 0};
|
||||
auto safe_array = SafeArrayCreate(VT_VARIANT, 1, &safe_array_bound);
|
||||
if (!safe_array) return false;
|
||||
|
||||
const auto _ = gsl::finally([safe_array]() { SafeArrayDestroy(safe_array); });
|
||||
|
||||
VARIANT* variant = nullptr;
|
||||
if (SafeArrayAccessData(safe_array, reinterpret_cast<void**>(&variant)) || !variant) return false;
|
||||
|
||||
std::wstring wide_html(html.begin(), html.end());
|
||||
|
||||
variant->vt = VT_BSTR;
|
||||
variant->bstrVal = SysAllocString(wide_html.data());
|
||||
if (!variant->bstrVal) return false;
|
||||
|
||||
document->write(safe_array);
|
||||
document->close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int html_frame::get_callback_id(const std::string& name)
|
||||
{
|
||||
for (auto i = 0u; i < this->callbacks_.size(); ++i)
|
||||
{
|
||||
if (this->callbacks_[i].first == name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void html_frame::invoke_callback(const int id, callback_params* params)
|
||||
{
|
||||
if (id >= 0 && static_cast<unsigned int>(id) < this->callbacks_.size())
|
||||
{
|
||||
this->callbacks_[id].second(params);
|
||||
}
|
||||
}
|
||||
|
||||
void html_frame::register_callback(const std::string& name, const std::function<void(callback_params*)>& callback)
|
||||
{
|
||||
this->callbacks_.emplace_back(name, callback);
|
||||
}
|
65
src/launcher/html_frame.hpp
Normal file
65
src/launcher/html_frame.hpp
Normal file
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
#include "html/ole_in_place_frame.hpp"
|
||||
#include "html/ole_in_place_site.hpp"
|
||||
#include "html/doc_host_ui_handler.hpp"
|
||||
#include "html/ole_client_site.hpp"
|
||||
#include "html/html_dispatch.hpp"
|
||||
#include "html/html_argument.hpp"
|
||||
|
||||
class html_frame final
|
||||
{
|
||||
public:
|
||||
class callback_params final
|
||||
{
|
||||
public:
|
||||
callback_params(DISPPARAMS* params, VARIANT* res);
|
||||
|
||||
std::vector<html_argument> arguments;
|
||||
html_argument result;
|
||||
};
|
||||
|
||||
html_frame();
|
||||
~html_frame();
|
||||
|
||||
void initialize(const HWND window);
|
||||
|
||||
void resize(DWORD width, DWORD height) const;
|
||||
bool load_url(const std::string& url) const;
|
||||
bool load_html(const std::string& html) const;
|
||||
|
||||
HWND get_window() const;
|
||||
|
||||
std::shared_ptr<IOleObject> get_browser_object() const;
|
||||
std::shared_ptr<IWebBrowser2> get_web_browser() const;
|
||||
std::shared_ptr<IDispatch> get_dispatch() const;
|
||||
std::shared_ptr<IHTMLDocument2> get_document() const;
|
||||
|
||||
ole_in_place_frame* get_in_place_frame();
|
||||
ole_in_place_site* get_in_place_site();
|
||||
doc_host_ui_handler* get_ui_handler();
|
||||
ole_client_site* get_client_site();
|
||||
html_dispatch* get_html_dispatch();
|
||||
|
||||
int get_callback_id(const std::string& name);
|
||||
void invoke_callback(int id, callback_params* params);
|
||||
|
||||
void register_callback(const std::string& name, const std::function<void(callback_params*)>& callback);
|
||||
|
||||
private:
|
||||
HWND window_ = nullptr;
|
||||
std::shared_ptr<IOleObject> browser_object_;
|
||||
|
||||
ole_in_place_frame in_place_frame_;
|
||||
ole_in_place_site in_place_site_;
|
||||
doc_host_ui_handler ui_handler_;
|
||||
ole_client_site client_site_;
|
||||
html_dispatch html_dispatch_;
|
||||
|
||||
std::vector<std::pair<std::string, std::function<void(callback_params*)>>> callbacks_;
|
||||
|
||||
void create_browser();
|
||||
void initialize_browser();
|
||||
|
||||
static void set_browser_feature(const std::string& feature, DWORD value);
|
||||
static void object_deleter(IUnknown* object);
|
||||
};
|
@ -1,75 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
#include "image.hpp"
|
||||
|
||||
image::image(const size_t resource)
|
||||
{
|
||||
this->bitmap_ = LoadBitmapA(GetModuleHandleA(nullptr), MAKEINTRESOURCEA(resource));
|
||||
}
|
||||
|
||||
image::~image()
|
||||
{
|
||||
DeleteBitmap(this->bitmap_);
|
||||
}
|
||||
|
||||
void image::set_position(const POINT& position)
|
||||
{
|
||||
this->position_ = position;
|
||||
}
|
||||
|
||||
void image::set_size(const POINT& size)
|
||||
{
|
||||
this->size_ = size;
|
||||
}
|
||||
|
||||
bool image::is_hovered(const POINT& mouse) const
|
||||
{
|
||||
return mouse.x >= this->position_.x && mouse.x < (this->position_.x + this->size_.x)
|
||||
&& mouse.y >= this->position_.y && mouse.y < (this->position_.y + this->size_.y);
|
||||
}
|
||||
|
||||
void image::paint(const HDC hdc, const POINT& mouse) const
|
||||
{
|
||||
BITMAP bitmap;
|
||||
GetObject(this->bitmap_, sizeof(bitmap), &bitmap);
|
||||
|
||||
const auto dc = CreateCompatibleDC(hdc);
|
||||
SelectObject(dc, this->bitmap_);
|
||||
|
||||
const LONG modifier = 2;
|
||||
LONG size_offset = 0;
|
||||
LONG position_offset = 0;
|
||||
if (this->is_hovered(mouse))
|
||||
{
|
||||
size_offset = modifier * 2;
|
||||
position_offset = -modifier;
|
||||
}
|
||||
|
||||
SetStretchBltMode(hdc, HALFTONE);
|
||||
StretchBlt(hdc, this->position_.x + position_offset, this->position_.y + position_offset,
|
||||
this->size_.x + size_offset, this->size_.y + size_offset, dc, 0, 0, bitmap.bmWidth,
|
||||
bitmap.bmHeight, SRCCOPY);
|
||||
|
||||
DeleteDC(dc);
|
||||
}
|
||||
|
||||
void image::set_click_listener(std::function<void()> callback)
|
||||
{
|
||||
this->callback_ = callback;
|
||||
}
|
||||
|
||||
void image::click(const POINT& mouse, const bool down)
|
||||
{
|
||||
if (down)
|
||||
{
|
||||
this->down_handled_ = this->is_hovered(mouse);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this->down_handled_ && this->is_hovered(mouse) && this->callback_)
|
||||
{
|
||||
this->callback_();
|
||||
}
|
||||
|
||||
this->down_handled_ = false;
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
class image final
|
||||
{
|
||||
public:
|
||||
image(size_t resource);
|
||||
~image();
|
||||
|
||||
void set_position(const POINT& position);
|
||||
void set_size(const POINT& size);
|
||||
|
||||
bool is_hovered(const POINT& mouse) const;
|
||||
|
||||
void paint(HDC hdc, const POINT& mouse) const;
|
||||
|
||||
void set_click_listener(std::function<void()> callback);
|
||||
|
||||
void click(const POINT& mouse, bool down);
|
||||
|
||||
private:
|
||||
POINT size_{};
|
||||
POINT position_{};
|
||||
HBITMAP bitmap_;
|
||||
|
||||
bool down_handled_ = false;
|
||||
std::function<void()> callback_;
|
||||
};
|
@ -1,19 +1,29 @@
|
||||
#include <std_include.hpp>
|
||||
#include "launcher.hpp"
|
||||
#include "html_frame.hpp"
|
||||
#include "utils/nt.hpp"
|
||||
|
||||
launcher::launcher() : window_("Open-IW5", 615, 300), image_sp_(IMAGE_SP), image_mp_(IMAGE_MP)
|
||||
launcher::launcher()
|
||||
{
|
||||
this->image_sp_.set_position({100, 90});
|
||||
this->image_mp_.set_position({401, 90});
|
||||
|
||||
this->image_sp_.set_size({100, 100});
|
||||
this->image_mp_.set_size({100, 100});
|
||||
|
||||
this->image_sp_.set_click_listener(std::bind(&launcher::select_mode, this, mode::singleplayer));
|
||||
this->image_mp_.set_click_listener(std::bind(&launcher::select_mode, this, mode::multiplayer));
|
||||
|
||||
this->window_.set_callback(std::bind(&launcher::handler, this, std::placeholders::_1, std::placeholders::_2,
|
||||
std::placeholders::_3));
|
||||
|
||||
this->html_frame_.register_callback("selectMode", [this](html_frame::callback_params* params)
|
||||
{
|
||||
if(params->arguments.empty()) return;
|
||||
|
||||
const auto param = params->arguments[0];
|
||||
if(!param.is_number()) return;
|
||||
|
||||
const auto number = param.get_number();
|
||||
if(number == singleplayer || number == multiplayer)
|
||||
{
|
||||
this->select_mode(static_cast<mode>(number));
|
||||
}
|
||||
});
|
||||
|
||||
this->window_.create("Open-IW5", 615, 300);
|
||||
this->html_frame_.load_html(load_content());
|
||||
}
|
||||
|
||||
launcher::mode launcher::run() const
|
||||
@ -25,27 +35,16 @@ launcher::mode launcher::run() const
|
||||
|
||||
LRESULT launcher::handler(const UINT message, const WPARAM w_param, const LPARAM l_param)
|
||||
{
|
||||
if (message == WM_PAINT)
|
||||
if (message == WM_SIZE)
|
||||
{
|
||||
this->paint();
|
||||
this->html_frame_.resize(LOWORD(l_param), HIWORD(l_param));
|
||||
return 0;
|
||||
}
|
||||
else if (message == WM_MOUSEMOVE)
|
||||
|
||||
if (message == WM_CREATE)
|
||||
{
|
||||
this->mouse_move(l_param);
|
||||
}
|
||||
else if (message == WM_LBUTTONDOWN)
|
||||
{
|
||||
this->image_sp_.click(this->mouse_, true);
|
||||
this->image_mp_.click(this->mouse_, true);
|
||||
}
|
||||
else if (message == WM_LBUTTONUP)
|
||||
{
|
||||
this->image_sp_.click(this->mouse_, false);
|
||||
this->image_mp_.click(this->mouse_, false);
|
||||
}
|
||||
else if (message == WM_ERASEBKGND)
|
||||
{
|
||||
return TRUE;
|
||||
this->html_frame_.initialize(this->window_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return DefWindowProc(this->window_, message, w_param, l_param);
|
||||
@ -57,64 +56,13 @@ void launcher::select_mode(const mode mode)
|
||||
this->window_.close();
|
||||
}
|
||||
|
||||
void launcher::draw_text(const HDC hdc)
|
||||
std::string launcher::load_content()
|
||||
{
|
||||
Gdiplus::Graphics graphics(hdc);
|
||||
Gdiplus::SolidBrush color(Gdiplus::Color(255, 150, 150, 150));
|
||||
Gdiplus::FontFamily font_family(L"Segoe UI");
|
||||
Gdiplus::Font font(&font_family, 20, Gdiplus::FontStyleRegular, Gdiplus::UnitPixel);
|
||||
const auto stringformat = Gdiplus::StringFormat::GenericTypographic();
|
||||
const auto res = FindResource(::utils::nt::module(), MAKEINTRESOURCE(MAIN_MENU), RT_RCDATA);
|
||||
if (!res) return {};
|
||||
|
||||
std::wstring sp(L"Singleplayer");
|
||||
std::wstring mp(L"Multiplayer");
|
||||
const auto handle = LoadResource(nullptr, res);
|
||||
if (!handle) return {};
|
||||
|
||||
Gdiplus::RectF rect{};
|
||||
graphics.MeasureString(sp.data(), -1, &font, rect, stringformat, &rect);
|
||||
|
||||
const Gdiplus::PointF pos{150 - (rect.Width / 2 + 2), 45};
|
||||
graphics.DrawString(sp.data(), -1, &font, pos, &color);
|
||||
|
||||
rect = {};
|
||||
graphics.MeasureString(mp.data(), -1, &font, rect, stringformat, &rect);
|
||||
graphics.DrawString(mp.data(), -1, &font, {451 - (rect.Width / 2 + 4), 45}, &color);
|
||||
|
||||
Gdiplus::Pen pen(Gdiplus::Color(50, 255, 255, 255), 1);
|
||||
graphics.DrawLine(&pen, 300, 0, 300, 600);
|
||||
}
|
||||
|
||||
void launcher::paint() const
|
||||
{
|
||||
RECT rect;
|
||||
GetClientRect(this->window_, &rect);
|
||||
const int width = rect.right - rect.left;
|
||||
const int height = rect.bottom + rect.left;
|
||||
|
||||
PAINTSTRUCT ps;
|
||||
const auto hdc = BeginPaint(this->window_, &ps);
|
||||
|
||||
const auto hdc_copy = CreateCompatibleDC(hdc);
|
||||
const auto bitmap = CreateCompatibleBitmap(hdc, width, height);
|
||||
SelectObject(hdc_copy, bitmap);
|
||||
|
||||
this->window_.clear(hdc_copy);
|
||||
|
||||
this->draw_text(hdc_copy);
|
||||
|
||||
this->image_sp_.paint(hdc_copy, this->mouse_);
|
||||
this->image_mp_.paint(hdc_copy, this->mouse_);
|
||||
|
||||
BitBlt(hdc, 0, 0, width, height, hdc_copy, 0, 0, SRCCOPY);
|
||||
|
||||
DeleteObject(bitmap);
|
||||
DeleteDC(hdc_copy);
|
||||
|
||||
EndPaint(this->window_, &ps);
|
||||
}
|
||||
|
||||
void launcher::mouse_move(const LPARAM l_param)
|
||||
{
|
||||
this->mouse_.x = GET_X_LPARAM(l_param);
|
||||
this->mouse_.y = GET_Y_LPARAM(l_param);
|
||||
|
||||
InvalidateRect(this->window_, nullptr, FALSE);
|
||||
return std::string(LPSTR(LockResource(handle)), SizeofResource(nullptr, res));
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "window.hpp"
|
||||
#include "image.hpp"
|
||||
#include "html_frame.hpp"
|
||||
|
||||
class launcher final
|
||||
{
|
||||
@ -21,17 +21,10 @@ private:
|
||||
mode mode_ = none;
|
||||
|
||||
window window_;
|
||||
|
||||
image image_sp_;
|
||||
image image_mp_;
|
||||
|
||||
POINT mouse_{};
|
||||
html_frame html_frame_;
|
||||
|
||||
LRESULT handler(const UINT message, const WPARAM w_param, const LPARAM l_param);
|
||||
|
||||
void select_mode(mode mode);
|
||||
|
||||
static void draw_text(const HDC hdc);
|
||||
void paint() const;
|
||||
void mouse_move(LPARAM l_param);
|
||||
static std::string load_content();
|
||||
};
|
||||
|
@ -1,36 +1,32 @@
|
||||
#include <std_include.hpp>
|
||||
#include "window.hpp"
|
||||
|
||||
window::window(const std::string& title, const int width, const int height)
|
||||
window::window()
|
||||
{
|
||||
Gdiplus::GdiplusStartupInput input;
|
||||
GdiplusStartup(&this->token_, &input, nullptr);
|
||||
|
||||
const auto handle = GetModuleHandle(nullptr);
|
||||
|
||||
ZeroMemory(&this->wc_, sizeof(this->wc_));
|
||||
|
||||
this->classname = "window-base-" + std::to_string(time(nullptr));
|
||||
this->classname_ = "window-base-" + std::to_string(time(nullptr));
|
||||
|
||||
this->wc_.cbSize = sizeof(this->wc_);
|
||||
this->wc_.style = CS_HREDRAW | CS_VREDRAW;
|
||||
this->wc_.lpfnWndProc = static_processor;
|
||||
this->wc_.hInstance = handle;
|
||||
this->wc_.hInstance = GetModuleHandle(nullptr);
|
||||
this->wc_.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
this->wc_.hIcon = LoadIcon(handle, MAKEINTRESOURCE(102));
|
||||
this->wc_.hIcon = LoadIcon(this->wc_.hInstance, MAKEINTRESOURCE(102));
|
||||
this->wc_.hIconSm = this->wc_.hIcon;
|
||||
this->wc_.hbrBackground = CreateSolidBrush(RGB(35, 35, 35));
|
||||
this->wc_.lpszClassName = this->classname.data();
|
||||
this->wc_.hbrBackground = HBRUSH(COLOR_WINDOW);
|
||||
this->wc_.lpszClassName = this->classname_.data();
|
||||
RegisterClassEx(&this->wc_);
|
||||
}
|
||||
|
||||
void window::create(const std::string& title, const int width, const int height)
|
||||
{
|
||||
const auto x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
|
||||
const auto y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
|
||||
|
||||
this->handle_ = CreateWindowExA(NULL, this->wc_.lpszClassName, title.data(),
|
||||
(WS_OVERLAPPEDWINDOW | WS_VISIBLE) & ~(WS_THICKFRAME | WS_MAXIMIZEBOX), x, y, width,
|
||||
height, nullptr, nullptr, handle, nullptr);
|
||||
|
||||
SetWindowLongPtrA(*this, GWLP_USERDATA, LONG_PTR(this));
|
||||
height, nullptr, nullptr, this->wc_.hInstance, this);
|
||||
}
|
||||
|
||||
window::~window()
|
||||
@ -38,8 +34,6 @@ window::~window()
|
||||
this->close();
|
||||
UnregisterClass(this->wc_.lpszClassName, this->wc_.hInstance);
|
||||
DeleteObject(this->wc_.hbrBackground);
|
||||
|
||||
Gdiplus::GdiplusShutdown(this->token_);
|
||||
}
|
||||
|
||||
void window::close()
|
||||
@ -53,25 +47,13 @@ void window::close()
|
||||
void window::run() const
|
||||
{
|
||||
MSG msg;
|
||||
while (this->handle_ && IsWindow(*this))
|
||||
while (GetMessage(&msg, nullptr, 0, 0))
|
||||
{
|
||||
if (PeekMessageA(&msg, nullptr, NULL, NULL, PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageA(&msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(1ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
|
||||
void window::clear(const HDC hdc) const
|
||||
{
|
||||
RECT rc;
|
||||
GetClientRect(*this, &rc);
|
||||
FillRect(hdc, &rc, this->wc_.hbrBackground);
|
||||
//if(!this->handle_) break;
|
||||
}
|
||||
}
|
||||
|
||||
void window::set_callback(const std::function<LRESULT(UINT, WPARAM, LPARAM)>& callback)
|
||||
@ -81,6 +63,12 @@ void window::set_callback(const std::function<LRESULT(UINT, WPARAM, LPARAM)>& ca
|
||||
|
||||
LRESULT CALLBACK window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param) const
|
||||
{
|
||||
if (message == WM_DESTROY)
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (message == WM_KILL_WINDOW)
|
||||
{
|
||||
DestroyWindow(*this);
|
||||
@ -97,6 +85,14 @@ LRESULT CALLBACK window::processor(const UINT message, const WPARAM w_param, con
|
||||
|
||||
LRESULT CALLBACK window::static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param)
|
||||
{
|
||||
if (message == WM_CREATE)
|
||||
{
|
||||
auto data = reinterpret_cast<LPCREATESTRUCT>(l_param);
|
||||
SetWindowLongPtrA(hwnd, GWLP_USERDATA, LONG_PTR(data->lpCreateParams));
|
||||
|
||||
reinterpret_cast<window*>(data->lpCreateParams)->handle_ = hwnd;
|
||||
}
|
||||
|
||||
const auto self = reinterpret_cast<window*>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
|
||||
if (self) return self->processor(message, w_param, l_param);
|
||||
|
||||
|
@ -5,23 +5,22 @@
|
||||
class window final
|
||||
{
|
||||
public:
|
||||
window(const std::string& title, int width, int height);
|
||||
window();
|
||||
~window();
|
||||
|
||||
void create(const std::string& title, int width, int height);
|
||||
|
||||
void close();
|
||||
void run() const;
|
||||
|
||||
void clear(const HDC hdc) const;
|
||||
|
||||
void set_callback(const std::function<LRESULT(UINT, WPARAM, LPARAM)>& callback);
|
||||
|
||||
operator HWND() const;
|
||||
|
||||
private:
|
||||
ULONG_PTR token_;
|
||||
WNDCLASSEX wc_{};
|
||||
HWND handle_ = nullptr;
|
||||
std::string classname;
|
||||
std::string classname_;
|
||||
std::function<LRESULT(UINT, WPARAM, LPARAM)> callback_;
|
||||
|
||||
LRESULT CALLBACK processor(UINT message, WPARAM w_param, LPARAM l_param) const;
|
||||
|
@ -55,7 +55,11 @@ int main()
|
||||
utils::nt::module self;
|
||||
|
||||
const auto mode = launcher.run();
|
||||
if (mode == launcher::mode::none) return 0;
|
||||
if (mode == launcher::mode::none)
|
||||
{
|
||||
module_loader::pre_destroy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
loader loader(mode);
|
||||
loader.set_import_resolver([self](const std::string& module, const std::string& function) -> FARPROC
|
||||
@ -81,6 +85,7 @@ int main()
|
||||
catch (std::exception& e)
|
||||
{
|
||||
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||
module_loader::pre_destroy();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,10 @@ void command::add(const std::string& name, const std::function<void(const std::v
|
||||
void command::pre_destroy()
|
||||
{
|
||||
std::lock_guard _(mutex_);
|
||||
callbacks_.clear();
|
||||
if(!callbacks_.empty())
|
||||
{
|
||||
callbacks_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void command::dispatcher()
|
||||
|
@ -1,15 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#define IMAGE_SP 300
|
||||
#define IMAGE_MP 301
|
||||
#define BINARY_SP 302
|
||||
#define BINARY_MP 303
|
||||
#define MAIN_MENU 300
|
||||
#define BINARY_SP 301
|
||||
#define BINARY_MP 302
|
||||
|
||||
#define DW_HEATMAP 304
|
||||
#define DW_MOTD 305
|
||||
#define DW_IMG 306
|
||||
#define DW_WAD 307
|
||||
#define DW_PLAYLIST 308
|
||||
#define DW_CONFIG 309
|
||||
#define DW_IOTD_TXT 310
|
||||
#define DW_IOTD_IMG 311
|
||||
#define DW_HEATMAP 303
|
||||
#define DW_MOTD 304
|
||||
#define DW_IMG 305
|
||||
#define DW_WAD 306
|
||||
#define DW_PLAYLIST 307
|
||||
#define DW_CONFIG 308
|
||||
#define DW_IOTD_TXT 309
|
||||
#define DW_IOTD_IMG 310
|
||||
|
@ -83,8 +83,8 @@ END
|
||||
//
|
||||
|
||||
102 ICON "resources/icon.ico"
|
||||
IMAGE_SP BITMAP "resources/singleplayer.bmp"
|
||||
IMAGE_MP BITMAP "resources/multiplayer.bmp"
|
||||
|
||||
MAIN_MENU RCDATA "resources/main.html"
|
||||
BINARY_SP RCDATA "resources/iw5sp.exe.diff"
|
||||
BINARY_MP RCDATA "resources/iw5mp.exe.diff"
|
||||
|
||||
|
107
src/resources/main.html
Normal file
107
src/resources/main.html
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 169 KiB |
Binary file not shown.
Before Width: | Height: | Size: 169 KiB |
@ -7,6 +7,8 @@
|
||||
#pragma comment(linker, "/section:.main,re")
|
||||
#pragma comment(linker, "/base:0x400000")
|
||||
|
||||
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
|
||||
// Moved to main.cpp to enforce early linking
|
||||
//__declspec(thread) char tls_data[TLS_PAYLOAD_SIZE];
|
||||
|
||||
|
@ -9,9 +9,9 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <windows.h>
|
||||
#include <Windowsx.h>
|
||||
#include <objidl.h>
|
||||
#include <gdiplus.h>
|
||||
#include <mshtml.h>
|
||||
#include <mshtmhst.h>
|
||||
#include <ExDisp.h>
|
||||
#include <WinSock2.h>
|
||||
#include <Ws2tcpip.h>
|
||||
#include <corecrt_io.h>
|
||||
@ -41,6 +41,8 @@
|
||||
#include <patch.h>
|
||||
#include <tomcrypt.h>
|
||||
|
||||
#include <gsl/gsl>
|
||||
|
||||
#pragma comment (lib, "gdiplus.lib")
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user