Merged PR 3390912: Basic setup for the sample browser app

This is the basic setup for the browser app. UI and content WebViews are now communicating.

Related work items: #22317625
This commit is contained in:
Luis Francisco Flores Romero 2019-06-24 18:42:29 +00:00
Коммит be8050cbc4
24 изменённых файлов: 1083 добавлений и 0 удалений

3
.clang-format Normal file
Просмотреть файл

@ -0,0 +1,3 @@
# Defines the coding style to apply. See:
# <http://clang.llvm.org/docs/ClangFormatStyleOptions.html>
DisableFormat: true

15
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,15 @@
Release/
Debug/
ipch/
x64/
x86/
.vs/
// Override root .gitignore to ensure we pick up changes for the sample app
!*.sln
!*.vcxproj
!*.vcxproj.filters
!packages/**/*
// Ignore the binary generated version of the resource (.rc) file
*.aps

321
BrowserWindow.cpp Normal file
Просмотреть файл

@ -0,0 +1,321 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "BrowserWindow.h"
#include <wrl.h>
using namespace Microsoft::WRL;
WCHAR BrowserWindow::s_windowClass[] = { 0 };
WCHAR BrowserWindow::s_title[] = { 0 };
//
// FUNCTION: RegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM BrowserWindow::RegisterClass(_In_ HINSTANCE hInstance)
{
// Initialize window class string
LoadStringW(hInstance, IDC_WEBVIEWBROWSERAPP, s_windowClass, MAX_LOADSTRING);
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProcStatic;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WEBVIEWBROWSERAPP));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_WEBVIEWBROWSERAPP);
wcex.lpszClassName = s_windowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: WndProcStatic(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Redirect messages to approriate instance or call default proc
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK BrowserWindow::WndProcStatic(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// Get the ptr to the BrowserWindow instance who created this hWnd
// The pointer was set when the hWnd was created during InitInstance
BrowserWindow* browser_window = reinterpret_cast<BrowserWindow*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
if (browser_window != nullptr)
{
return browser_window->WndProc(hWnd, message, wParam, lParam); // forward message to instance-aware WndProc
}
else
{
OutputDebugString(L"hWnd does not have associated BrowserWindow instance\n");
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for each browser window instance.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK BrowserWindow::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_GETMINMAXINFO:
{
MINMAXINFO* minmax = reinterpret_cast<MINMAXINFO*>(lParam);
minmax->ptMinTrackSize.x = m_minWindowWidth;
minmax->ptMinTrackSize.y = m_minWindowHeight;
}
break;
case WM_DPICHANGED:
{
UpdateMinWindowSize(hWnd);
if (m_uiWebview != nullptr)
{
ResizeUIWebView(hWnd);
}
if (m_activeTab != nullptr)
{
m_activeTab->ResizeWebView();
}
}
break;
case WM_SIZE:
{
if (m_uiWebview != nullptr)
{
ResizeUIWebView(hWnd);
}
if (m_activeTab != nullptr)
{
m_activeTab->ResizeWebView();
}
}
break;
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
{
// TO DO: close only the interacted browser window
PostQuitMessage(0);
}
break;
default:
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
}
return 0;
}
BOOL BrowserWindow::LaunchWindow(_In_ HINSTANCE hInstance, _In_ int nCmdShow)
{
BrowserWindow* window = new BrowserWindow();
if (!window->InitInstance(hInstance, nCmdShow))
{
delete window;
return FALSE;
}
// TO DO: make sure the instance is destroyed properly
return TRUE;
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL BrowserWindow::InitInstance(HINSTANCE hInstance, int nCmdShow)
{
m_hInst = hInstance; // Store app instance handle
LoadStringW(m_hInst, IDS_APP_TITLE, s_title, MAX_LOADSTRING);
SetUIMessageBroker();
HWND hWnd = CreateWindowW(s_windowClass, s_title, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, m_hInst, nullptr);
if (!hWnd)
{
return FALSE;
}
// Make the BrowserWindow instance ptr available through the hWnd
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
// TO DO: remove the menu from resources
SetMenu(hWnd, nullptr);
UpdateMinWindowSize(hWnd);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
InitUIWebView(hWnd, m_hInst);
// TO DO: use a separate env for content webviews
m_activeTab = Tab::CreateNewTab(hWnd, m_uiEnv.Get());
return TRUE;
}
void BrowserWindow::InitUIWebView(_In_ HWND hWnd, _In_ HINSTANCE hInst)
{
THROW_IF_FAILED(CreateWebView2EnvironmentWithDetails(L".", nullptr, WEBVIEW2_RELEASE_CHANNEL_PREFERENCE_STABLE,
L"", Callback<IWebView2CreateWebView2EnvironmentCompletedHandler>(
[hWnd, this](HRESULT result, IWebView2Environment* env) -> HRESULT {
if (!SUCCEEDED(result))
{
OutputDebugString(L"WebView environment creation failed\n");
return result;
}
// Environment is ready, create the WebView
m_uiEnv = env;
THROW_IF_FAILED(env->CreateWebView(hWnd, Callback<IWebView2CreateWebViewCompletedHandler>(
[hWnd, this](HRESULT result, IWebView2WebView* webview) -> HRESULT {
if (!SUCCEEDED(result))
{
OutputDebugString(L"UI WebView creation failed\n");
return result;
}
// WebView created
m_uiWebview = webview;
RETURN_IF_FAILED(m_uiWebview->add_WebMessageReceived(m_uiMessageBroker.Get(), &m_uiMessageBrokerToken));
ResizeUIWebView(hWnd);
WCHAR path[MAX_PATH];
GetModuleFileNameW(m_hInst, path, MAX_PATH);
std::wstring pathName(path);
std::size_t index = pathName.find_last_of(L"\\") + 1;
pathName.replace(index, pathName.length(), L"ui_bar\\bar.html");
RETURN_IF_FAILED(m_uiWebview->Navigate(pathName.c_str()));
return S_OK;
}).Get()));
return S_OK;
}).Get()));
}
// Set the message broker for the UI webview. This will capture messages from ui web content.
// Lambda is used to capture the instance while satisfying Microsoft::WRL::Callback<T>()
void BrowserWindow::SetUIMessageBroker()
{
m_uiMessageBroker = Callback<IWebView2WebMessageReceivedEventHandler>(
[this](IWebView2WebView* webview, IWebView2WebMessageReceivedEventArgs* eventArgs) -> HRESULT
{
wil::unique_cotaskmem_string jsonString;
eventArgs->get_WebMessageAsJson(&jsonString); // Get the message from the UI WebView as JSON formatted string
web::json::value jsonObj = web::json::value::parse(jsonString.get());
// TO DO: validate the message is correctly formatted
int message = jsonObj.at(L"message").as_integer();
web::json::value args = jsonObj.at(L"args");
switch (message)
{
case MG_NAVIGATE:
{
LPCTSTR uri = args.at(L"uri").as_string().c_str();
THROW_IF_FAILED(m_activeTab->m_contentWebview->Navigate(uri));
}
break;
default:
{
OutputDebugString(L"Unexpected message\n");
}
break;
}
return S_OK;
});
}
void BrowserWindow::HandleTabURIUpdate(IWebView2WebView* webview)
{
wil::unique_cotaskmem_string uri;
THROW_IF_FAILED(webview->get_Source(&uri));
web::json::value jsonObj = web::json::value::parse(L"{}");
jsonObj[L"message"] = web::json::value(MG_UPDATE_URI);
jsonObj[L"args"] = web::json::value::parse(L"{}");
jsonObj[L"args"][L"uri"] = web::json::value(uri.get());
utility::stringstream_t stream;
jsonObj.serialize(stream);
THROW_IF_FAILED(m_uiWebview->PostWebMessageAsJson(stream.str().c_str()));
}
void BrowserWindow::ResizeUIWebView(HWND hWnd)
{
RECT bounds;
GetClientRect(hWnd, &bounds);
bounds.bottom = bounds.top + (c_uiBarHeight * GetDpiForWindow(hWnd) / DEFAULT_DPI);
THROW_IF_FAILED(m_uiWebview->put_Bounds(bounds));
}
void BrowserWindow::UpdateMinWindowSize(HWND hWnd)
{
// TO DO: figure out why these limits are not being applied properly
m_minWindowWidth = MIN_WINDOW_WIDTH * GetDpiForWindow(hWnd) / DEFAULT_DPI;
m_minWindowHeight = MIN_WINDOW_HEIGHT * GetDpiForWindow(hWnd) / DEFAULT_DPI;
}
void BrowserWindow::CheckFailure(HRESULT hr)
{
if (FAILED(hr))
{
WCHAR message[512] = L"";
StringCchPrintf(message, ARRAYSIZE(message), L"Error: 0x%x", hr);
MessageBoxW(nullptr, message, nullptr, MB_OK);
}
}

44
BrowserWindow.h Normal file
Просмотреть файл

@ -0,0 +1,44 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "framework.h"
#include "Tab.h"
class BrowserWindow
{
public:
static const int c_uiBarHeight = 70;
static ATOM RegisterClass(_In_ HINSTANCE hInstance);
static LRESULT CALLBACK WndProcStatic(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
static BOOL LaunchWindow(_In_ HINSTANCE hInstance, _In_ int nCmdShow);
void HandleTabURIUpdate(IWebView2WebView* webview);
void CheckFailure(HRESULT hr);
protected:
HINSTANCE m_hInst = nullptr; // current app instance
static WCHAR s_windowClass[MAX_LOADSTRING]; // the window class name
static WCHAR s_title[MAX_LOADSTRING]; // The title bar text
int m_minWindowWidth = 0;
int m_minWindowHeight = 0;
Microsoft::WRL::ComPtr<IWebView2Environment> m_uiEnv;
Microsoft::WRL::ComPtr<IWebView2WebView> m_uiWebview;
std::unique_ptr<Tab> m_activeTab;
EventRegistrationToken m_uiMessageBrokerToken = {}; // token for the registered UI message handler of this window
Microsoft::WRL::ComPtr<IWebView2WebMessageReceivedEventHandler> m_uiMessageBroker;
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
void InitUIWebView(_In_ HWND hWnd, _In_ HINSTANCE hInst);
void SetUIMessageBroker();
void ResizeUIWebView(HWND hWnd);
void UpdateMinWindowSize(HWND hWnd);
};

31
Resource.h Normal file
Просмотреть файл

@ -0,0 +1,31 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by WebViewBrowserApp.rc
//
#define IDC_MYICON 2
#define IDD_WEBVIEWBROWSERAPP_DIALOG 102
#define IDS_APP_TITLE 103
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDI_WEBVIEWBROWSERAPP 107
#define IDI_SMALL 108
#define IDC_WEBVIEWBROWSERAPP 109
#define IDR_MAINFRAME 128
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 131
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif

58
Tab.cpp Normal file
Просмотреть файл

@ -0,0 +1,58 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "BrowserWindow.h"
#include "Tab.h"
using namespace Microsoft::WRL;
std::unique_ptr<Tab> Tab::CreateNewTab(HWND hWnd, IWebView2Environment* env)
{
OutputDebugString(L"Should launch new tab");
std::unique_ptr<Tab> tab = std::make_unique<Tab>();
tab->m_parentHWnd = hWnd;
tab->Init(env);
return tab;
}
void Tab::Init(IWebView2Environment* env)
{
THROW_IF_FAILED(env->CreateWebView(m_parentHWnd, Callback<IWebView2CreateWebViewCompletedHandler>(
[this](HRESULT result, IWebView2WebView* webview) -> HRESULT {
if (!SUCCEEDED(result))
{
OutputDebugString(L"Tab WebView creation failed\n");
return result;
}
m_contentWebview = webview;
// Register event handler for doc state change
THROW_IF_FAILED(m_contentWebview->add_DocumentStateChanged(Callback<IWebView2DocumentStateChangedEventHandler>(
[this](IWebView2WebView* webview, IWebView2DocumentStateChangedEventArgs* args) -> HRESULT
{
BrowserWindow* browser_window = reinterpret_cast<BrowserWindow*>(GetWindowLongPtr(m_parentHWnd, GWLP_USERDATA));
browser_window->HandleTabURIUpdate(webview);
return S_OK;
}).Get(), &m_uriUpdateForwarderToken));
ResizeWebView();
THROW_IF_FAILED(m_contentWebview->Navigate(L"https://www.bing.com"));
return S_OK;
}).Get()));
}
void Tab::ResizeWebView()
{
RECT bounds;
GetClientRect(m_parentHWnd, &bounds);
// TO DO: remove hacky offset once put_Bounds is fixed
bounds.top += (BrowserWindow::c_uiBarHeight * GetDpiForWindow(m_parentHWnd) / DEFAULT_DPI) / 2;
bounds.bottom -= bounds.top;
THROW_IF_FAILED(m_contentWebview->put_Bounds(bounds));
}

21
Tab.h Normal file
Просмотреть файл

@ -0,0 +1,21 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "framework.h"
class Tab
{
public:
Microsoft::WRL::ComPtr<IWebView2WebView> m_contentWebview;
static std::unique_ptr<Tab> CreateNewTab(HWND hWnd, IWebView2Environment* env);
void ResizeWebView();
protected:
HWND m_parentHWnd = nullptr;
EventRegistrationToken m_uriUpdateForwarderToken = {};
void Init(IWebView2Environment* env);
};

64
WebViewBrowserApp.cpp Normal file
Просмотреть файл

@ -0,0 +1,64 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// WebViewBrowserApp.cpp : Defines the entry point for the application.
//
#include "BrowserWindow.h"
#include "WebViewBrowserApp.h"
#include "framework.h"
using namespace Microsoft::WRL;
void tryLaunchWindow(HINSTANCE hInstance, int nCmdShow);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
BrowserWindow::RegisterClass(hInstance);
tryLaunchWindow(hInstance, nCmdShow);
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WEBVIEWBROWSERAPP));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
void tryLaunchWindow(HINSTANCE hInstance, int nCmdShow)
{
BOOL launched = BrowserWindow::LaunchWindow(hInstance, nCmdShow);
if (!launched)
{
int msgboxID = MessageBox(NULL, L"Could not launch the browser", L"Error", MB_RETRYCANCEL);
switch (msgboxID)
{
case IDRETRY:
tryLaunchWindow(hInstance, nCmdShow);
break;
case IDCANCEL:
default:
PostQuitMessage(0);
}
}
}

7
WebViewBrowserApp.h Normal file
Просмотреть файл

@ -0,0 +1,7 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "framework.h"

Двоичные данные
WebViewBrowserApp.ico Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 45 KiB

Двоичные данные
WebViewBrowserApp.rc Normal file

Двоичный файл не отображается.

31
WebViewBrowserApp.sln Normal file
Просмотреть файл

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29001.49
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WebViewBrowserApp", "WebViewBrowserApp.vcxproj", "{D65018E5-6B31-4DC7-AFAC-7999384BA4BD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Debug|x64.ActiveCfg = Debug|x64
{D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Debug|x64.Build.0 = Debug|x64
{D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Debug|x86.ActiveCfg = Debug|x64
{D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Debug|x86.Build.0 = Debug|x64
{D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Release|x64.ActiveCfg = Release|x64
{D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Release|x64.Build.0 = Release|x64
{D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Release|x86.ActiveCfg = Release|Win32
{D65018E5-6B31-4DC7-AFAC-7999384BA4BD}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0C9921DB-4634-415A-9AB1-087EA9B2EB24}
EndGlobalSection
EndGlobal

193
WebViewBrowserApp.vcxproj Normal file
Просмотреть файл

@ -0,0 +1,193 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{D65018E5-6B31-4DC7-AFAC-7999384BA4BD}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>WebViewBrowserApp</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>..\..\..\..\..\out\$(Configuration)_$(Platform)\</OutDir>
<IncludePath>..\..\..\..\..;$(OutDir)EBWebView\x64;$(OutDir)gen\edge_embedded_browser\client\win\current;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(OutDir)WebView2Loader.dll.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>xcopy "$(ProjectDir)ui_bar" "$(OutDir)ui_bar" /S /I /Y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="BrowserWindow.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="Tab.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="WebViewBrowserApp.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="BrowserWindow.cpp" />
<ClCompile Include="Tab.cpp" />
<ClCompile Include="WebViewBrowserApp.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WebViewBrowserApp.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="small.ico" />
<Image Include="WebViewBrowserApp.ico" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="ui_bar.html" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="packages\Microsoft.Windows.ImplementationLibrary.1.0.190610.2\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.190610.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('packages\Microsoft.Windows.ImplementationLibrary.1.0.190610.2\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', 'packages\Microsoft.Windows.ImplementationLibrary.1.0.190610.2\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Resource.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="WebViewBrowserApp.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BrowserWindow.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Tab.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="WebViewBrowserApp.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="BrowserWindow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Tab.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="WebViewBrowserApp.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="small.ico">
<Filter>Resource Files</Filter>
</Image>
<Image Include="WebViewBrowserApp.ico">
<Filter>Resource Files</Filter>
</Image>
</ItemGroup>
<ItemGroup>
<None Include="ui_bar.html" />
<None Include="packages.config" />
</ItemGroup>
</Project>

33
framework.h Normal file
Просмотреть файл

@ -0,0 +1,33 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files
#include <atlstr.h>
#include <strsafe.h>
#include <wil/result.h>
#include <windows.h>
#include <wrl.h>
// C RunTime Header Files
#include <cpprest/json.h>
#include <malloc.h>
#include <memory.h>
#include <memory>
#include <stdlib.h>
#include <tchar.h>
// App specific includes
#include "resource.h"
#include "webview2.h"
#define DEFAULT_DPI 96
#define MIN_WINDOW_WIDTH 700
#define MIN_WINDOW_HEIGHT 400
#define MAX_LOADSTRING 256
#define MG_NAVIGATE 1
#define MG_UPDATE_URI 2

4
packages.config Normal file
Просмотреть файл

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.190610.2" targetFramework="native" />
</packages>

Двоичные данные
small.ico Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 45 KiB

10
targetver.h Normal file
Просмотреть файл

@ -0,0 +1,10 @@
// Copyright (C) Microsoft Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>

31
ui_bar/bar.html Normal file
Просмотреть файл

@ -0,0 +1,31 @@
<html>
<head>
<link rel="stylesheet" type="text/css" href="styles.css">
<link rel="stylesheet" type="text/css" href="controls.css">
<link rel="stylesheet" type="text/css" href="strip.css">
</head>
<body>
<div id="controls-bar">
<div class="controls-group" id="nav-controls-container">
<div class="btn" id="btn-back"></div>
<div class="btn" id="btn-forward"></div>
<div class="btn" id="btn-reload"></div>
</div>
<div id="address-bar-container">
<div class="icn" id="icn-lock"></div>
<div class="icn" id="icn-favicon"></div>
<input type="text" id="address-field">
</div>
<div class="controls-group" id="manage-controls-container">
<div class="btn" id="btn-fav"></div>
<div class="btn" id="btn-options"></div>
</div>
</div>
<div id="tabs-strip"></div>
<script src="commands.js"></script>
<script src="script.js"></script>
</body>
</html>

4
ui_bar/commands.js Normal file
Просмотреть файл

@ -0,0 +1,4 @@
const commands = {
MG_NAVIGATE: 1,
MG_UPDATE_URI: 2
};

84
ui_bar/controls.css Normal file
Просмотреть файл

@ -0,0 +1,84 @@
#controls-bar {
display: flex;
justify-content: space-between;
flex-direction: row;
height: 40px;
background-color: rgb(230, 230, 230);
}
.btn {
display: inline-block;
margin: 0;
border: none;
outline: none;
height: 40px;
width: 40px;
background-color: red;
}
.controls-group {
display: inline-block;
height: 40px;
}
#nav-controls-container {
align-self: flex-start;
padding-left: 10px;
}
#manage-controls-container {
align-self: flex-end;
padding-right: 10px;
}
.btn:hover {
background-color: blue;
}
#address-bar-container {
display: inline-block;
height: calc(inherit - 10px);
min-width: 400px;
width: 70%;
max-width: calc(100% - 250px);
position: relative;
align-self: center;
}
.icn {
display: inline-block;
margin: 2px;
border-radius: 5px;
position: absolute;
top: 0;
width: 26px;
height: 26px;
background-color: rgb(200, 200, 200);
}
#icn-favicon {
left: 30px;
}
#address-form {
margin: 0;
}
#address-field {
display: inline-block;
margin: 0;
border: 1px solid gray;
border-radius: 5px;
padding: 0;
padding-left: 62px;
height: 30px;
width: 100%;
}
#address-field:focus {
outline: none;
box-shadow: 0 0 3px dodgerblue;
}

