mirror of
https://github.com/momo5502/hypervisor.git
synced 2026-10-18 00:53:31 +00:00
Remove experiments
This commit is contained in:
1 parent
e77359be93
commit
8510755ea4
25 files changed
-1964
No files matched your search
@@ -1,115 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#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;
|
||||
};
|
||||
@@ -1,51 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
bool html_argument::is_bool() const
|
||||
{
|
||||
if (this->is_empty()) return false;
|
||||
return this->value_->vt == VT_BOOL;
|
||||
}
|
||||
|
||||
std::string html_argument::get_string() const
|
||||
{
|
||||
if (!this->is_string()) return {};
|
||||
std::wstring wide_string(this->value_->bstrVal);
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4244)
|
||||
return std::string(wide_string.begin(), wide_string.end());
|
||||
#pragma warning(pop)
|
||||
}
|
||||
|
||||
int html_argument::get_number() const
|
||||
{
|
||||
if (!this->is_number()) return 0;
|
||||
return this->value_->intVal;
|
||||
}
|
||||
|
||||
bool html_argument::get_bool() const
|
||||
{
|
||||
if (!this->is_bool()) return false;
|
||||
return this->value_->boolVal != FALSE;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
class html_argument final
|
||||
{
|
||||
public:
|
||||
html_argument(VARIANT* val);
|
||||
|
||||
bool is_empty() const;
|
||||
|
||||
bool is_string() const;
|
||||
bool is_number() const;
|
||||
bool is_bool() const;
|
||||
|
||||
std::string get_string() const;
|
||||
int get_number() const;
|
||||
bool get_bool() const;
|
||||
|
||||
private:
|
||||
VARIANT* value_;
|
||||
};
|
||||
@@ -1,67 +0,0 @@
|
||||
#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]);
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4244)
|
||||
std::string name(wide_name.begin(), wide_name.end());
|
||||
#pragma warning(pop)
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#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;
|
||||
};
|
||||
@@ -1,298 +0,0 @@
|
||||
#include "../../std_include.hpp"
|
||||
#include "../../finally.hpp"
|
||||
|
||||
#include "../../utils/nt.hpp"
|
||||
|
||||
#include "html_frame.hpp"
|
||||
|
||||
|
||||
std::atomic<int> html_frame::frame_count_ = 0;
|
||||
|
||||
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 (frame_count_++ == 0 && OleInitialize(nullptr) != S_OK)
|
||||
{
|
||||
throw std::runtime_error("Unable to initialize the OLE library");
|
||||
}
|
||||
|
||||
auto needs_restart = false;
|
||||
needs_restart |= set_browser_feature("FEATURE_BROWSER_EMULATION", 11000);
|
||||
needs_restart |= set_browser_feature("FEATURE_GPU_RENDERING", 1);
|
||||
|
||||
if (needs_restart)
|
||||
{
|
||||
utils::nt::relaunch_self();
|
||||
utils::nt::terminate(0);
|
||||
}
|
||||
}
|
||||
|
||||
html_frame::~html_frame()
|
||||
{
|
||||
if (--frame_count_ <= 0)
|
||||
{
|
||||
frame_count_ = 0;
|
||||
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 (FAILED(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 (FAILED(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 (FAILED(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 (FAILED(
|
||||
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);
|
||||
}
|
||||
|
||||
bool 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 (RegCreateKeyA(HKEY_CURRENT_USER, registry_path.data(), &key) == ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(key);
|
||||
}
|
||||
|
||||
key = nullptr;
|
||||
if (RegOpenKeyExA(
|
||||
HKEY_CURRENT_USER, registry_path.data(), 0,
|
||||
KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
|
||||
{
|
||||
return false; // Error :(
|
||||
}
|
||||
|
||||
const utils::nt::library self;
|
||||
const auto name = self.get_name();
|
||||
|
||||
DWORD type{};
|
||||
auto is_new = true;
|
||||
if (RegQueryValueExA(key, name.data(), nullptr, &type, nullptr, nullptr) == ERROR_SUCCESS)
|
||||
{
|
||||
is_new = false;
|
||||
}
|
||||
|
||||
RegSetValueExA(key, name.data(), 0, REG_DWORD, reinterpret_cast<const BYTE*>(&value), sizeof(value));
|
||||
RegCloseKey(key);
|
||||
|
||||
return is_new;
|
||||
}
|
||||
|
||||
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 _ = utils::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 _ = utils::finally([safe_array]() { SafeArrayDestroy(safe_array); });
|
||||
|
||||
VARIANT* variant = nullptr;
|
||||
if (FAILED(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);
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
#pragma once
|
||||
#include "ole_in_place_frame.hpp"
|
||||
#include "ole_in_place_site.hpp"
|
||||
#include "doc_host_ui_handler.hpp"
|
||||
#include "ole_client_site.hpp"
|
||||
#include "html_dispatch.hpp"
|
||||
#include "html_argument.hpp"
|
||||
|
||||
class html_frame
|
||||
{
|
||||
public:
|
||||
class callback_params final
|
||||
{
|
||||
public:
|
||||
callback_params(DISPPARAMS* params, VARIANT* res);
|
||||
|
||||
std::vector<html_argument> arguments;
|
||||
html_argument result;
|
||||
};
|
||||
|
||||
html_frame();
|
||||
virtual ~html_frame();
|
||||
|
||||
void initialize(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 bool set_browser_feature(const std::string& feature, DWORD value);
|
||||
static void object_deleter(IUnknown* object);
|
||||
|
||||
static std::atomic<int> frame_count_;
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
#include "../../std_include.hpp"
|
||||
#include "html_window.hpp"
|
||||
|
||||
window* html_window::get_window()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
html_frame* html_window::get_html_frame()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
LRESULT html_window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param)
|
||||
{
|
||||
if (message == WM_SIZE)
|
||||
{
|
||||
this->resize(LOWORD(l_param), HIWORD(l_param));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (message == WM_CREATE)
|
||||
{
|
||||
this->initialize(*this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return window::processor(message, w_param, l_param);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
#include "../window.hpp"
|
||||
#include "html_frame.hpp"
|
||||
|
||||
class html_window final : public window, public html_frame
|
||||
{
|
||||
public:
|
||||
~html_window() = default;
|
||||
|
||||
window* get_window();
|
||||
html_frame* get_html_frame();
|
||||
|
||||
private:
|
||||
LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param) override;
|
||||
};
|
||||
@@ -1,77 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
#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;
|
||||
};
|
||||
@@ -1,82 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#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;
|
||||
};
|
||||
@@ -1,105 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
#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;
|
||||
};
|
||||
@@ -1,33 +0,0 @@
|
||||
#include "../std_include.hpp"
|
||||
#include "../resource.hpp"
|
||||
#include "launcher.hpp"
|
||||
|
||||
#include "../utils/nt.hpp"
|
||||
|
||||
launcher::launcher()
|
||||
{
|
||||
this->create_main_menu();
|
||||
}
|
||||
|
||||
void launcher::create_main_menu()
|
||||
{
|
||||
this->main_window_.set_callback(
|
||||
[](window* window, const UINT message, const WPARAM w_param, const LPARAM l_param) -> LRESULT
|
||||
{
|
||||
if (message == WM_CLOSE)
|
||||
{
|
||||
window::close_all();
|
||||
}
|
||||
|
||||
return DefWindowProcA(*window, message, w_param, l_param);
|
||||
});
|
||||
|
||||
this->main_window_.create("S1x", 750, 420);
|
||||
this->main_window_.load_html(utils::nt::load_resource(MAIN_MENU));
|
||||
this->main_window_.show();
|
||||
}
|
||||
|
||||
void launcher::run() const
|
||||
{
|
||||
window::run();
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
#include "html/html_window.hpp"
|
||||
|
||||
class launcher final
|
||||
{
|
||||
public:
|
||||
launcher();
|
||||
|
||||
void run() const;
|
||||
|
||||
private:
|
||||
html_window main_window_;
|
||||
|
||||
void create_main_menu();
|
||||
};
|
||||
@@ -1,208 +0,0 @@
|
||||
#include "../std_include.hpp"
|
||||
#include "window.hpp"
|
||||
|
||||
#include "../utils/nt.hpp"
|
||||
|
||||
std::mutex window::mutex_;
|
||||
std::vector<window*> window::windows_;
|
||||
|
||||
window::window()
|
||||
{
|
||||
ZeroMemory(&this->wc_, sizeof(this->wc_));
|
||||
|
||||
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 = GetModuleHandle(nullptr);
|
||||
this->wc_.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
this->wc_.hIcon = LoadIcon(this->wc_.hInstance, MAKEINTRESOURCE(102));
|
||||
this->wc_.hIconSm = this->wc_.hIcon;
|
||||
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 long flags)
|
||||
{
|
||||
{
|
||||
std::lock_guard _(mutex_);
|
||||
windows_.push_back(this);
|
||||
}
|
||||
|
||||
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(), flags, x, y, width, height, nullptr,
|
||||
nullptr, this->wc_.hInstance, this);
|
||||
|
||||
SendMessageA(this->handle_, WM_DPICHANGED, 0, 0);
|
||||
}
|
||||
|
||||
window::~window()
|
||||
{
|
||||
this->close();
|
||||
UnregisterClass(this->wc_.lpszClassName, this->wc_.hInstance);
|
||||
}
|
||||
|
||||
void window::close()
|
||||
{
|
||||
if (!this->handle_) return;
|
||||
|
||||
SendMessageA(this->handle_, WM_KILL_WINDOW, NULL, NULL);
|
||||
this->handle_ = nullptr;
|
||||
}
|
||||
|
||||
void window::run()
|
||||
{
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, nullptr, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void window::close_all()
|
||||
{
|
||||
std::unique_lock lock(mutex_);
|
||||
auto window_list = windows_;
|
||||
lock.unlock();
|
||||
|
||||
const auto current_thread_id = GetCurrentThreadId();
|
||||
for (auto& window : window_list)
|
||||
{
|
||||
const auto thread_id = GetWindowThreadProcessId(*window, nullptr);
|
||||
|
||||
if (thread_id == current_thread_id)
|
||||
{
|
||||
window->close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void window::remove_window(const window* window)
|
||||
{
|
||||
std::lock_guard _(mutex_);
|
||||
|
||||
for (auto i = windows_.begin(); i != windows_.end(); ++i)
|
||||
{
|
||||
if (*i == window)
|
||||
{
|
||||
windows_.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int window::get_window_count()
|
||||
{
|
||||
std::lock_guard _(mutex_);
|
||||
|
||||
auto count = 0;
|
||||
const auto current_thread_id = GetCurrentThreadId();
|
||||
|
||||
for (const auto& window : windows_)
|
||||
{
|
||||
const auto thread_id = GetWindowThreadProcessId(*window, nullptr);
|
||||
|
||||
if (thread_id == current_thread_id)
|
||||
{
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void window::show() const
|
||||
{
|
||||
ShowWindow(this->handle_, SW_SHOW);
|
||||
UpdateWindow(this->handle_);
|
||||
}
|
||||
|
||||
void window::hide() const
|
||||
{
|
||||
ShowWindow(this->handle_, SW_HIDE);
|
||||
UpdateWindow(this->handle_);
|
||||
}
|
||||
|
||||
void window::set_callback(const std::function<LRESULT(window*, UINT, WPARAM, LPARAM)>& callback)
|
||||
{
|
||||
this->callback_ = callback;
|
||||
}
|
||||
|
||||
LRESULT window::processor(const UINT message, const WPARAM w_param, const LPARAM l_param)
|
||||
{
|
||||
if (message == WM_DPICHANGED)
|
||||
{
|
||||
const utils::nt::library user32{"user32.dll"};
|
||||
const auto get_dpi = user32 ? user32.get_proc<UINT(WINAPI *)(HWND)>("GetDpiForWindow") : nullptr;
|
||||
|
||||
if (get_dpi)
|
||||
{
|
||||
const auto dpi = get_dpi(*this);
|
||||
if (dpi != this->last_dpi_)
|
||||
{
|
||||
RECT rect;
|
||||
GetWindowRect(*this, &rect);
|
||||
|
||||
const auto scale = dpi * 1.0 / this->last_dpi_;
|
||||
this->last_dpi_ = dpi;
|
||||
|
||||
const auto width = rect.right - rect.left;
|
||||
const auto height = rect.bottom - rect.top;
|
||||
|
||||
MoveWindow(*this, rect.left, rect.top, int(width * scale), int(height * scale), TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (message == WM_DESTROY)
|
||||
{
|
||||
remove_window(this);
|
||||
|
||||
if (get_window_count() == 0)
|
||||
{
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (message == WM_KILL_WINDOW)
|
||||
{
|
||||
DestroyWindow(*this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (this->callback_)
|
||||
{
|
||||
return this->callback_(this, message, w_param, l_param);
|
||||
}
|
||||
|
||||
return DefWindowProc(*this, message, w_param, l_param);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
static_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);
|
||||
|
||||
return DefWindowProc(hwnd, message, w_param, l_param);
|
||||
}
|
||||
|
||||
|
||||
window::operator HWND() const
|
||||
{
|
||||
return this->handle_;
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define WM_KILL_WINDOW (WM_USER+0)
|
||||
|
||||
class window
|
||||
{
|
||||
public:
|
||||
window();
|
||||
virtual ~window();
|
||||
|
||||
void create(const std::string& title, int width, int height,
|
||||
long flags = (WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX)));
|
||||
|
||||
void close();
|
||||
|
||||
void show() const;
|
||||
void hide() const;
|
||||
|
||||
void set_callback(const std::function<LRESULT(window*, UINT, WPARAM, LPARAM)>& callback);
|
||||
|
||||
operator HWND() const;
|
||||
|
||||
static void run();
|
||||
static void close_all();
|
||||
|
||||
protected:
|
||||
virtual LRESULT processor(UINT message, WPARAM w_param, LPARAM l_param);
|
||||
|
||||
private:
|
||||
uint32_t last_dpi_ = 96;
|
||||
|
||||
WNDCLASSEX wc_{};
|
||||
HWND handle_ = nullptr;
|
||||
std::string classname_;
|
||||
std::function<LRESULT(window*, UINT, WPARAM, LPARAM)> callback_;
|
||||
|
||||
static LRESULT CALLBACK static_processor(HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param);
|
||||
|
||||
static std::mutex mutex_;
|
||||
static std::vector<window*> windows_;
|
||||
|
||||
static void remove_window(const window* window);
|
||||
static int get_window_count();
|
||||
};
|
||||
@@ -11,8 +11,6 @@
|
||||
|
||||
#include "resource.hpp"
|
||||
|
||||
#include "launcher/launcher.hpp"
|
||||
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
void patch_data(const driver_device& driver_device, const uint32_t pid, const uint64_t addr, const uint8_t* buffer,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define DRIVER_BINARY 300
|
||||
#define MAIN_MENU 301
|
||||
@@ -85,7 +85,6 @@ END
|
||||
|
||||
102 ICON "resources/icon.ico"
|
||||
DRIVER_BINARY RCDATA DRIVER_FILE
|
||||
MAIN_MENU RCDATA "resources/main.html"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,574 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
||||
<title>S1x</title>
|
||||
|
||||
<style>
|
||||
* {
|
||||
user-select: none;
|
||||
-ms-user-select: none;
|
||||
cursor: default;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
-ms-overflow-style: none;
|
||||
margin: 0;
|
||||
background: url(data:image/jpeg;base64,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 truncated
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
color: #222;
|
||||
font-family: "Segoe UI Light", "Segoe UI", "Lucida Sans", Arial, sans-serif;
|
||||
font-style: normal;
|
||||
font-weight: lighter;
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1 0 auto;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
p {
|
||||
font-weight: 200;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
p a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
p a:hover {
|
||||
color: #ffc320;
|
||||
}
|
||||
|
||||
nav {
|
||||
padding: 0px;
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;
|
||||
border-bottom: 1px solid;
|
||||
border-color: rgba(34, 34, 34, 0.25);
|
||||
}
|
||||
|
||||
#brand {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#brand i {
|
||||
font-size: 40px;
|
||||
width: 64px;
|
||||
vertical-align: top;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#brand span {
|
||||
font-size: 27px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
nav ul li {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
nav .nav-link {
|
||||
display: inline-block;
|
||||
font-size: 1.3em;
|
||||
color: #222;
|
||||
text-transform: uppercase;
|
||||
padding: 0 10px;
|
||||
letter-spacing: 1px;
|
||||
padding: 10px 0px;
|
||||
margin-right: 15px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
nav .nav-link.active {
|
||||
border-bottom: 1px solid #222;
|
||||
}
|
||||
|
||||
nav .nav-link:hover,
|
||||
nav .nav-link.active {
|
||||
text-shadow: 0px 0px 8px rgba(34, 34, 34, 0.5);
|
||||
}
|
||||
|
||||
nav .nav-link:first-child {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
nav .nav-link.not-active {
|
||||
color: rgba(34, 34, 34, 0.25);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.side-nav-container {
|
||||
min-width: 64px;
|
||||
border-right: 1px solid;
|
||||
border-color: rgba(34, 34, 34, 0.25);
|
||||
}
|
||||
|
||||
.side-nav {
|
||||
color: rgba(34, 34, 34, 0.7);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
padding-top: 78px;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
max-height: 100vh;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.side-nav i {
|
||||
padding: 10px 0;
|
||||
transition: all .1s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.side-nav i:hover {
|
||||
color: rgba(34, 34, 34, 1);
|
||||
}
|
||||
|
||||
.side-nav-bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
padding: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 80%;
|
||||
padding: 0 15px;
|
||||
margin-top: 25px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.container.full {
|
||||
width: 100%;
|
||||
/*padding: 0px;*/
|
||||
}
|
||||
|
||||
.container h1,
|
||||
.container h2,
|
||||
.container h3 {
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 5px;
|
||||
margin-top: 0;
|
||||
letter-spacing: 1px;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
.container h3 {
|
||||
margin-bottom: 0px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.full-row .card {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
.full-row .card.small {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.card {
|
||||
display: flex;
|
||||
width: 25%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.card.small {
|
||||
width: 12.5%;
|
||||
}
|
||||
|
||||
.card.full {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media(max-width: 1341px) {
|
||||
.card {
|
||||
width: 50%;
|
||||
}
|
||||
.card.small {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
.card .card-container {
|
||||
width: 100%;
|
||||
/*margin: 5px;
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;*/
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.5);
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
/*.card:hover .card-container {
|
||||
box-shadow: 0px 0px 5px 0px rgba(0,0,0,0);
|
||||
}*/
|
||||
|
||||
.card .card-img {
|
||||
overflow: hidden;
|
||||
height: 185px;
|
||||
}
|
||||
|
||||
.card img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
z-index: 1;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.card.full .card-img {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.card .card-content {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
min-height: 88px;
|
||||
padding: 10px 20px;
|
||||
padding-bottom: 42px;
|
||||
background-color: rgba(34, 34, 34, 0.1);
|
||||
color: #222;
|
||||
z-index: 5;
|
||||
transition: all 0.5s ease;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.card:hover .card-content {
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
/*.card:hover img {
|
||||
transform: scale(1.1);
|
||||
}*/
|
||||
|
||||
.card .card-content span {
|
||||
font-size: 1.7em;
|
||||
font-weight: 500;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.card .card-content p {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.card:hover .card-action {
|
||||
opacity: 1;
|
||||
bottom: 0;
|
||||
border-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.card .card-action {
|
||||
/*opacity: 0;*/
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
border-top: 1px solid;
|
||||
border-color: rgba(34, 34, 34, 0.25);
|
||||
text-transform: uppercase;
|
||||
padding: 7px;
|
||||
box-sizing: border-box;
|
||||
font-weight: 500;
|
||||
transition: opacity bottom 0.5s;
|
||||
}
|
||||
|
||||
.card .card-action.hidden-action {
|
||||
bottom: -43px;
|
||||
transition: bottom 0.5s ease;
|
||||
border-color: rgba(0, 0, 0, 0.0);
|
||||
}
|
||||
|
||||
.card:hover .card-action.hidden-action {
|
||||
bottom: 0;
|
||||
border-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
a.btn {
|
||||
display: inline-block;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
border: 1px solid rgba(34, 34, 34, 0.42);
|
||||
color: #222;
|
||||
font-weight: 600;
|
||||
padding: 10px 100px;
|
||||
border-radius: 1px;
|
||||
transition: all 0.5s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a.btn i {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
a.btn.highlight {
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
a.btn:hover {
|
||||
background: white;
|
||||
color: black;
|
||||
box-shadow: 0px 0px 10px rgba(34, 34, 34, 0.42);
|
||||
}
|
||||
|
||||
a.btn.small {
|
||||
padding: 10px 50px;
|
||||
}
|
||||
|
||||
div.menus>div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.menus>div.active {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.progress {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
padding: 0;
|
||||
border-radius: 0px;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(34, 34, 34, 0.25);
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.progress>.bar {
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
background: rgb(121, 121, 121);
|
||||
background: linear-gradient(145deg, rgba(121, 121, 121, 1) 0%, rgba(0, 212, 255, 1) 100%);
|
||||
transition: all 0.2s linear;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<main>
|
||||
<div class="main-container">
|
||||
<nav class="sticky">
|
||||
<ul>
|
||||
<li>
|
||||
<a class="nav-link _play" onClick="showMenu('play')">
|
||||
Play
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="nav-link _survival" onClick="showMenu('survival')">
|
||||
Survival
|
||||
</a>
|
||||
</li>
|
||||
<!--<li>
|
||||
<a class="nav-link _settings" onClick="showMenu('settings')">
|
||||
Settings
|
||||
</a>
|
||||
</li>-->
|
||||
<li>
|
||||
<a class="nav-link _about" onClick="showMenu('about')">
|
||||
About
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div class="menus">
|
||||
|
||||
<div class="_play">
|
||||
<div class="container full full-row">
|
||||
<div class="card" onClick="window.external.selectMode(1)">
|
||||
<div class="card-container">
|
||||
<div class="card-img">
|
||||
<img src="data:image/png;base64,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 truncated
|
||||
/>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<span>Singleplayer</span>
|
||||
<a>
|
||||
<div class="card-action hidden-action">
|
||||
Launch
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="spacer" style="width: 25px"></div>
|
||||
|
||||
<div class="card" onClick="window.external.selectMode(2)">
|
||||
<div class="card-container">
|
||||
<div class="card-img">
|
||||
<img src="data:image/png;base64,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 truncated
|
||||
/>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<span>Multiplayer</span>
|
||||
<a>
|
||||
<div class="card-action hidden-action">
|
||||
Launch
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="_survival">
|
||||
<div class="container full full-row">
|
||||
<div class="card" onClick="window.external.selectMode(4)">
|
||||
<div class="card-container">
|
||||
<div class="card-img">
|
||||
<img src="data:image/png;base64,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 truncated
|
||||
/>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<span>Survival</span>
|
||||
<a>
|
||||
<div class="card-action hidden-action">
|
||||
Launch
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="spacer" style="width: 25px"></div>
|
||||
|
||||
<div class="card" onClick="window.external.selectMode(5)">
|
||||
<div class="card-container">
|
||||
<div class="card-img">
|
||||
<img src="data:image/png;base64,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 truncated
|
||||
/>
|
||||
</div>
|
||||
<div class="card-content">
|
||||
<span>Zombies</span>
|
||||
<a>
|
||||
<div class="card-action hidden-action">
|
||||
Launch
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="_settings">
|
||||
|
||||
<div class="container full full-row">
|
||||
<h2>No settings yet!</h2>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="_about">
|
||||
|
||||
<div class="container full full-row">
|
||||
<div style="text-align: center; width: 100%;">
|
||||
<h1>X Labs: S1x</h1>
|
||||
<p>Developed by <a onClick="window.external.openUrl('https://xlabs.dev');">X Labs</a>.<br>Big thanks to all the contributors and supporters.</p>
|
||||
<p>
|
||||
Join us on <a onClick="window.external.openUrl('https://discord.gg/sKeVmR3');">Discord</a>.
|
||||
<br>
|
||||
Support us on <a onClick="window.external.openUrl('https://www.patreon.com/xlabsproject');">Patreon</a>.<br>
|
||||
Follow the project on <a onClick="window.external.openUrl('https://github.com/XLabsProject/s1x-client');">GitHub</a> or <a onClick="window.external.openUrl('https://twitter.com/XLabsProject');">Twitter</a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="_update">
|
||||
|
||||
<div class="container full full-row">
|
||||
<div class="progress">
|
||||
<div class="bar">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
function activateElement(name, elements) {
|
||||
for (var i = 0; i < elements.length; ++i) {
|
||||
var element = elements[i];
|
||||
var classList = element.classList;
|
||||
var show = false;
|
||||
|
||||
for (var j = 0; j < classList.length; ++j) {
|
||||
if (classList[j] == '_' + name) {
|
||||
show = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (show) {
|
||||
classList.add('active');
|
||||
} else {
|
||||
classList.remove('active');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function showMenu(menu) {
|
||||
var menus = document.querySelectorAll("div.menus>div");
|
||||
var buttons = document.querySelectorAll("nav a.nav-link");
|
||||
|
||||
activateElement(menu, menus);
|
||||
activateElement(menu, buttons);
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
showMenu("play");
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -10,7 +10,4 @@
|
||||
#include <Shlwapi.h>
|
||||
#include <ShlObj.h>
|
||||
|
||||
#include <MsHTML.h>
|
||||
#include <MsHtmHst.h>
|
||||
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
Reference in new issue
Block a user