返回
Visual Studio 2019构建CEF样例:踏出高效开发的第一步
前端
2024-02-11 09:36:57
前言
CEF(Chromium Embedded Framework)是一个开源框架,将Chromium嵌入其他应用程序,使其能够展现网页内容。在上一节中,我们已经完成了CEF的配置与编译工作。现在,让我们在Visual Studio 2019中创建一个空白的C++Windows Desktop Application项目,并逐步进行CEF样例编写。
创建空白C++ Windows Desktop Application项目
- 打开Visual Studio 2019
- 点击“新建”->“项目”
- 选择“Visual C++”->“桌面”->“Windows桌面应用程序”
- 输入项目名称,选择项目位置,点击“创建”
添加CEF库
- 在解决方案资源管理器中,右键单击项目名称,选择“添加”->“现有项”
- 导航到CEF库的目录,选择“include”和“lib”文件夹,点击“添加”
配置项目属性
- 在解决方案资源管理器中,右键单击项目名称,选择“属性”
- 在“配置属性”->“常规”中,将“字符集”设置为“使用Unicode字符集”
- 在“配置属性”->“链接器”->“常规”中,将“子系统”设置为“控制台”
- 在“配置属性”->“链接器”->“输入”中,添加CEF库的库文件路径,如“C:\path\to\cef\lib\x64\cef.lib”
- 在“配置属性”->“链接器”->“附加依赖项”中,添加CEF库的依赖项,如“libcef_dll_wrapper.lib;libcef.lib;libcrypto.lib;libicudate.lib;libicuuc.lib;libbrotlidec.lib;libbrotlienc.lib;libssl.lib”
创建主窗口类
- 在解决方案资源管理器中,右键单击项目名称,选择“添加”->“新建项”
- 选择“代码”->“C++文件(.cpp)”
- 输入文件名,如“MainWindow.cpp”,点击“添加”
- 在MainWindow.cpp中添加如下代码:
#include <windows.h>
#include <commctrl.h>
class MainWindow : public HWND
{
public:
MainWindow();
~MainWindow();
BOOL Create(HINSTANCE hInstance, int nCmdShow);
void Destroy();
private:
HINSTANCE m_hInstance;
HWND m_hWnd;
};
MainWindow::MainWindow()
{
m_hInstance = nullptr;
m_hWnd = nullptr;
}
MainWindow::~MainWindow()
{
Destroy();
}
BOOL MainWindow::Create(HINSTANCE hInstance, int nCmdShow)
{
m_hInstance = hInstance;
WNDCLASSEXW wc = { 0 };
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.lpszClassName = L"MainWindow";
RegisterClassExW(&wc);
m_hWnd = CreateWindowExW(0, L"MainWindow", L"CEF Example", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, nullptr, nullptr, hInstance, this);
if (m_hWnd == nullptr)
{
return FALSE;
}
ShowWindow(m_hWnd, nCmdShow);
UpdateWindow(m_hWnd);
return TRUE;
}
void MainWindow::Destroy()
{
if (m_hWnd != nullptr)
{
DestroyWindow(m_hWnd);
m_hWnd = nullptr;
}
UnregisterClassW(L"MainWindow", m_hInstance);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
MainWindow* pThis = (MainWindow*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
switch (message)
{
case WM_CREATE:
{
CREATESTRUCTW* pCreateStruct = (CREATESTRUCTW*)lParam;
SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)pCreateStruct->lpCreateParams);
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
default:
return DefWindowProcW(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
MainWindow window;
if (!window.Create(hInstance, nCmdShow))
{
return -1;
}
MSG msg;
while (GetMessageW(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return (int)msg.wParam;
}
添加CEF控件
- 在解决方案资源管理器中,右键单击项目名称,选择“添加”->“新建项”
- 选择“CEF”->“CEF控件”
- 输入文件名,如“CEFControl.cpp”,点击“添加”
- 在CEFControl.cpp中添加如下代码:
#include "CEFControl.h"
#include <windows.h>
#include <commctrl.h>
#include <string>
#include <vector>
#include <include/cef_base.h>
#include <include/cef_app.h>
#include <include/cef_browser.h>
#include <include/cef_client.h>
#include <include/cef_command_line.h>
#include <include/cef_frame.h>
#include <include/cef_runnable.h>
#include <include/cef_string.h>
#include <include/cef_version.h>
class CEFControl : public HWND
{
public:
CEFControl();
~CEFControl();
BOOL Create(HINSTANCE hInstance, HWND hParentWnd);
void Destroy();
void LoadURL(const std::string& url);
private:
HINSTANCE m_hInstance;
HWND m_hWnd;
HWND m_hParentWnd;
CefRefPtr<CefBrowser> m_browser;
};
CEFControl::CEFControl()
{
m_hInstance = nullptr;
m_hWnd = nullptr;
m_hParentWnd = nullptr;
m_browser = nullptr;
}
CEFControl::~CEFControl()
{
Destroy();
}
BOOL CEFControl::Create(HINSTANCE hInstance, HWND hParentWnd)
{
m_hInstance = hInstance;
m_hParentWnd = hParentWnd;
CefMainArgs mainArgs(hInstance);
CefRefPtr<CefCommandLine> commandLine = CefCommandLine::CreateCommandLine();
commandLine->InitFromString(mainArgs.command_line_args_utf8());
CefSettings settings;
settings.single_process = true;
settings.no_sandbox = true;
settings.windowless_frame_rate = 30;
CefInitialize(mainArgs, settings, commandLine.get());
RECT rect;
GetClientRect(m_hParentWnd, &rect);
CefWindowInfo windowInfo;
windowInfo.SetAsChild(m_hParentWnd, rect);
CefRefPtr<CefClient> client(new CefClient());
m_browser = CefBrowserHost::CreateBrowser(windowInfo, client.get(), "https://www.google.com");
m_hWnd = m_browser->GetHost()->GetWindowHandle();
return TRUE;
}
void CEFControl::Destroy()
{
if (m_browser != nullptr)
{
m_browser->Get