52
ui_bar/script.js Normal file
Просмотреть файл

@ -0,0 +1,52 @@
const URI_REGEX = /([http|https]:\/\/)[a-z]/i;
function processAddressBarInput() {
var text = document.querySelector('#address-field').value;
if (!text) {
return;
}
if (!isURI(text)) {
text = getSearchURI(text);
}
navigateTopWebView(text);
}
function navigateTopWebView(uri) {
var message = {
message: commands.MG_NAVIGATE,
args: {
uri: uri
}
};
window.chrome.webview.postMessage(message);
}
function isURI(query) {
return URI_REGEX.test(query);
}
function getSearchURI(query) {
return `https://www.bing.com/search?q=${encodeURIComponent(query)}`;
}
window.chrome.webview.addEventListener('message', event => {
var message = event.data.message;
var args = event.data.args;
switch (message) {
case commands.MG_UPDATE_URI:
document.getElementById('address-field').value = args.uri;
break;
}
});
document.querySelector('#address-field').addEventListener('keypress', function (e) {
var key = e.which || e.keyCode;
if (key === 13) { // 13 is enter
e.preventDefault();
processAddressBarInput();
}
});

5
ui_bar/strip.css Normal file
Просмотреть файл

@ -0,0 +1,5 @@
#tabs-strip {
display: block;
height: 30px;
background-color: green;
}

7
ui_bar/styles.css Normal file
Просмотреть файл

@ -0,0 +1,7 @@
html, body {
margin: 0;
border: none;
padding: 0;
height: 70px;
}