refactor
This commit is contained in:
1 parent
f9f277c784
commit
efa57fe37f
20 files changed
+605
-582
No files matched your search
@@ -3,4 +3,4 @@ BasedOnStyle: Microsoft
|
||||
IndentWidth: 4
|
||||
|
||||
SortIncludes: true
|
||||
ColumnLimit: 80
|
||||
ColumnLimit: 120
|
||||
+3
-2
@@ -4,8 +4,9 @@ CompileFlags:
|
||||
-D_UNICODE,
|
||||
-DFANY_DEBUG,
|
||||
"-std=c++17",
|
||||
"-IC:\\Users\\SonnyCalcr\\EDisk\\CppCodes\\Win32Codes\\DirectWriteExperiment\\includes", # you should replace this to your own include path of this project
|
||||
"-IC:\\Users\\SonnyCalcr\\EDisk\\CppCodes\\Win32Codes\\DirectWriteExperiment\\fmt\\include", # you should replace this to your own include path of fmt
|
||||
"-IC:\\Users\\SonnyCalcr\\EDisk\\CppCodes\\IMECodes\\FanIME-UI\\includes",
|
||||
"-IC:\\Users\\SonnyCalcr\\EDisk\\CppCodes\\IMECodes\\FanIME-UI\\fmt\\include",
|
||||
"-IC:\\Users\\SonnyCalcr\\EDisk\\CppCodes\\IMECodes\\FanIME-UI\\src",
|
||||
"-IC:\\Users\\SonnyCalcr\\.nuget\\packages\\microsoft.web.webview2\\1.0.3124.44\\build\\native\\include",
|
||||
"-IC:\\Users\\SonnyCalcr\\.nuget\\packages\\microsoft.windows.implementationlibrary\\1.0.240803.1\\include",
|
||||
-Wno-microsoft-goto,
|
||||
|
||||
+18
-5
@@ -4,11 +4,16 @@ set(PROJECT_NAME "fanimeui")
|
||||
|
||||
project(${PROJECT_NAME} VERSION 1.0)
|
||||
|
||||
set(Boost_ROOT "C:/Users/SonnyCalcr/scoop/apps/boost/1.87.0")
|
||||
set (Boost_USE_STATIC_LIBS ON)
|
||||
find_package(Boost REQUIRED COMPONENTS locale)
|
||||
|
||||
add_subdirectory(fmt)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
add_definitions(
|
||||
/D_UNICODE=1
|
||||
@@ -20,14 +25,22 @@ add_definitions(
|
||||
# )
|
||||
|
||||
include_directories("./src/")
|
||||
include_directories("./src/webview2")
|
||||
|
||||
set(MY_EXECUTABLE_NAME "fanimeui")
|
||||
|
||||
set(SRC_FILES
|
||||
"./src/webview2/webview2_ui.cpp"
|
||||
"./src/webview2/webview2_ui.h"
|
||||
"src/MainWindow.cpp"
|
||||
"./src/defines/defines.h"
|
||||
"./src/log/fanylog.cpp"
|
||||
"./src/log/fanylog.h"
|
||||
"./src/utils/webview_utils.cpp"
|
||||
"./src/utils/webview_utils.h"
|
||||
"./src/utils/common_utils.cpp"
|
||||
"./src/utils/common_utils.h"
|
||||
"./src/webview2/candidate_window_webview2.cpp"
|
||||
"./src/webview2/candidate_window_webview2.h"
|
||||
"./src/window/candidate_window.cpp"
|
||||
"./src/window/candidate_window.h"
|
||||
"./src/main.cpp"
|
||||
)
|
||||
|
||||
add_executable(${MY_EXECUTABLE_NAME} WIN32
|
||||
@@ -38,4 +51,4 @@ set_target_properties(${PROJECT_NAME} PROPERTIES VS_GLOBAL_WebView2LoaderPrefere
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES VS_USER_PROPS "${CMAKE_SOURCE_DIR}/FanIME_UI.props")
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES VS_PACKAGE_REFERENCES "Microsoft.Web.WebView2_1.0.3124.44;Microsoft.Windows.ImplementationLibrary_1.0.240803.1")
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} fmt::fmt)
|
||||
target_link_libraries(${PROJECT_NAME} fmt::fmt Boost::locale)
|
||||
@@ -0,0 +1,55 @@
|
||||
<div class="container">
|
||||
<!--0Anchor-->
|
||||
<div class="row pinyin">
|
||||
<div class="text">{0}</div>
|
||||
</div>
|
||||
<!--1Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand first">
|
||||
<div class="text">{1}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--2Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{2}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--3Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{3}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--4Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{4}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--5Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{5}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--6Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{6}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--7Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{7}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--8Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{8}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--9Anchor-->
|
||||
</div>
|
||||
@@ -0,0 +1,55 @@
|
||||
<div class="container">
|
||||
<!--0Anchor-->
|
||||
<div class="row pinyin">
|
||||
<div class="text">{0}</div>
|
||||
</div>
|
||||
<!--1Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand first">
|
||||
<div class="text">{1}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--2Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{2}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--3Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{3}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--4Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{4}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--5Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{5}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--6Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{6}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--7Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{7}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--8Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{8}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--9Anchor-->
|
||||
</div>
|
||||
File renamed without changes.
@@ -1,574 +0,0 @@
|
||||
#include "WebView2.h"
|
||||
#include "fmt/core.h"
|
||||
#include "fmt/xchar.h"
|
||||
#include <chrono>
|
||||
#include <dwmapi.h>
|
||||
#include <fstream>
|
||||
#include <intsafe.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <synchapi.h>
|
||||
#include <tchar.h>
|
||||
#include <vector>
|
||||
#include <windows.h>
|
||||
#include <winnt.h>
|
||||
#include <winuser.h>
|
||||
#include <wrl.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
//
|
||||
// Message define
|
||||
//
|
||||
UINT WM_SHOW_MAIN_WINDOW;
|
||||
UINT WM_HIDE_MAIN_WINDOW;
|
||||
UINT WM_MOVE_CANDIDATE_WINDOW;
|
||||
|
||||
static TCHAR szWindowClass[] = _T("global_candidate_window");
|
||||
static TCHAR szTitle[] = _T("Global Candidate Window");
|
||||
|
||||
std::wstring candStr = L"";
|
||||
|
||||
static std::wstring HTMLString = LR"(
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Vertical Candidate Window</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.container {
|
||||
/* margin-top: 50px;
|
||||
margin-left: 50px; */
|
||||
margin-top: 0px;
|
||||
margin-left: 0px;
|
||||
background-color: #202020;
|
||||
padding: 2px;
|
||||
border-radius: 6px;
|
||||
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.5);
|
||||
width: 100px;
|
||||
user-select: none;
|
||||
border: 2px solid #9b9b9b2e;
|
||||
}
|
||||
|
||||
.row {
|
||||
justify-content: space-between;
|
||||
padding: 2px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.cand:hover {
|
||||
border-radius: 6px;
|
||||
background-color: #414141;
|
||||
}
|
||||
|
||||
.row-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* .cand:hover::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
height: 16px;
|
||||
width: 3px;
|
||||
background: linear-gradient(to bottom, #ff7eb3, #ff758c, #ff5a5f);
|
||||
border-radius: 8px;
|
||||
} */
|
||||
|
||||
.first {
|
||||
background-color: #3e3e3eb9;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.first::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
height: 16px;
|
||||
width: 3px;
|
||||
background: linear-gradient(to bottom, #ff7eb3, #ff758c, #ff5a5f);
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.text {
|
||||
padding-left: 8px;
|
||||
color: #e9e8e8;
|
||||
}
|
||||
</style>
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row pinyin">
|
||||
<div class="text">ni'uo</div>
|
||||
</div>
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand first">
|
||||
<div class="text">1. 你说</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">2. 笔画</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">3. 量子</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">4. 牛魔</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">5. 仙人</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">6. 可恨</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">7. 木槿</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">8. 无量</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
)";
|
||||
|
||||
static std::wstring BodyString = LR"(
|
||||
<div class="container">
|
||||
<!--0Anchor-->
|
||||
<div class="row pinyin">
|
||||
<div class="text">{0}</div>
|
||||
</div>
|
||||
<!--1Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand first">
|
||||
<div class="text">{1}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--2Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{2}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--3Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{3}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--4Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{4}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--5Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{5}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--6Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{6}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--7Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{7}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--8Anchor-->
|
||||
<div class="row-wrapper">
|
||||
<div class="row cand">
|
||||
<div class="text">{8}</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--9Anchor-->
|
||||
</div>
|
||||
)";
|
||||
|
||||
HINSTANCE hInst = 0;
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
static ComPtr<ICoreWebView2Controller> webviewController;
|
||||
static ComPtr<ICoreWebView2> webview;
|
||||
ComPtr<ICoreWebView2_3> webview3;
|
||||
ComPtr<ICoreWebView2Controller2> webviewController2;
|
||||
|
||||
void LogMessageW(const wchar_t *message)
|
||||
{
|
||||
std::time_t now = std::time(nullptr);
|
||||
std::tm *localTime = std::localtime(&now);
|
||||
|
||||
wchar_t timeBuffer[80];
|
||||
wcsftime(timeBuffer, sizeof(timeBuffer) / sizeof(wchar_t),
|
||||
L"%Y-%m-%d %H:%M:%S", localTime);
|
||||
|
||||
std::wstring logfilePath = L"C:"
|
||||
L"\\Users\\SonnyCalcr\\EDisk\\CppCodes\\Win32Cod"
|
||||
L"es\\DirectWriteExperiment\\log.txt";
|
||||
std::wofstream logFile(logfilePath, std::ios_base::app);
|
||||
if (logFile.is_open())
|
||||
{
|
||||
logFile.imbue(std::locale("Chinese_China.65001"));
|
||||
logFile << L"[" << timeBuffer << L"] " << message;
|
||||
logFile << std::endl;
|
||||
logFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateHtmlContentWithJavaScript(ComPtr<ICoreWebView2> webview,
|
||||
const std::wstring &newContent)
|
||||
{
|
||||
if (webview != nullptr)
|
||||
{
|
||||
std::wstring script =
|
||||
L"document.body.innerHTML = `" + newContent + L"`;";
|
||||
webview->ExecuteScript(script.c_str(), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void MeasureDomUpdateTime(ComPtr<ICoreWebView2> webview)
|
||||
{
|
||||
std::wstring script =
|
||||
LR"(document.body.innerHTML = '<div>1. 原来</div> <div>2. 如此</div> <div>3. 竟然</div> <div>4. 这样</div> <div>5. 可恶</div> <div>6. 棋盘</div> <div>7. 磨合</div> <div>8. 樱花</div> </body>';)";
|
||||
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
webview->ExecuteScript(script.c_str(), nullptr);
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto duration =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(end - start);
|
||||
std::wstring message =
|
||||
L"DOM update time: " + std::to_wstring(duration.count()) + L" μs";
|
||||
LogMessageW(message.c_str());
|
||||
}
|
||||
|
||||
void inflateCandidateWindow(std::wstring &str)
|
||||
{
|
||||
std::wstringstream wss(str);
|
||||
std::wstring token;
|
||||
std::vector<std::wstring> words;
|
||||
|
||||
while (std::getline(wss, token, L','))
|
||||
{
|
||||
words.push_back(token);
|
||||
}
|
||||
|
||||
int size = words.size();
|
||||
|
||||
while (words.size() < 9)
|
||||
{
|
||||
words.push_back(L"");
|
||||
}
|
||||
|
||||
std::wstring result = fmt::format( //
|
||||
BodyString, //
|
||||
words[0], //
|
||||
words[1], //
|
||||
words[2], //
|
||||
words[3], //
|
||||
words[4], //
|
||||
words[5], //
|
||||
words[6], //
|
||||
words[7], //
|
||||
words[8] //
|
||||
); //
|
||||
|
||||
if (size < 9)
|
||||
{
|
||||
result = result.substr( //
|
||||
0, //
|
||||
result.find(fmt::format(L"<!--{}Anchor-->", size)) //
|
||||
) //
|
||||
+ //
|
||||
L"</div>"; //
|
||||
}
|
||||
|
||||
UpdateHtmlContentWithJavaScript(webview, result);
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
LPARAM lParam)
|
||||
{
|
||||
|
||||
if (message == WM_SHOW_MAIN_WINDOW)
|
||||
{
|
||||
ShowWindow(hWnd, SW_SHOWNOACTIVATE);
|
||||
return 0;
|
||||
}
|
||||
if (message == WM_HIDE_MAIN_WINDOW)
|
||||
{
|
||||
ShowWindow(hWnd, SW_HIDE);
|
||||
if (candStr.find(L",") == 1)
|
||||
{
|
||||
inflateCandidateWindow(candStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateHtmlContentWithJavaScript(webview, L"");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_MOUSEACTIVATE:
|
||||
// Stop the window from being activated by mouse click
|
||||
return MA_NOACTIVATE;
|
||||
case WM_COPYDATA: {
|
||||
COPYDATASTRUCT *pcds = (COPYDATASTRUCT *)lParam;
|
||||
if (pcds->dwData == 0)
|
||||
{
|
||||
POINT *pt = (POINT *)pcds->lpData;
|
||||
MoveWindow( //
|
||||
hWnd, //
|
||||
pt->x, //
|
||||
pt->y + 3, //
|
||||
(108 + 15) * 1.5, //
|
||||
(246 + 15) * 1.5, //
|
||||
TRUE //
|
||||
); //
|
||||
}
|
||||
else if (pcds->dwData == 1)
|
||||
{
|
||||
WCHAR *p = (WCHAR *)pcds->lpData;
|
||||
std::wstring str = p;
|
||||
candStr = str;
|
||||
#ifdef FANY_DEBUG
|
||||
LogMessageW(str.c_str());
|
||||
#endif
|
||||
inflateCandidateWindow(str);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
case WM_ACTIVATE: {
|
||||
if (LOWORD(wParam) != WA_INACTIVE)
|
||||
{
|
||||
ShowWindow(hWnd, SW_SHOWNOACTIVATE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_DESTROY: {
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InitWebview(HWND hWnd)
|
||||
{
|
||||
CreateCoreWebView2EnvironmentWithOptions(
|
||||
nullptr, nullptr, nullptr,
|
||||
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(
|
||||
[hWnd](HRESULT result, ICoreWebView2Environment *env) -> HRESULT {
|
||||
if (result != S_OK)
|
||||
{
|
||||
MessageBox(hWnd, L"Failed to create WebView2 environment.",
|
||||
L"Error", MB_OK);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Create a CoreWebView2Controller and get the associated
|
||||
// CoreWebView2
|
||||
env->CreateCoreWebView2Controller(
|
||||
hWnd,
|
||||
Callback<
|
||||
ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>(
|
||||
[hWnd](HRESULT result,
|
||||
ICoreWebView2Controller *controller) -> HRESULT {
|
||||
if (controller == nullptr || FAILED(result))
|
||||
{
|
||||
MessageBox(
|
||||
hWnd,
|
||||
L"Failed to create WebView2 controller.",
|
||||
L"Error", MB_OK);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
webviewController = controller;
|
||||
webviewController->get_CoreWebView2(
|
||||
webview.GetAddressOf());
|
||||
|
||||
if (webview == nullptr)
|
||||
{
|
||||
MessageBox(hWnd,
|
||||
L"Failed to get WebView2 instance.",
|
||||
L"Error", MB_OK);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Add a few settings for the webview
|
||||
ICoreWebView2Settings *settings;
|
||||
webview->get_Settings(&settings);
|
||||
settings->put_IsScriptEnabled(TRUE);
|
||||
settings->put_AreDefaultScriptDialogsEnabled(TRUE);
|
||||
settings->put_IsWebMessageEnabled(TRUE);
|
||||
settings->put_AreHostObjectsAllowed(TRUE);
|
||||
|
||||
if (webview->QueryInterface(
|
||||
IID_PPV_ARGS(&webview3)) == S_OK)
|
||||
{
|
||||
webview3->SetVirtualHostNameToFolderMapping(
|
||||
L"appassets",
|
||||
L"C:"
|
||||
L"\\Users\\SonnyCalcr\\AppData\\Roaming\\Po"
|
||||
L"tPla"
|
||||
L"yerMini64\\Capture",
|
||||
COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY_CORS);
|
||||
}
|
||||
|
||||
if (controller->QueryInterface(
|
||||
IID_PPV_ARGS(&webviewController2)) == S_OK)
|
||||
{
|
||||
COREWEBVIEW2_COLOR backgroundColor = {0, 0, 0,
|
||||
0};
|
||||
webviewController2->put_DefaultBackgroundColor(
|
||||
backgroundColor);
|
||||
}
|
||||
|
||||
// Resize WebView to fit the bounds of the parent
|
||||
// window
|
||||
RECT bounds;
|
||||
GetClientRect(hWnd, &bounds);
|
||||
webviewController->put_Bounds(bounds);
|
||||
// Navigate to a simple HTML string
|
||||
auto hr =
|
||||
webview->NavigateToString(HTMLString.c_str());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
MessageBox(hWnd,
|
||||
L"Failed to navigate to string.",
|
||||
L"Error", MB_OK);
|
||||
}
|
||||
|
||||
// webview->OpenDevToolsWindow();
|
||||
|
||||
return S_OK;
|
||||
})
|
||||
.Get());
|
||||
return S_OK;
|
||||
})
|
||||
.Get());
|
||||
}
|
||||
|
||||
int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance,
|
||||
_In_ LPSTR lpCmdLine, _In_ int nCmdShow)
|
||||
{
|
||||
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
|
||||
WM_SHOW_MAIN_WINDOW = RegisterWindowMessage(L"WM_SHOW_MAIN_WINDOW");
|
||||
WM_HIDE_MAIN_WINDOW = RegisterWindowMessage(L"WM_HIDE_MAIN_WINDOW");
|
||||
WM_MOVE_CANDIDATE_WINDOW =
|
||||
RegisterWindowMessage(L"WM_MOVE_CANDIDATE_WINDOW");
|
||||
|
||||
WNDCLASSEX wcex;
|
||||
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wcex.lpfnWndProc = WndProc;
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = 0;
|
||||
wcex.hInstance = hInstance;
|
||||
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
|
||||
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
wcex.lpszMenuName = NULL;
|
||||
wcex.lpszClassName = szWindowClass;
|
||||
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
|
||||
|
||||
if (!RegisterClassEx(&wcex))
|
||||
{
|
||||
MessageBox(NULL, _T("Call to RegisterClassEx failed!"),
|
||||
_T("Windows Desktop Guided Tour"), NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Store instance handle in our global variable
|
||||
hInst = hInstance;
|
||||
|
||||
HWND hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOOLWINDOW | //
|
||||
WS_EX_NOACTIVATE | //
|
||||
WS_EX_TOPMOST, //
|
||||
szWindowClass, //
|
||||
L"fanycandidatewindow", //
|
||||
WS_POPUP, //
|
||||
100, //
|
||||
100, //
|
||||
(108 + 15) * 1.5, //
|
||||
(246 + 15) * 1.5, //
|
||||
nullptr, nullptr, hInstance, nullptr);
|
||||
|
||||
if (!hWnd)
|
||||
{
|
||||
MessageBox(NULL, _T("Call to CreateWindow failed!"),
|
||||
_T("Windows Desktop Guided Tour"), NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
MoveWindow(hWnd, -1000, 100, (108 + 15) * 1.5, (246 + 15) * 1.5, TRUE);
|
||||
ShowWindow(hWnd, SW_SHOW);
|
||||
UpdateWindow(hWnd);
|
||||
|
||||
InitWebview(hWnd);
|
||||
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return (int)msg.wParam;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
//
|
||||
// Message define
|
||||
//
|
||||
inline UINT WM_SHOW_MAIN_WINDOW;
|
||||
inline UINT WM_HIDE_MAIN_WINDOW;
|
||||
inline UINT WM_MOVE_CANDIDATE_WINDOW;
|
||||
@@ -0,0 +1,23 @@
|
||||
#include "fanylog.h"
|
||||
|
||||
void LogMessageW(const wchar_t *message)
|
||||
{
|
||||
// std::time_t now = std::time(nullptr);
|
||||
// std::tm *localTime = std::localtime(&now);
|
||||
|
||||
// wchar_t timeBuffer[80];
|
||||
// wcsftime(timeBuffer, sizeof(timeBuffer) / sizeof(wchar_t),
|
||||
// L"%Y-%m-%d %H:%M:%S", localTime);
|
||||
|
||||
// std::wstring logfilePath = L"C:"
|
||||
// L"\\Users\\SonnyCalcr\\EDisk\\CppCodes\\Win32Cod"
|
||||
// L"es\\DirectWriteExperiment\\log.txt";
|
||||
// std::wofstream logFile(logfilePath, std::ios_base::app);
|
||||
// if (logFile.is_open())
|
||||
// {
|
||||
// logFile.imbue(std::locale("Chinese_China.65001"));
|
||||
// logFile << L"[" << timeBuffer << L"] " << message;
|
||||
// logFile << std::endl;
|
||||
// logFile.close();
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
|
||||
void LogMessageW(const wchar_t *);
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "window/candidate_window.h"
|
||||
|
||||
int CALLBACK WinMain(_In_ HINSTANCE hInstance, _In_ HINSTANCE hPrevInstance,
|
||||
_In_ LPSTR lpCmdLine, _In_ int nCmdShow)
|
||||
{
|
||||
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
|
||||
RegisterCandidateWindowMessage();
|
||||
|
||||
WNDCLASSEX wcex;
|
||||
RegisterCandidateWindowClass(wcex, hInstance);
|
||||
int ret = CreateCandidateWindow(hInstance);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "common_utils.h"
|
||||
|
||||
void ShowErrorMessage(HWND hWnd, const std::wstring &message)
|
||||
{
|
||||
MessageBox(hWnd, message.c_str(), L"Error", MB_OK);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
void ShowErrorMessage(HWND, const std::wstring &);
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "webview_utils.h"
|
||||
|
||||
void MeasureDomUpdateTime(ComPtr<ICoreWebView2> webview)
|
||||
{
|
||||
std::wstring script =
|
||||
LR"(document.body.innerHTML = '<div>1. 原来</div> <div>2. 如此</div> <div>3. 竟然</div> <div>4. 这样</div> <div>5. 可恶</div> <div>6. 棋盘</div> <div>7. 磨合</div> <div>8. 樱花</div> </body>';)";
|
||||
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
|
||||
webview->ExecuteScript(script.c_str(), nullptr);
|
||||
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
|
||||
auto duration =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(end - start);
|
||||
std::wstring message =
|
||||
L"DOM update time: " + std::to_wstring(duration.count()) + L" μs";
|
||||
// LogMessageW(message.c_str());
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "webview2/candidate_window_webview2.h"
|
||||
|
||||
void MeasureDomUpdateTime(ComPtr<ICoreWebView2>);
|
||||
@@ -0,0 +1,179 @@
|
||||
#include "candidate_window_webview2.h"
|
||||
#include "utils/common_utils.h"
|
||||
#include <filesystem>
|
||||
#include <windows.h>
|
||||
|
||||
std::wstring ReadHtmlFile(const std::wstring &filePath)
|
||||
{
|
||||
std::wifstream file(filePath);
|
||||
if (!file)
|
||||
{
|
||||
// TODO: Log
|
||||
return L"";
|
||||
}
|
||||
// Use Boost Locale to handle UTF-8
|
||||
file.imbue(boost::locale::generator().generate("en_US.UTF-8"));
|
||||
std::wstringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
return buffer.str();
|
||||
}
|
||||
|
||||
int PrepareCandidateWindowHtml()
|
||||
{
|
||||
std::wstring htmlPath =
|
||||
std::filesystem::current_path().wstring() + L"/html/default-themes/vertical_candidate_window_dark.html";
|
||||
::HTMLString = ReadHtmlFile(htmlPath);
|
||||
std::wstring bodyPath =
|
||||
std::filesystem::current_path().wstring() + L"/html/default-themes/body/vertical_candidate_window_dark.html";
|
||||
::BodyString = ReadHtmlFile(bodyPath);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UpdateHtmlContentWithJavaScript(ComPtr<ICoreWebView2> webview, const std::wstring &newContent)
|
||||
{
|
||||
if (webview != nullptr)
|
||||
{
|
||||
std::wstring script = L"document.body.innerHTML = `" + newContent + L"`;";
|
||||
webview->ExecuteScript(script.c_str(), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void InflateCandidateWindow(std::wstring &str)
|
||||
{
|
||||
std::wstringstream wss(str);
|
||||
std::wstring token;
|
||||
std::vector<std::wstring> words;
|
||||
|
||||
while (std::getline(wss, token, L','))
|
||||
{
|
||||
words.push_back(token);
|
||||
}
|
||||
|
||||
int size = words.size();
|
||||
|
||||
while (words.size() < 9)
|
||||
{
|
||||
words.push_back(L"");
|
||||
}
|
||||
|
||||
std::wstring result = fmt::format( //
|
||||
BodyString, //
|
||||
words[0], //
|
||||
words[1], //
|
||||
words[2], //
|
||||
words[3], //
|
||||
words[4], //
|
||||
words[5], //
|
||||
words[6], //
|
||||
words[7], //
|
||||
words[8] //
|
||||
); //
|
||||
|
||||
if (size < 9)
|
||||
{
|
||||
size_t pos = result.find(fmt::format(L"<!--{}Anchor-->", size));
|
||||
result = result.substr(0, pos) + L"</div>";
|
||||
}
|
||||
|
||||
UpdateHtmlContentWithJavaScript(webview, result);
|
||||
}
|
||||
|
||||
// Handle WebView2 controller creation
|
||||
HRESULT OnControllerCreated( //
|
||||
HWND hWnd, //
|
||||
HRESULT result, //
|
||||
ICoreWebView2Controller *controller //
|
||||
)
|
||||
{
|
||||
if (!controller || FAILED(result))
|
||||
{
|
||||
ShowErrorMessage(hWnd, L"Failed to create WebView2 controller.");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
webviewController = controller;
|
||||
webviewController->get_CoreWebView2(webview.GetAddressOf());
|
||||
|
||||
if (!webview)
|
||||
{
|
||||
ShowErrorMessage(hWnd, L"Failed to get WebView2 instance.");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
// Configure WebView settings
|
||||
ComPtr<ICoreWebView2Settings> settings;
|
||||
if (SUCCEEDED(webview->get_Settings(&settings)))
|
||||
{
|
||||
settings->put_IsScriptEnabled(TRUE);
|
||||
settings->put_AreDefaultScriptDialogsEnabled(TRUE);
|
||||
settings->put_IsWebMessageEnabled(TRUE);
|
||||
settings->put_AreHostObjectsAllowed(TRUE);
|
||||
}
|
||||
|
||||
// Configure virtual host path
|
||||
if (SUCCEEDED(webview->QueryInterface(IID_PPV_ARGS(&webview3))))
|
||||
{
|
||||
webview3->SetVirtualHostNameToFolderMapping( //
|
||||
L"appassets", //
|
||||
LocalAssetsPath.c_str(), //
|
||||
COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_DENY_CORS //
|
||||
); //
|
||||
}
|
||||
|
||||
// Set transparent background
|
||||
if (SUCCEEDED(controller->QueryInterface(IID_PPV_ARGS(&webviewController2))))
|
||||
{
|
||||
COREWEBVIEW2_COLOR backgroundColor = {0, 0, 0, 0};
|
||||
webviewController2->put_DefaultBackgroundColor(backgroundColor);
|
||||
}
|
||||
|
||||
// Adjust to window size
|
||||
RECT bounds;
|
||||
GetClientRect(hWnd, &bounds);
|
||||
webviewController->put_Bounds(bounds);
|
||||
|
||||
// Navigate to HTML
|
||||
HRESULT hr = webview->NavigateToString(HTMLString.c_str());
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ShowErrorMessage(hWnd, L"Failed to navigate to string.");
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Handle WebView2 environment creation
|
||||
HRESULT OnEnvironmentCreated(HWND hWnd, HRESULT result, ICoreWebView2Environment *env)
|
||||
{
|
||||
if (FAILED(result) || !env)
|
||||
{
|
||||
ShowErrorMessage(hWnd, L"Failed to create WebView2 environment.");
|
||||
return result;
|
||||
}
|
||||
|
||||
// Create WebView2 controller
|
||||
return env->CreateCoreWebView2Controller( //
|
||||
hWnd, //
|
||||
Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>( //
|
||||
[hWnd](HRESULT result, //
|
||||
ICoreWebView2Controller *controller) -> HRESULT { //
|
||||
return OnControllerCreated(hWnd, result, controller); //
|
||||
}) //
|
||||
.Get() //
|
||||
); //
|
||||
}
|
||||
|
||||
// Initialize WebView2
|
||||
void InitWebview(HWND hWnd)
|
||||
{
|
||||
CreateCoreWebView2EnvironmentWithOptions( //
|
||||
nullptr, //
|
||||
nullptr, //
|
||||
nullptr, //
|
||||
Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>( //
|
||||
[hWnd](HRESULT result, ICoreWebView2Environment *env) -> HRESULT { //
|
||||
return OnEnvironmentCreated(hWnd, result, env); //
|
||||
}) //
|
||||
.Get() //
|
||||
); //
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "WebView2.h"
|
||||
#include "fmt/core.h"
|
||||
#include "fmt/xchar.h"
|
||||
#include <boost/locale.hpp>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <wrl.h>
|
||||
#include <wrl/client.h>
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
inline ComPtr<ICoreWebView2Controller> webviewController;
|
||||
inline ComPtr<ICoreWebView2> webview;
|
||||
inline ComPtr<ICoreWebView2_3> webview3;
|
||||
inline ComPtr<ICoreWebView2Controller2> webviewController2;
|
||||
|
||||
inline std::wstring HTMLString = LR"()";
|
||||
inline std::wstring BodyString = LR"()";
|
||||
inline std::wstring CandStr = L"";
|
||||
const std::wstring LocalAssetsPath = L"C:\\Users\\SonnyCalcr\\AppData\\Roaming\\PotPlayerMini64\\Capture";
|
||||
|
||||
int PrepareCandidateWindowHtml();
|
||||
void UpdateHtmlContentWithJavaScript( //
|
||||
ComPtr<ICoreWebView2>, //
|
||||
const std::wstring & //
|
||||
); //
|
||||
void InflateCandidateWindow(std::wstring &);
|
||||
void InitWebview(HWND);
|
||||
Whitespace-only changes.
@@ -0,0 +1,160 @@
|
||||
#include "candidate_window.h"
|
||||
#include "defines/defines.h"
|
||||
#include "log/fanylog.h"
|
||||
#include "webview2/candidate_window_webview2.h"
|
||||
#include <minwindef.h>
|
||||
|
||||
LRESULT RegisterCandidateWindowMessage()
|
||||
{
|
||||
|
||||
WM_SHOW_MAIN_WINDOW = RegisterWindowMessage(L"WM_SHOW_MAIN_WINDOW");
|
||||
WM_HIDE_MAIN_WINDOW = RegisterWindowMessage(L"WM_HIDE_MAIN_WINDOW");
|
||||
WM_MOVE_CANDIDATE_WINDOW = RegisterWindowMessage(L"WM_MOVE_CANDIDATE_WINDOW");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LRESULT RegisterCandidateWindowClass(WNDCLASSEX &wcex, HINSTANCE hInstance)
|
||||
{
|
||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wcex.lpfnWndProc = WndProc;
|
||||
wcex.cbClsExtra = 0;
|
||||
wcex.cbWndExtra = 0;
|
||||
wcex.hInstance = hInstance;
|
||||
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
|
||||
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
|
||||
wcex.lpszMenuName = NULL;
|
||||
wcex.lpszClassName = szWindowClass;
|
||||
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
|
||||
|
||||
if (!RegisterClassEx(&wcex))
|
||||
{
|
||||
MessageBox( //
|
||||
NULL, //
|
||||
L"Call to RegisterClassEx failed!", //
|
||||
L"Windows Desktop Guided Tour", //
|
||||
NULL //
|
||||
); //
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CreateCandidateWindow(HINSTANCE hInstance)
|
||||
{
|
||||
DWORD dwExStyle = WS_EX_LAYERED | //
|
||||
WS_EX_TOOLWINDOW | //
|
||||
WS_EX_NOACTIVATE | //
|
||||
WS_EX_TOPMOST; //
|
||||
HWND hWnd = CreateWindowEx( //
|
||||
dwExStyle, //
|
||||
szWindowClass, //
|
||||
lpWindowName, //
|
||||
WS_POPUP, //
|
||||
100, //
|
||||
100, //
|
||||
(108 + 15) * 1.5, //
|
||||
(246 + 15) * 1.5, //
|
||||
nullptr, //
|
||||
nullptr, //
|
||||
hInstance, //
|
||||
nullptr //
|
||||
); //
|
||||
|
||||
if (!hWnd)
|
||||
{
|
||||
MessageBox( //
|
||||
NULL, //
|
||||
L"Call to CreateWindow failed!", //
|
||||
L"Windows Desktop Guided Tour", //
|
||||
NULL //
|
||||
); //
|
||||
return 1;
|
||||
}
|
||||
|
||||
MoveWindow(hWnd, -1000, 100, (108 + 15) * 1.5, (246 + 15) * 1.5, TRUE);
|
||||
ShowWindow(hWnd, SW_SHOW);
|
||||
UpdateWindow(hWnd);
|
||||
|
||||
PrepareCandidateWindowHtml();
|
||||
InitWebview(hWnd);
|
||||
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, NULL, 0, 0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return (int)msg.wParam;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (message == WM_SHOW_MAIN_WINDOW)
|
||||
{
|
||||
ShowWindow(hWnd, SW_SHOWNOACTIVATE);
|
||||
return 0;
|
||||
}
|
||||
if (message == WM_HIDE_MAIN_WINDOW)
|
||||
{
|
||||
ShowWindow(hWnd, SW_HIDE);
|
||||
if (::CandStr.find(L",") == 1)
|
||||
{
|
||||
InflateCandidateWindow(::CandStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateHtmlContentWithJavaScript(webview, L"");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_MOUSEACTIVATE:
|
||||
// Stop the window from being activated by mouse click
|
||||
return MA_NOACTIVATE;
|
||||
case WM_COPYDATA: {
|
||||
COPYDATASTRUCT *pcds = (COPYDATASTRUCT *)lParam;
|
||||
if (pcds->dwData == 0)
|
||||
{
|
||||
POINT *pt = (POINT *)pcds->lpData;
|
||||
MoveWindow( //
|
||||
hWnd, //
|
||||
pt->x, //
|
||||
pt->y + 3, //
|
||||
(108 + 15) * 1.5, //
|
||||
(246 + 15) * 1.5, //
|
||||
TRUE //
|
||||
); //
|
||||
}
|
||||
else if (pcds->dwData == 1)
|
||||
{
|
||||
WCHAR *p = (WCHAR *)pcds->lpData;
|
||||
std::wstring str = p;
|
||||
CandStr = str;
|
||||
#ifdef FANY_DEBUG
|
||||
LogMessageW(str.c_str());
|
||||
#endif
|
||||
InflateCandidateWindow(str);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
case WM_ACTIVATE: {
|
||||
if (LOWORD(wParam) != WA_INACTIVE)
|
||||
{
|
||||
ShowWindow(hWnd, SW_SHOWNOACTIVATE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_DESTROY: {
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
inline WCHAR szWindowClass[] = L"global_candidate_window";
|
||||
inline WCHAR szTitle[] = L"Global Candidate Window";
|
||||
inline WCHAR lpWindowName[] = L"fanycandidatewindow";
|
||||
|
||||
LRESULT RegisterCandidateWindowMessage();
|
||||
LRESULT RegisterCandidateWindowClass(WNDCLASSEX &, HINSTANCE);
|
||||
int CreateCandidateWindow(HINSTANCE);
|
||||
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
Reference in new issue
Block a user