318 lines
10 KiB
C++
318 lines
10 KiB
C++
// dllmain.cpp : Defines the entry point for the DLL application.
|
|
#include "pch.h"
|
|
#include <combaseapi.h>
|
|
#include <commctrl.h>
|
|
#include <stdlib.h>
|
|
#include <string>
|
|
#include <tchar.h>
|
|
#include <vector>
|
|
#include <wil/com.h>
|
|
#include <wrl.h>
|
|
#include "libwebview2.h"
|
|
#include "WebView2.h"
|
|
#pragma comment(lib, "comctl32.lib")
|
|
|
|
#define WM_WEBV_USER (WM_APP + 0)
|
|
#define WM_JSMSG (WM_APP + 1)
|
|
|
|
|
|
#define G_BUFFER_SIZE (1024 * 100)
|
|
static TCHAR g_buffer[G_BUFFER_SIZE] = { 0, };
|
|
static webview2_callback_t g_call_back = NULL;
|
|
void set_g_callback(webview2_callback_t f)
|
|
{
|
|
g_call_back = f;
|
|
}
|
|
|
|
const TCHAR* strClassName = TEXT("CREATE_WEBVIEW2");
|
|
using namespace Microsoft::WRL;
|
|
struct windowobj {
|
|
HWND hwnd = nullptr;
|
|
wil::com_ptr<ICoreWebView2> webviewWindow = nullptr;
|
|
wil::com_ptr<ICoreWebView2Controller> webviewController = nullptr;
|
|
wil::com_ptr<ICoreWebView2_2> webView2 = nullptr;
|
|
std::wstring startup_script = L"";
|
|
int createid = -1;
|
|
};
|
|
|
|
HINSTANCE hInst;
|
|
int g_randomid = 0;
|
|
std::wstring g_startup_script = L"";
|
|
std::vector<windowobj> m_windowobjs;
|
|
|
|
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
|
{
|
|
switch (ul_reason_for_call) {
|
|
case DLL_PROCESS_ATTACH:
|
|
case DLL_THREAD_ATTACH:
|
|
case DLL_THREAD_DETACH:
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
void create_randomid()
|
|
{
|
|
g_randomid = 0;
|
|
}
|
|
int get_current_windowobj_idx(HWND hwnd)
|
|
{
|
|
for (int i = 0; i < m_windowobjs.size(); i++) {
|
|
if (m_windowobjs[i].hwnd == hwnd) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
void load_url(HWND hWnd, const TCHAR* url)
|
|
{
|
|
int idx = get_current_windowobj_idx(hWnd);
|
|
m_windowobjs[idx].webviewWindow->Navigate(url);
|
|
|
|
|
|
}
|
|
void resize_webview(HWND hWnd)
|
|
{
|
|
int idx = get_current_windowobj_idx(hWnd);
|
|
if (idx == -1)
|
|
return;
|
|
if (m_windowobjs[idx].webviewController != nullptr) {
|
|
RECT bounds;
|
|
GetClientRect(m_windowobjs[idx].hwnd, &bounds);
|
|
m_windowobjs[idx].webviewController->put_Bounds(bounds);
|
|
};
|
|
}
|
|
void set_copydata(HWND hWnd, std::wstring s, int wmmsg)
|
|
{
|
|
DWORD bytes = (s.size()+10) * sizeof(wchar_t);
|
|
TCHAR* buffer = new TCHAR[s.length() + 1];
|
|
wcscpy_s(buffer, s.length() + 1, s.c_str());
|
|
|
|
if (g_call_back != NULL) {
|
|
g_call_back(buffer);
|
|
}
|
|
|
|
COPYDATASTRUCT data_to_send = { 0 };
|
|
data_to_send.dwData = g_randomid;
|
|
data_to_send.cbData = bytes;
|
|
data_to_send.lpData = buffer;
|
|
SendMessage(hWnd, wmmsg, 0, (LPARAM)&data_to_send);
|
|
delete[] buffer;
|
|
}
|
|
|
|
LPTSTR get_webview2_version()
|
|
{
|
|
memset(g_buffer, 0, sizeof(TCHAR) * G_BUFFER_SIZE);
|
|
LPWSTR version = NULL;
|
|
GetAvailableCoreWebView2BrowserVersionString(nullptr, &version);
|
|
|
|
if (version != NULL) {
|
|
wcscpy_s(g_buffer, version);
|
|
CoTaskMemFree(version);
|
|
}
|
|
|
|
return g_buffer;
|
|
}
|
|
|
|
LPTSTR get_udf_path()
|
|
{
|
|
memset(g_buffer, 0, sizeof(TCHAR) * G_BUFFER_SIZE);
|
|
DWORD path_len = ::GetTempPathW(G_BUFFER_SIZE, g_buffer);
|
|
size_t remaining_size = G_BUFFER_SIZE - path_len;
|
|
|
|
// wcscpy_s는 안전한 문자열 복사 함수입니다.
|
|
wcscpy_s(&g_buffer[path_len], remaining_size, L"mapview\\");
|
|
|
|
// 4. 'mapview' 폴더가 있는지 확인하고 없으면 생성합니다.
|
|
DWORD attributes = ::GetFileAttributesW(g_buffer);
|
|
if (attributes == INVALID_FILE_ATTRIBUTES || !(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
// 폴더가 존재하지 않으면 생성
|
|
if (!::CreateDirectoryW(g_buffer, nullptr)) {
|
|
// 폴더 생성 실패 시 nullptr 반환
|
|
return nullptr;
|
|
}
|
|
}
|
|
return g_buffer;
|
|
}
|
|
LPTSTR get_msg_string(LPARAM lp)
|
|
{
|
|
COPYDATASTRUCT* copy_data_structure = { 0 };
|
|
copy_data_structure = (COPYDATASTRUCT*)lp;
|
|
LPCWSTR arguments = (LPCWSTR)copy_data_structure->lpData;
|
|
return (LPTSTR)arguments;
|
|
}
|
|
void set_jsmsg_to_copydata(HWND hWnd, std::wstring s)
|
|
{
|
|
set_copydata(hWnd, s, WM_JSMSG);
|
|
}
|
|
HWND get_main_hwnd(int createid)
|
|
{
|
|
for (int i = 0; i < m_windowobjs.size(); i++) {
|
|
if (m_windowobjs[i].createid == createid) {
|
|
return m_windowobjs[i].hwnd;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
void close_window(HWND hWnd)
|
|
{
|
|
PostMessage(hWnd, WM_CLOSE, 0, 0);
|
|
}
|
|
void reload_page(HWND hWnd)
|
|
{
|
|
int idx = get_current_windowobj_idx(hWnd);
|
|
m_windowobjs[idx].webviewWindow->Reload();
|
|
}
|
|
void set_startup_script(HWND hWnd, const TCHAR* script)
|
|
{
|
|
int idx = get_current_windowobj_idx(hWnd);
|
|
m_windowobjs[idx].startup_script = script;
|
|
}
|
|
void set_global_startup_script(const TCHAR* script)
|
|
{
|
|
g_startup_script = script;
|
|
}
|
|
void exec_js(HWND hWnd, const TCHAR* script)
|
|
{
|
|
int idx = get_current_windowobj_idx(hWnd);
|
|
|
|
m_windowobjs[idx].webviewWindow->ExecuteScript(script,
|
|
Callback<ICoreWebView2ExecuteScriptCompletedHandler>([hWnd](HRESULT error, PCWSTR result) -> HRESULT {
|
|
|
|
std::wstring msgstr = L"{\"msg\"\:\"exec_js_done\"}";
|
|
set_jsmsg_to_copydata(hWnd, msgstr);
|
|
return S_OK;
|
|
}).Get());
|
|
}
|
|
void send_json(HWND hWnd, const TCHAR* jsonstr)
|
|
{
|
|
int idx = get_current_windowobj_idx(hWnd);
|
|
m_windowobjs[idx].webviewWindow->PostWebMessageAsJson(jsonstr);
|
|
}
|
|
void close_window_event(HWND hWnd)
|
|
{
|
|
int idx = get_current_windowobj_idx(hWnd);
|
|
m_windowobjs.erase(m_windowobjs.begin() + idx);
|
|
if (m_windowobjs.size() < 1) {
|
|
PostQuitMessage(0);
|
|
}
|
|
}
|
|
void CHECK_FAILURE(HRESULT hr)
|
|
{
|
|
if (FAILED(hr)) {
|
|
std::wstring message;
|
|
message = std::wstring(L"Something went wrong.");
|
|
MessageBoxW(nullptr, message.c_str(), nullptr, MB_OK);
|
|
}
|
|
}
|
|
|
|
void webview_events(HWND hWnd)
|
|
{
|
|
int idx = get_current_windowobj_idx(hWnd);
|
|
EventRegistrationToken token;
|
|
m_windowobjs[idx].webviewWindow->add_WebMessageReceived(
|
|
Callback<ICoreWebView2WebMessageReceivedEventHandler>(
|
|
[hWnd](ICoreWebView2* webview, ICoreWebView2WebMessageReceivedEventArgs* args) -> HRESULT {
|
|
wil::unique_cotaskmem_string source;
|
|
CHECK_FAILURE(args->get_Source(&source));
|
|
wil::unique_cotaskmem_string webMessageAsJson;
|
|
CHECK_FAILURE(args->get_WebMessageAsJson(&webMessageAsJson));
|
|
Sleep(200);
|
|
set_jsmsg_to_copydata(hWnd, webMessageAsJson.get());
|
|
return S_OK;
|
|
})
|
|
.Get(),
|
|
&token);
|
|
|
|
std::wstring script = g_startup_script;
|
|
if (4 < m_windowobjs[idx].startup_script.length())
|
|
script = m_windowobjs[idx].startup_script;
|
|
|
|
m_windowobjs[idx].webviewWindow->AddScriptToExecuteOnDocumentCreated(script.c_str(),
|
|
Callback<ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler>(
|
|
[](HRESULT error, PCWSTR id) -> HRESULT {
|
|
return S_OK;
|
|
})
|
|
.Get());
|
|
EventRegistrationToken m_DOMContentLoadedToken;
|
|
wil::com_ptr<ICoreWebView2_2> webView2;
|
|
m_windowobjs[idx].webviewWindow->QueryInterface(IID_PPV_ARGS(&webView2));
|
|
m_windowobjs[idx].webView2 = webView2;
|
|
webView2->add_DOMContentLoaded(
|
|
Callback<ICoreWebView2DOMContentLoadedEventHandler>(
|
|
[hWnd](ICoreWebView2* sender, ICoreWebView2DOMContentLoadedEventArgs* args) -> HRESULT {
|
|
std::wstring msgstr = L"{\"msg\"\:\"DOMContentLoaded\"}";
|
|
set_jsmsg_to_copydata(hWnd, msgstr);
|
|
return S_OK;
|
|
})
|
|
.Get(),
|
|
&m_DOMContentLoadedToken);
|
|
}
|
|
void init_webview2(HWND hWnd, std::wstring url2str)
|
|
{
|
|
//WCHAR path[MAX_PATH] = { 0, };
|
|
//::GetTempPathW(MAX_PATH, path);
|
|
|
|
|
|
CreateCoreWebView2EnvironmentWithOptions(nullptr, get_udf_path(), nullptr,
|
|
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
|
|
[hWnd, url2str](HRESULT result, ICoreWebView2Environment* env) -> HRESULT {
|
|
env->CreateCoreWebView2Controller(hWnd,
|
|
Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
|
|
[hWnd, url2str](HRESULT result, ICoreWebView2Controller* controller) -> HRESULT {
|
|
wil::com_ptr<ICoreWebView2> webviewWindow;
|
|
if (controller != nullptr) {
|
|
auto webviewController = controller;
|
|
webviewController->get_CoreWebView2(&webviewWindow);
|
|
int idx = get_current_windowobj_idx(hWnd);
|
|
m_windowobjs[idx].webviewController = controller;
|
|
m_windowobjs[idx].webviewWindow = webviewWindow;
|
|
|
|
wil::com_ptr<ICoreWebView2Controller4> controller4 =
|
|
m_windowobjs[idx].webviewController.try_query<ICoreWebView2Controller4>();
|
|
if (controller4 != nullptr) {
|
|
controller4->put_AllowExternalDrop(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
ICoreWebView2Settings* Settings;
|
|
webviewWindow->get_Settings(&Settings);
|
|
Settings->put_IsScriptEnabled(TRUE);
|
|
Settings->put_AreDefaultScriptDialogsEnabled(TRUE);
|
|
Settings->put_IsWebMessageEnabled(TRUE);
|
|
Settings->put_AreDefaultContextMenusEnabled(FALSE);
|
|
Settings->put_IsZoomControlEnabled(FALSE);
|
|
Settings->put_IsStatusBarEnabled(FALSE);
|
|
|
|
resize_webview(hWnd);
|
|
webview_events(hWnd);
|
|
load_url(hWnd, url2str.c_str());
|
|
|
|
return S_OK;
|
|
})
|
|
.Get());
|
|
return S_OK;
|
|
})
|
|
.Get());
|
|
}
|
|
bool create_webview2(HWND hWnd, int createid, const TCHAR* url)
|
|
{
|
|
if (hWnd == NULL)
|
|
return false;
|
|
|
|
windowobj wobj;
|
|
wobj.hwnd = hWnd;
|
|
wobj.webviewWindow = nullptr;
|
|
wobj.webviewController = nullptr;
|
|
wobj.webView2 = nullptr;
|
|
wobj.startup_script = L"";
|
|
wobj.createid = createid;
|
|
m_windowobjs.push_back(wobj);
|
|
|
|
std::wstring url2str = url;
|
|
init_webview2(hWnd, url2str);
|
|
return true;
|
|
}
|
|
|