这个厉害,比使用edg打包方便多了
大佬,对方需要有webview环境或者edg吗?
:噜阿噜感谢大佬,先试试
大佬,有点尴尬,系统没WebView环境还运行不了{:2_25:}
66666666666666
kankan
不错
谢谢,看一下
经过测试发现,该库在win2012服务器,安装相应环境后,依然无法打开软件;但是别人的WEBUI程序可以打开。
后面经过和AI一起的分析,分析了大概两个多小时,成功定位到问题:
XHwebUI 当前库强制调用 ICoreWebView2Settings9
Windows Server 2012 R2 上的 WebView2 Runtime 109 不支持该高版本接口
导致原先 创建主窗口() 返回假
解决方案:牺牲一点无边框拖拽高级特性,在UI类的创建webview2中打入相应兼容补丁。
方法 创建webview2 <类型 = 逻辑型 @禁止流程检查 = 真>
{
@ if(!g_env)return false;
@ HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
@ if (!event) return false;
@ bool ret = false;
// 创建控制器和webview2
@ HRESULT hr = g_env->CreateCoreWebView2Controller(window, Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler>((HRESULT result, ICoreWebView2Controller* controller) -> HRESULT
@ {
@ ret = (SUCCEEDED(result) && controller != nullptr);
@ if(ret)
@ {
@ this->controller = controller;
@ controller->get_CoreWebView2(&this->webview);
@
@ RECT bounds;
@ GetClientRect(this->window, &bounds);
@ controller->put_Bounds(bounds);
@ // 唤醒渲染睡眠
@ controller->put_IsVisible(FALSE);
@ controller->put_IsVisible(TRUE);
@ controller->NotifyParentWindowPositionChanged();
@
@ // 将本地对象添加到脚本中
@ VARIANT var = { 0 };
@ var.vt = VT_DISPATCH;
@ var.pdispVal = this->hostObj.Get();
@ ret = SUCCEEDED(webview->AddHostObjectToScript(L"host",&var));
@ }
@ SetEvent(event);
@ return S_OK;
@ }).Get());
@ if(FAILED(hr))CloseHandle(event);
@ else WaitEvent(event, window);
@ if(!ret)return false;
// 对webview2进行一些设置
@ Microsoft::WRL::ComPtr<ICoreWebView2Settings> settings;
@ hr = webview->get_Settings(&settings);
@ if(FAILED(hr))return false;
@ Microsoft::WRL::ComPtr<ICoreWebView2Settings9> settings9;
@ hr = settings.As(&settings9);
@ if(SUCCEEDED(hr) && settings9 != nullptr)
@ {
@ settings9->put_IsNonClientRegionSupportEnabled(TRUE);
@ }
// 非调试版本禁止右键菜单和
@ #ifndef _DEBUG
@ // 监听按键
@ hr = controller->add_AcceleratorKeyPressed(Callback<ICoreWebView2AcceleratorKeyPressedEventHandler>([](ICoreWebView2Controller* controller, ICoreWebView2AcceleratorKeyPressedEventArgs* args) -> HRESULT
@ {
@ //检测快捷键
@ UINT32 virtualKey;
@ args->get_VirtualKey(&virtualKey);
@ if (virtualKey == VK_F5 || virtualKey == VK_F7 || virtualKey == VK_F12)//屏蔽刷新和开发者工具
@ {
@ args->put_Handled(TRUE);
@ return S_OK;
@ }
@
@ //检查功能键
@ if(GetKeyState(VK_CONTROL) < 0)//Ctrl
@ {
@ if (virtualKey == 'F' || virtualKey == 'P' || virtualKey == 'R' || virtualKey == 'G' || virtualKey == 'J' || virtualKey == 'U')
@ {
@ args->put_Handled(TRUE);
@ return S_OK;
@ }
@
@ if (GetKeyState(VK_SHIFT) < 0)//Shift
@ {
@ if (virtualKey == 'I')
@ {
@ args->put_Handled(TRUE);
@ return S_OK;
@ }
@ }
@ }
@
@ if (GetKeyState(VK_MENU) < 0)//Alt
@ {
@ if(virtualKey == VK_LEFT || virtualKey == VK_RIGHT)
@ {
@ args->put_Handled(TRUE);
@ return S_OK;
@ }
@ }
@
@ return S_OK;
@ }).Get(), nullptr);
@ if(FAILED(hr))return false;
@
@ //禁用状态栏
@ hr = settings->put_IsStatusBarEnabled(false);
@ if(FAILED(hr))return false;
@ //禁用开发者工具
@ settings->put_AreDevToolsEnabled(false);
@ if(FAILED(hr))return false;
@ //禁用右键菜单
@ settings->put_AreDefaultContextMenusEnabled(false);
@ if(FAILED(hr))return false;
@
@ #endif
// 资源所有过滤
@ hr = webview->AddWebResourceRequestedFilter(L"*", COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL);
@ if(FAILED(hr))return false;
// 设置开始加载事件
@ hr = webview->add_WebResourceRequested(Callback<ICoreWebView2WebResourceRequestedEventHandler>((ICoreWebView2* sender, ICoreWebView2WebResourceRequestedEventArgs* args) -> HRESULT
@ {
@ ComPtr<ICoreWebView2WebResourceRequest> request;
@ HRESULT hr = args->get_Request(&request);
@ if (FAILED(hr)) return hr;
@ LPWSTR uri = nullptr;
@ hr = request->get_Uri(&uri);
@ if (FAILED(hr) || uri == nullptr) return hr;
@ CVolString* str = new CVolString(uri);
@ if(pUrls->find (uri) != pUrls->end ())
@ {
@ hr = args->put_Response((*pUrls).Get());
@ if(!PostMessageW(this->window, WM_USER + 50, (WPARAM)str, 0))delete str;
@ }else if(g_urls.find (uri) != g_urls.end ())
@ {
@ hr = args->put_Response(g_urls.Get());
@ if(!PostMessageW(this->window, WM_USER + 50, (WPARAM)str, 1))delete str;
@ }else
@ {
@ if(!PostMessageW(this->window, WM_USER + 50, (WPARAM)str, -1))delete str;
@ }
@
@ CoTaskMemFree(uri);
@
@ return hr;
@ }).Get(), nullptr);
// 设置加载完成事件
@ BOOL show = @<窗口可视>;
@ hr = webview->add_NavigationCompleted(Callback<ICoreWebView2NavigationCompletedEventHandler>((ICoreWebView2* sender, ICoreWebView2NavigationCompletedEventArgs* args) -> HRESULT
@ {
@ if(this->cwin != this->window)
@ {
@ if(show)ShowWindow(this->window, SW_SHOW);
@ this->cwin = this->window;
@ }
@
@ LPWSTR url = nullptr;
@ if (SUCCEEDED(sender->get_Source(&url)) && url != nullptr)
@ {
@ int httpStatusCode = 0;
@ BOOL success = false;
@ args->get_IsSuccess(&success);
@ if(success)
@ {
@ Microsoft::WRL::ComPtr<ICoreWebView2NavigationCompletedEventArgs2> args2;
@ if (SUCCEEDED(args->QueryInterface(IID_PPV_ARGS(&args2))))args2->get_HttpStatusCode(&httpStatusCode);
@ }
@
@ sender->ExecuteScript(funcJS.GetText(), nullptr);
@ CVolString* str = new CVolString(url);
@ if(!PostMessageW(this->window, WM_USER + 51, (WPARAM)str, httpStatusCode))delete str;
@ CoTaskMemFree(url);
@ }
@
@ return S_OK;
@ }).Get(), nullptr);
@ if(FAILED(hr))return false;
// 框架页面加载完毕事件
@ hr = webview->add_FrameNavigationCompleted(Callback<ICoreWebView2NavigationCompletedEventHandler>((ICoreWebView2* sender, ICoreWebView2NavigationCompletedEventArgs* args) -> HRESULT
@ {
@ LPWSTR url = nullptr;
@ if (SUCCEEDED(sender->get_Source(&url)) && url != nullptr)
@ {
@ int httpStatusCode = 0;
@ BOOL success = false;
@ args->get_IsSuccess(&success);
@ if(success)
@ {
@ Microsoft::WRL::ComPtr<ICoreWebView2NavigationCompletedEventArgs2> args2;
@ if (SUCCEEDED(args->QueryInterface(IID_PPV_ARGS(&args2))))args2->get_HttpStatusCode(&httpStatusCode);
@ }
@
@ sender->ExecuteScript(funcJS.GetText(), nullptr);
@ CVolString* str = new CVolString(url);
@ if(!PostMessageW(this->window, WM_USER + 51, (WPARAM)str, httpStatusCode))delete str;
@ CoTaskMemFree(url);
@ }
@
@ return S_OK;
@ }).Get(), nullptr);
@ if(FAILED(hr))return false;
// 标题改变事件
@ hr = webview->add_DocumentTitleChanged(Callback<ICoreWebView2DocumentTitleChangedEventHandler>((ICoreWebView2* sender, IUnknown* args) -> HRESULT
@ {
@ LPWSTR title = nullptr;
@ if (this->window && SUCCEEDED(sender->get_DocumentTitle(&title)) && title != nullptr)
@ {
@ SetWindowTextW(this->window, title);
@ CoTaskMemFree(title);
@ }
@ return S_OK;
@ }).Get(), nullptr);
@ if(FAILED(hr))return false;
// 全屏切换事件
@ hr = webview->add_ContainsFullScreenElementChanged(Callback<ICoreWebView2ContainsFullScreenElementChangedEventHandler>((ICoreWebView2* sender, IUnknown* args) -> HRESULT
@ {
@ if (sender && this->window)
@ {
@ BOOL isFullScreen = FALSE;
@ sender->get_ContainsFullScreenElement(&isFullScreen);
@ RECT rect;
@ GetWindowRect(this->window, &rect);
@ *this->pFull =(rect.left == 0 && rect.top ==0 && rect.right == GetSystemMetrics (SM_CXSCREEN) && rect.bottom == GetSystemMetrics (SM_CYSCREEN));
@ if(*this->pFull == (bool)isFullScreen)return S_OK;
@
@ *this->pFull = isFullScreen;
@ if(*this->pFull )
@ {
@ this->oldWndPos.length = sizeof(WINDOWPLACEMENT);
@ GetWindowPlacement(this->window, &this->oldWndPos);
@ DWORD style = GetWindowLong(this->window, GWL_STYLE);
@ this->oldStyle = style;
@ if((style & WS_CAPTION) == WS_CAPTION)style &= ~WS_CAPTION;
@ if((style & WS_THICKFRAME) == WS_THICKFRAME)style &= ~WS_THICKFRAME;
@ SetWindowLongPtr(this->window, GWL_STYLE, style);
@ SetWindowPos (this->window, NULL, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), SWP_NOZORDER);
@ }
@ else
@ {
@ SetWindowLongPtr(this->window, GWL_STYLE, this->oldStyle);
@ SetWindowPlacement(this->window, &this->oldWndPos);
@ SetWindowPos(this->window, NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER);//刷新窗口
@ }
@ }
@ return S_OK;
@ }).Get(), nullptr);
@ if(FAILED(hr))return false;
// // 弹出窗口事件
// @ webview->add_NewWindowRequested(Callback<ICoreWebView2NewWindowRequestedEventHandler>([](ICoreWebView2* sender, ICoreWebView2NewWindowRequestedEventArgs* args) -> HRESULT
// @ {
// @ args->put_Handled(TRUE);//阻止创建
// @ return S_OK;
// @ }).Get(), nullptr);
@ if(!@<首页地址>.IsEmpty ())hr = webview->Navigate(@<首页地址>.GetText());
@ if(FAILED(hr) || @<首页地址>.IsEmpty ())//载入地址错误或不载入地址需要显示窗口
@ {
@ if(@<窗口可视>)ShowWindow(window, SW_SHOW);
@ cwin = window;
@ }
@ return true;
}
主要改动在这个地方:
1、把 XHwebUI 里 CoreWebView2Settings9 获取失败 → return false
改成
ICoreWebView2Settings9 获取成功才启用非客户区支持
获取失败就跳过,继续创建窗口
对应插入的代码如下:
// 对webview2进行一些设置
@ Microsoft::WRL::ComPtr<ICoreWebView2Settings> settings;
@ hr = webview->get_Settings(&settings);
@ if(FAILED(hr))return false;
@ Microsoft::WRL::ComPtr<ICoreWebView2Settings9> settings9;
@ hr = settings.As(&settings9);
@ if(SUCCEEDED(hr) && settings9 != nullptr)
@ {
@ settings9->put_IsNonClientRegionSupportEnabled(TRUE);
@ }
// 非调试版本禁止右键菜单和
大佬牛逼{:2_25:}{:2_25:}
感谢开源