个人笔记:编写简单的浏览器【套壳webkit内核】

用visual studio 2022编译苹果开源webkit浏览器内核
界面用网易的开源duilib-netease
github仓库 简单的浏览器源码
m_patch = (++m_patch) % 2;用来强制刷新webkit view
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
( S o l u t i o n D i r ) (SolutionDir) (SolutionDir)(Platform)$(Configuration)
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
#####solunar项目##################################################

( S o l u t i o n D i r ) (SolutionDir) (SolutionDir)(Platform)$(Configuration)
$(ProjectName)
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
把webkit项目中MiniBrowser的附加库目录复制到solunar项目中,点击编辑框ctrl+a复制所有
在这里插入图片描述
同样的复制附加依赖,最后一项添加分号;
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
中间目录$(Platform)$(Configuration)
在这里插入图片描述
把文件复制到D:\VSProject\solunar\x64\Debug,两个文件夹也要复制
在这里插入图片描述

复制duilib-netease的resources

在这里插入图片描述

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<Window size="600,700" caption="0,0,0,35" shadowattached="false">
	<VBox bkcolor="bk_wnd_darkcolor" bordercolor="purple" bordersize="2">
		<HBox width="stretch" height="35">
			<Label name="tooltip" text="同辉" font="system_bold_18" normaltextcolor="white" margin="10,6,0,0"/>
			<Control />
			<Button class="btn_wnd_min" name="minbtn" margin="4,6,0,0"/>
			<Box width="21" margin="4,6,0,0">
				<Button class="btn_wnd_max" name="maxbtn"/>
				<Button class="btn_wnd_restore" name="restorebtn" visible="false"/>
			</Box>
			<Button class="btn_wnd_close" name="closebtn" margin="4,6,8,0"/>
		</HBox>
		<VBox>
			<HBox height="35" >
				<Option class="btn_global_blue_80x30" name="option_baidu" selectedforenormalimage="../public/button/btn_wnd_gray_min_pushed.png" margin="4,0,4,0" text="百度" selected="true" group="quickbar"/>
				<Option class="btn_global_blue_80x30" name="option_douyin" selectedforenormalimage="../public/button/btn_wnd_gray_min_pushed.png" margin="4,0,4,0" text="抖音" group="quickbar"/>
			</HBox>
			<TabBox name="tab_browser">
				<VBox>
					<Progress class="progress_blue" name="progress_baidu" height="5" value="0" margin="6,0,6,0"/>
					<WebkitBrowser name="wb_baidu" bkcolor="purple" margin="6,6,6,6"/>
				</VBox>
				<VBox>
					<Progress class="progress_blue" name="progress_douyin" height="5" value="0" margin="6,0,6,0"/>
					<WebkitBrowser name="wb_douyin" bkcolor="purple" margin="6,6,6,6"/>
				</VBox>
			</TabBox>
		</VBox>
	</VBox>
</Window>

global.xml

<?xml version="1.0" encoding="UTF-8"?>
<Global>
    <!--所有字体-->
    <Font id="system_12" name="system" size="12" default="true"/>
    <Font id="system_14" name="system" size="14"/>
    <Font id="system_16" name="system" size="16"/>
    <Font id="system_18" name="system" size="18"/>
    <Font id="system_20" name="system" size="20"/>
    <Font id="system_22" name="system" size="22"/>
    <Font id="system_bold_12" name="system" size="12" bold="true"/>
    <Font id="system_bold_14" name="system" size="14" bold="true"/>
    <Font id="system_bold_16" name="system" size="16" bold="true"/>
    <Font id="system_bold_18" name="system" size="18" bold="true"/>
    <Font id="system_bold_20" name="system" size="20" bold="true"/>
    <Font id="system_bold_22" name="system" size="22" bold="true"/>
    <Font id="arial_12" name="arial" size="12"/>
    <Font id="arial_14" name="arial" size="14"/>
    <Font id="arial_16" name="arial" size="16"/>
    <Font id="arial_18" name="arial" size="18"/>
    <Font id="arial_20" name="arial" size="20"/>
    <Font id="arial_22" name="arial" size="22"/>
    <Font id="arial_bold_12" name="arial" size="12" bold="true"/>
    <Font id="arial_bold_14" name="arial" size="14" bold="true"/>
    <Font id="arial_bold_16" name="arial" size="16" bold="true"/>
    <Font id="arial_bold_18" name="arial" size="18" bold="true"/>
    <Font id="arial_bold_20" name="arial" size="20" bold="true"/>
    <Font id="arial_bold_22" name="arial" size="22" bold="true"/>
    <Font id="system_underline_12" name="system" size="12" underline="true"/>
    <Font id="system_underline_14" name="system" size="14" underline="true"/>
    <Font id="system_underline_16" name="system" size="16" underline="true"/>
    <Font id="system_underline_18" name="system" size="18" underline="true"/>
    <Font id="system_underline_20" name="system" size="20" underline="true"/>
    <Font id="system_underline_22" name="system" size="22" underline="true"/>

    <!--一些常规固定颜色-->
    <TextColor name="white" value="#ffffffff"/>
    <TextColor name="black" value="#ff000000"/>
    <TextColor name="darkcolor" value="#ff333333"/>
    <TextColor name="lightcolor" value="#ff888888"/>
    <TextColor name="gray" value="#ff8e99a6"/>
    <TextColor name="light_gray" value="#ffa8a8a8"/>
    <TextColor name="dark_gray" value="#ff72797f"/>
    <TextColor name="green" value="#ff00bb96"/>
    <TextColor name="light_green" value="#ff21c7a6"/>
    <TextColor name="blue" value="#ff006DD9"/>
    <TextColor name="red" value="#ffC63535"/>
	<TextColor name="purple" value="#ff7160e8"/>

    <!--文字色值,不带透明层-->
    <TextColor name="textdefaultcolor" value="#ff333333"/>
    <TextColor name="textdefaultdisablecolor" value="#ffa1aebc"/>

    <!--窗口常用背景色-->
    <TextColor name="bk_main_wnd_title" value="#ff238efa"/>
    <TextColor name="bk_main_wnd_search" value="#ff1e7ad7"/>
    <TextColor name="bk_wnd_darkcolor" value="#ff1f1f1f"/>
    <TextColor name="bk_wnd_lightcolor" value="#ffffffff"/>
    <TextColor name="bk_menuitem_hovered" value="#ffe1e6eb"/>
    <TextColor name="bk_menuitem_selected" value="#ffced4db"/>
    <TextColor name="bk_listitem_hovered" value="#fff0f2f5"/>
    <TextColor name="bk_listitem_selected" value="#ffe4e7eb"/>

    <!--置顶项的背景颜色-->
    <TextColor name="bk_topitem_normal" value="#ffffffe0"/>
    <TextColor name="bk_topitem_hovered" value="#ffffffeb"/>
    <TextColor name="bk_topitem_selected" value="#fffafacd"/>

    <!--进度条专用-->
    <TextColor name="bk_progress_bk" value="#ffe3ecf5"/>
    <TextColor name="bk_progress_progress" value="#ff2aceae"/>

    <!--背景色值,半透明-->
    <TextColor name="transbkblack" value="#80000000"/>

    <!--第一级分割线,较深-->
    <TextColor name="splitline_level1" value="#ffd2d4d6"/>

    <!--第二级分割线,较浅-->
    <TextColor name="splitline_level2" value="#ffebedf0"/>

    <!--调色板色值-->
    <TextColor name="color_palette1" value="#ffff2600"/>
    <TextColor name="color_palette2" value="#ffffeb00"/>
    <TextColor name="color_palette3" value="#ff61ed00"/>
    <TextColor name="color_palette4" value="#ff00b4ff"/>
    <TextColor name="color_palette5" value="#ffa100ff"/>
    <TextColor name="color_palette6" value="#ff000000"/>
    <TextColor name="color_palette7" value="#ff545454"/>
    <TextColor name="color_palette8" value="#ffa8a8a8"/>
    <TextColor name="color_palette9" value="#ffffffff"/>

    <!--字体大小-->
    <Class name="font_title" font="system_14"/>

    <!--标题栏-->
    <Class name="caption" height="34" bkimage="file='../public/caption/caption_public.png' corner='0,0,0,1'" padding="10,0,5,0" />

    <!--滚动条-->
    <Class name="vscrollbar" width="14" fadealpha="true" thumbnormalimage="file='../public/vscrollbar/thumb_normal.png'  corner='0,8,0,8'" thumbhotimage="file='../public/vscrollbar/thumb_hovered.png' corner='0,8,0,8'" bkhotimage="file='../public/vscrollbar/bk_hovered.png' corner='0,4,0,4'" showbutton1="false" showbutton2="false" />   
    <Class name="hscrollbar" height="14" fadealpha="true" thumbnormalimage="file='../public/hscrollbar/thumb_normal.png' corner='8,0,8,0'" thumbhotimage="file='../public/hscrollbar/thumb_hovered.png' corner='8,0,8,0'" bkhotimage="file='../public/hscrollbar/bk_hovered.png' corner='4,0,4,0'" showbutton1="false" showbutton2="false"/>

    <!--单选框-->
    <Class name="option" selectednormalimage="../public/option/selected.png" selectedhotimage="../public/option/selectedhover.png" selectedpushedimage="../public/option/selectedhover.png"/>
    <Class name="circle_option" normalimage="../public/option/circle_unselected.png" disabledimage="../public/option/circle_unselected_disabled.png"/>
    <Class name="circle_option_2" height="18" textpadding="25,0,0,0" font="system_12" normaltextcolor="darkcolor" normalimage="file='../public/option/circle_unselected.png' dest='0,0,18,18'" selectednormalimage="file='../public/option/circle_selected.png' dest='0,0,18,18'"/>

    <!--复选框-->
    <Class name="checkbox_font12" height="16" textpadding="20,0,0,0" font="system_12" normaltextcolor="darkcolor" normalimage="file='../public/CheckBox/check_no.png' dest='0,0,16,16'" disabledimage="file='../public/CheckBox/check_no.png' dest='0,0,16,16' fade='80'" selectednormalimage="file='../public/CheckBox/check_yes.png' dest='0,0,16,16'" selecteddisabledimage="file='../public/CheckBox/check_yes.png' dest='0,0,16,16' fade='80'"/>
    <Class name="checkbox_font14" height="20" textpadding="20,0,0,0" font="system_14" normaltextcolor="darkcolor" normalimage="file='../public/CheckBox/check_no.png' dest='0,2,16,18'" disabledimage="file='../public/CheckBox/check_no.png' dest='0,2,16,18' fade='80'" selectednormalimage="file='../public/CheckBox/check_yes.png' dest='0,2,16,18'" selecteddisabledimage="file='../public/CheckBox/check_yes.png' dest='0,2,16,18' fade='80'"/>
    <Class name="checkbox_green" normalimage="file='../public/CheckBox/check_green_no.png'" disabledimage="file='../public/CheckBox/check_green_no.png' fade='80'" selectednormalimage="file='../public/CheckBox/check_green_yes.png'" selecteddisabledimage="file='../public/CheckBox/check_green_yes.png' fade='80'"/>
    
    <!--按钮-->
    <Class name="btn_global_blue_80x30" font="system_bold_14" normaltextcolor="white" normalimage="file='../public/button/btn_global_blue_80x30_normal.png'" hotimage="file='../public/button/btn_global_blue_80x30_hovered.png'" pushedimage="file='../public/button/btn_global_blue_80x30_pushed.png'" disabledimage="file='../public/button/btn_global_blue_80x30_normal.png' fade='80'"/>
    <Class name="btn_global_white_80x30" font="system_bold_14" normaltextcolor="dark_gray" normalimage="file='../public/button/btn_global_white_80x30_normal.png'" hotimage="file='../public/button/btn_global_white_80x30_hovered.png'" pushedimage="file='../public/button/btn_global_white_80x30_pushed.png'" disabledimage="file='../public/button/btn_global_white_80x30_normal.png' fade='128'"/>
    <Class name="btn_global_red_80x30" font="system_bold_14" normaltextcolor="white" normalimage="file='../public/button/btn_global_red_80x30_normal.png'" hotimage="file='../public/button/btn_global_red_80x30_hovered.png'" pushedimage="file='../public/button/btn_global_red_80x30_pushed.png'" disabledimage="file='../public/button/btn_global_red_80x30_normal.png' fade='80'"/>

    <!--窗口右上角按钮 灰色版 -->
    <Class name="btn_wnd_min" width="auto" height="auto" forenormalimage="file='../public/button/btn_wnd_gray_min.png' dest='4,4,16,16'" normalimage="" hotimage="../public/button/btn_wnd_gray_min_hovered.png" pushedimage="../public/button/btn_wnd_gray_min_pushed.png"/>
    <Class name="btn_wnd_close" width="20" height="20" normalimage="file='../public/button/btn_wnd_gray_close.png' dest='4,4,16,16'" hotimage="../public/button/btn_wnd_white_close_hovered.png" pushedimage="../public/button/btn_wnd_white_close_pushed.png" fadehot="false"/>
    <Class name="btn_wnd_max" width="auto" height="auto" forenormalimage="file='../public/button/btn_wnd_gray_max.png' dest='4,4,16,16'" normalimage="" hotimage="../public/button/btn_wnd_gray_max_hovered.png" pushedimage="../public/button/btn_wnd_gray_max_pushed.png"/>
    <Class name="btn_wnd_restore" width="auto" height="auto" forenormalimage="file='../public/button/btn_wnd_gray_restore.png' dest='4,4,16,16'" normalimage="" hotimage="../public/button/btn_wnd_gray_restore_hovered.png" pushedimage="../public/button/btn_wnd_gray_restore_pushed.png"/>
    <Class name="btn_wnd_settings" width="auto" height="auto" forenormalimage="file='../public/button/btn_wnd_settings.png' source='1,1,21,21'" hotimage="../public/button/btn_wnd_bk_hovered.png" pushedimage="../public/button/btn_wnd_bk_pushed.png"/>

    <!--窗口右上角按钮 白色版 -->
    <Class name="btn_wnd_white_min" width="auto" height="auto" forenormalimage="file='../public/button/btn_wnd_white_min.png'" normalimage="" hotimage="../public/button/btn_wnd_white_min_hovered.png" pushedimage="../public/button/btn_wnd_white_min_pushed.png"/>
    <Class name="btn_wnd_white_close" width="auto" height="auto" forenormalimage="file='../public/button/btn_wnd_white_close.png'" normalimage="" hotimage="../public/button/btn_wnd_white_close_hovered.png" pushedimage="../public/button/btn_wnd_white_close_pushed.png"/>
    <Class name="btn_wnd_white_max" width="auto" height="auto" forenormalimage="file='../public/button/btn_wnd_white_max.png' dest='4,4,16,16'" normalimage="" hotimage="../public/button/btn_wnd_white_max_hovered.png" pushedimage="../public/button/btn_wnd_white_max_pushed.png"/>
    <Class name="btn_wnd_white_menu" width="auto" height="auto" forenormalimage="file='../public/button/btn_wnd_white_menu.png' dest='4,5,16,15'" normalimage="" hotimage="../public/button/btn_wnd_white_menu_hovered.png" pushedimage="../public/button/btn_wnd_white_menu_pushed.png"/>

    <!--删除按钮通用样式-->
    <Class name="btn_delete" normalimage="file='../public/button/funcicon.png' source='0,0,26,26'" hotimage="file='../public/button/funcicon.png' source='31,0,57,26'" pushedimage="file='../public/button/funcicon.png' source='62,0,88,26'" disabledimage="file='../public/button/funcicon.png' source='93,0,119,26'"/>
    <Class name="btn_recycle" width="auto" height="auto" normalimage="file='../public/button/btn_recycle_normal.png'" hotimage="file='../public/button/btn_recycle_hovered.png'" pushedimage="file='../public/button/btn_recycle_pushed.png'" disabledimage="file='../public/button/btn_recycle_normal.png' fade='80'"/>
    <Class name="btn_refresh" width="auto" height="auto" normalimage="file='../public/button/btn_refresh_normal.png'" hotimage="file='../public/button/btn_refresh_hovered.png'" pushedimage="file='../public/button/btn_refresh_pushed.png'" disabledimage="file='../public/button/btn_refresh_normal.png' fade='80'"/>
    <Class name="btn_del_search" normalimage="../public/button/btn_del_search_normal_gray.png" hotimage="../public/button/btn_del_search_hover_gray.png" pushedimage="../public/button/btn_del_search_pushed_gray.png"/>

    <!--列表通用样式-->
    <Class name="list" bkcolor="bk_wnd_lightcolor" vscrollbar="true"/>
    <Class name="listitem" hotcolor="bk_listitem_hovered" pushedcolor="bk_listitem_selected" selectednormalcolor="bk_listitem_selected" fadehot="false"/>
    <Class name="list_topitem" normalcolor="bk_topitem_normal" hotcolor="bk_topitem_hovered" pushedcolor="bk_topitem_selected" selectednormalcolor="bk_topitem_selected" fadehot="false"/>

    <!--进度条通用样式, 注意进度条的值使用`_value`属性-->
    <Class name="progress_blue" valign="center" _value="0" bkimage="../public/progress/progress_blue_bg.png" height="3" width="stretch" hor="true" max="100" min="0" progressimage="../public/progress/progress_blue_fg.png"/>
    <Class name="slider_green" width="stretch" height="14" margin="4,0,0,0" valign="center" thumbsize="14,14" min="0" max="255" progressbarpadding="0,6,0,6" bkimage="file='../public/slider/slider_hor_bk.png' dest='0,6,1000,8'" progresscolor="bk_progress_progress" thumbnormalimage="../public/slider/slider_thumb.png"/>

    <!--菜单通用样式-->
    <Class name="menu" width="auto" height="auto" bkcolor="bk_wnd_lightcolor"/>
    <Class name="menu_element" padding="20,0,20,0" height="40" hotcolor="bk_menuitem_hovered" pushedcolor="bk_menuitem_selected" selectednormalcolor="bk_menuitem_selected"/>
    <Class name="menu_text" normaltextcolor="darkcolor" font="system_14" valign="center"/>

    <!--分割线通用样式-->
    <Class name="splitline_hor_level1" bkcolor="splitline_level1" height="1"/>
    <Class name="splitline_hor_level2" bkcolor="splitline_level2" height="1"/>
    <Class name="splitline_ver_level1" bkcolor="splitline_level1" width="1"/>

    <!--富文本控件通用样式-->
    <Class name="simple" multiline="false" autohscroll="true" wantreturnmsg="true" wanttab="false" rich="false" normaltextcolor="darkcolor" disabledtextcolor="textdefaultdisablecolor"/>
    <Class name="prompt" promptmode="true" promptcolor="light_gray"/>
    <Class name="edit" hotimage="file='../public/edit/edit1.png' corner='10,10,10,10'" focusedimage="file='../public/edit/edit2.png' corner='10,10,10,10'"/>
    <Class name="input" normalimage="file='../public/edit/edit0.png' corner='10,10,10,10'" hotimage="file='../public/edit/edit0.png' corner='10,10,10,10'" focusedimage="file='../public/edit/edit0.png' corner='10,10,10,10'" disabledimage="file='../public/edit/edit0.png' corner='10,10,10,10' fade='80'"/>

   <!--头像蒙版-->
    <Class name="icon_headimage_mask_40x40" width="40" height="40" bkimage="../public/headmask/icon_headimage_mask_40x40_normal.png"/>
</Global>

stdafx.h

#pragma once

#include <assert.h>
#include <comdef.h>
#include <comip.h>
#include <commctrl.h>
#include <commdlg.h>
#include <comutil.h>
#include <malloc.h>
#include <memory.h>
#include <objbase.h>
#include <shellapi.h>
#include <shlwapi.h>
#include <stdlib.h>
#include <string>
#include <tchar.h>
#include <windows.h>
#include <wininet.h>
#include <wtf/Platform.h>

#include <JavaScriptCore/JSExportMacros.h>
#include <WebCore/PlatformExportMacros.h>

Common.h

#pragma once

#include "stdafx.h"
#include "MainWindow.h"
#include <knownfolders.h>

Common2.h

#pragma once

#include <WebKit/WKRetainPtr.h>
#include <WebKit/WKString.h>

std::wstring createString(WKStringRef);

MainWindow.h

#pragma once

#include "BrowserWindow.h"
#include <functional>
#include <memory>
#include <string>
#include <wtf/RefPtr.h>

class MainWindow final : public RefCounted<MainWindow>, public BrowserWindowClient {
public:
    using BrowserWindowFactory = std::function<Ref<BrowserWindow>(BrowserWindowClient&, HWND mainWnd)>;

    static Ref<MainWindow> create();

    bool init(BrowserWindowFactory, HWND);

    HWND hwnd() const { return m_hMainWnd; }
    HWND browserHwnd() const { return m_browserWindow->hwnd(); }
    BrowserWindow* browserWindow() const { return m_browserWindow.get(); }

    void resetZoom();
    void loadURL(std::wstring);

    // BrowserWindowClient
    void progressChanged(double) final;
    void progressFinished() final;
    void activeURLChanged(std::wstring) final;

private:

    HWND m_hMainWnd{ nullptr };
    RefPtr<BrowserWindow> m_browserWindow;
};

WebKitBrowserWindow.h

#pragma once

#include "BrowserWindow.h"
#include "Common.h"
#include <WebKit/WKRetainPtr.h>
#include <WebKit/WebKit2_C.h>
#include <unordered_map>
#include <wtf/Ref.h>

class WebKitBrowserWindow : public BrowserWindow {
public:
    static Ref<BrowserWindow> create(BrowserWindowClient&, HWND mainWnd);
    void resetZoom() override;

private:
    WebKitBrowserWindow(BrowserWindowClient&, WKPageConfigurationRef, HWND mainWnd);

    HWND hwnd() override;

    HRESULT loadURL(const BSTR& url) override;
    void reload() override;

    void setUserAgent(_bstr_t&) override;

    static void didChangeTitle(const void*);
    static void didChangeIsLoading(const void*);
    static void didChangeEstimatedProgress(const void*);
    static void didChangeActiveURL(const void*);
    static void close(WKPageRef, const void*);
    static void didNotHandleKeyEvent(WKPageRef, WKNativeEventPtr, const void*);
    static WKRect getWindowFrame(WKPageRef, const void*);
    static void runJavaScriptAlert(WKPageRef, WKStringRef, WKFrameRef, WKSecurityOriginRef, WKPageRunJavaScriptAlertResultListenerRef, const void*);
    static void runJavaScriptConfirm(WKPageRef, WKStringRef, WKFrameRef, WKSecurityOriginRef, WKPageRunJavaScriptConfirmResultListenerRef, const void*);
    static void runJavaScriptPrompt(WKPageRef, WKStringRef, WKStringRef, WKFrameRef, WKSecurityOriginRef, WKPageRunJavaScriptPromptResultListenerRef, const void*);

    BrowserWindowClient& m_client;
    WKRetainPtr<WKViewRef> m_view;
    HWND m_hMainWnd{ nullptr };
};

BrowserWindow.h

#pragma once

#include <windows.h>
#include <wtf/RefCounted.h>

class BrowserWindowClient {
public:
    virtual void progressChanged(double) = 0;
    virtual void progressFinished() = 0;
    virtual void activeURLChanged(std::wstring) = 0;
};

class BrowserWindow : public RefCounted<BrowserWindow> {
public:
    enum class FeatureType { Experimental, InternalDebug };

    virtual ~BrowserWindow() { };

    virtual HWND hwnd() = 0;

    virtual HRESULT loadURL(const BSTR& passedURL) = 0;
    virtual void reload() = 0;
    virtual bool usesLayeredWebView() const { return false; }

    void setUserAgent();
    virtual void setUserAgent(_bstr_t& customUAString) = 0;

    virtual void resetZoom() = 0;
};

WebkitBrowser.h

#pragma once

#define WM_PROGRESS_CHANGE (WM_USER + 1)

class BrowserMiddleware {
public:
	BrowserMiddleware(HWND parentHWND);
	HWND WINAPI GetParentHWND() {
		return m_parentHWND;
	};
	HWND WINAPI GetBrowserHWND();
	void WINAPI loadURL(std::wstring url);
	void resetZoom();
private:
	HWND m_parentHWND{ nullptr };
	void* m_mainWindow{ nullptr };
};

Common2.cpp

#include "stdafx.h"
#include "Common2.h"

#include <vector>

std::wstring createString(WKStringRef wkString)
{
    size_t maxSize = WKStringGetLength(wkString);

    std::vector<WKChar> wkCharBuffer(maxSize);
    size_t actualLength = WKStringGetCharacters(wkString, wkCharBuffer.data(), maxSize);
    return std::wstring(wkCharBuffer.data(), actualLength);
}

MainWindow.cpp

#include "stdafx.h"
#include "MainWindow.h"
#include "WebkitBrowser.h"

#include "Common.h"
#include "WebKitBrowserWindow.h"
#include <sstream>

static const wchar_t* kMiniBrowserRegistryKey = L"Software\\WebKit\\MiniBrowser";

Ref<MainWindow> MainWindow::create()
{
    return adoptRef(*new MainWindow());
}

bool MainWindow::init(BrowserWindowFactory factory, HWND hwnd)
{
    m_hMainWnd = hwnd;

    if (!m_hMainWnd)
        return false;

    m_browserWindow = factory(*this, m_hMainWnd);
    if (!m_browserWindow)
        return false;

    m_browserWindow->setUserAgent();

    return true;
}

void MainWindow::resetZoom()
{
    m_browserWindow->resetZoom();
}

void MainWindow::loadURL(std::wstring url)
{
    if (::PathFileExists(url.c_str()) || ::PathIsUNC(url.c_str())) {
        wchar_t fileURL[INTERNET_MAX_URL_LENGTH];
        DWORD fileURLLength = _countof(fileURL);

        if (SUCCEEDED(::UrlCreateFromPath(url.c_str(), fileURL, &fileURLLength, 0)))
            url = fileURL;
    }
    if (url.find(L"://") == url.npos)
        url = L"http://" + url;

    if (FAILED(m_browserWindow->loadURL(_bstr_t(url.c_str()))))
        return;

    SetFocus(m_browserWindow->hwnd());
}

void MainWindow::progressChanged(double progress)
{
    ::SendMessage(m_hMainWnd, WM_PROGRESS_CHANGE, progress * 100, (LPARAM)browserHwnd());
}

void MainWindow::progressFinished()
{

}

void MainWindow::activeURLChanged(std::wstring url)
{
}

WebKitBrowserWindow.cpp

#include "stdafx.h"
#include "WebKitBrowserWindow.h"

#include "Common.h"
#include "Common2.h"
#include <WebCore/GDIUtilities.h>
#include <WebKit/WKAuthenticationChallenge.h>
#include <WebKit/WKAuthenticationDecisionListener.h>
#include <WebKit/WKCertificateInfoCurl.h>
#include <WebKit/WKContextConfigurationRef.h>
#include <WebKit/WKCredential.h>
#include <WebKit/WKDownloadClient.h>
#include <WebKit/WKDownloadRef.h>
#include <WebKit/WKFrameInfoRef.h>
#include <WebKit/WKHTTPCookieStoreRef.h>
#include <WebKit/WKInspector.h>
#include <WebKit/WKNavigationResponseRef.h>
#include <WebKit/WKPreferencesRefPrivate.h>
#include <WebKit/WKProtectionSpace.h>
#include <WebKit/WKProtectionSpaceCurl.h>
#include <WebKit/WKSecurityOriginRef.h>
#include <WebKit/WKURLResponse.h>
#include <WebKit/WKWebsiteDataStoreConfigurationRef.h>
#include <WebKit/WKWebsiteDataStoreRef.h>
#include <WebKit/WKWebsiteDataStoreRefCurl.h>
#include <filesystem>
#include <sstream>
#include <vector>

std::wstring createString(WKURLRef wkURL)
{
    if (!wkURL)
        return { };
    WKRetainPtr<WKStringRef> url = adoptWK(WKURLCopyString(wkURL));
    return createString(url.get());
}

std::string createUTF8String(const wchar_t* src, size_t srcLength)
{
    int length = WideCharToMultiByte(CP_UTF8, 0, src, srcLength, 0, 0, nullptr, nullptr);
    std::vector<char> buffer(length);
    size_t actualLength = WideCharToMultiByte(CP_UTF8, 0, src, srcLength, buffer.data(), length, nullptr, nullptr);
    return { buffer.data(), actualLength };
}

WKRetainPtr<WKStringRef> createWKString(_bstr_t str)
{
    auto utf8 = createUTF8String(str, str.length());
    return adoptWK(WKStringCreateWithUTF8CString(utf8.data()));
}

WKRetainPtr<WKStringRef> createWKString(const std::wstring& str)
{
    auto utf8 = createUTF8String(str.c_str(), str.length());
    return adoptWK(WKStringCreateWithUTF8CString(utf8.data()));
}

WKRetainPtr<WKStringRef> createWKString(const wchar_t* str)
{
    return createWKString(std::wstring(str));
}

WKRetainPtr<WKURLRef> createWKURL(_bstr_t str)
{
    auto utf8 = createUTF8String(str, str.length());
    return adoptWK(WKURLCreateWithUTF8CString(utf8.data()));
}

WKRetainPtr<WKURLRef> createWKURL(const std::wstring& str)
{
    auto utf8 = createUTF8String(str.c_str(), str.length());
    return adoptWK(WKURLCreateWithUTF8CString(utf8.data()));
}

WKRetainPtr<WKStringRef> injectedBundlePath()
{
    auto module = GetModuleHandle(nullptr);
    std::wstring path;
    for (;;) {
        path.resize(path.size() + MAX_PATH);
        auto copied = GetModuleFileName(module, path.data(), path.size());
        if (copied < path.size()) {
            path.resize(copied);
            break;
        }
    }
    path = std::filesystem::path(path).replace_filename("MiniBrowserInjectedBundle.dll");
    return createWKString(path);
}

Ref<BrowserWindow> WebKitBrowserWindow::create(BrowserWindowClient& client, HWND mainWnd)
{
    auto websiteDataStoreConf = adoptWK(WKWebsiteDataStoreConfigurationCreate());

    auto websiteDataStore = adoptWK(WKWebsiteDataStoreCreateWithConfiguration(websiteDataStoreConf.get()));

    auto contextConf = adoptWK(WKContextConfigurationCreate());
    WKContextConfigurationSetInjectedBundlePath(contextConf.get(), injectedBundlePath().get());

    auto context = adoptWK(WKContextCreateWithConfiguration(contextConf.get()));

    auto preferences = adoptWK(WKPreferencesCreate());
    WKPreferencesSetMediaCapabilitiesEnabled(preferences.get(), false);
    WKPreferencesSetDeveloperExtrasEnabled(preferences.get(), true);
    WKPreferencesSetAcceleratedCompositingEnabled(preferences.get(), true);
    WKPreferencesSetAcceleratedDrawingEnabled(preferences.get(), true);
    WKPreferencesSetAccelerated2DCanvasEnabled(preferences.get(), true);

    auto pageConf = adoptWK(WKPageConfigurationCreate());
    WKPageConfigurationSetWebsiteDataStore(pageConf.get(), websiteDataStore.get());
    WKPageConfigurationSetContext(pageConf.get(), context.get());
    WKPageConfigurationSetPreferences(pageConf.get(), preferences.get());

    return adoptRef(*new WebKitBrowserWindow(client, pageConf.get(), mainWnd));
}

void WebKitBrowserWindow::resetZoom()
{
    auto page = WKViewGetPage(m_view.get());
    WKPageSetPageZoomFactor(page, WebCore::deviceScaleFactorForWindow(hwnd()));
}

WebKitBrowserWindow::WebKitBrowserWindow(BrowserWindowClient& client, WKPageConfigurationRef pageConf, HWND mainWnd)
    : m_client(client)
    , m_hMainWnd(mainWnd)
{
    RECT rect = { };
    m_view = adoptWK(WKViewCreate(rect, pageConf, mainWnd));
    WKViewSetIsInWindow(m_view.get(), true);

    auto page = WKViewGetPage(m_view.get());

    WKPageUIClientV13 uiClient = { };
    uiClient.base.version = 13;
    uiClient.base.clientInfo = this;
    uiClient.createNewPage = nullptr;
    uiClient.close = close;
    uiClient.didNotHandleKeyEvent = didNotHandleKeyEvent;
    uiClient.getWindowFrame = getWindowFrame;
    uiClient.runJavaScriptAlert = runJavaScriptAlert;
    uiClient.runJavaScriptConfirm = runJavaScriptConfirm;
    uiClient.runJavaScriptPrompt = runJavaScriptPrompt;
    WKPageSetPageUIClient(page, &uiClient.base);

    WKPageStateClientV0 stateClient = { };
    stateClient.base.version = 0;
    stateClient.base.clientInfo = this;
    stateClient.didChangeTitle = didChangeTitle;
    stateClient.didChangeIsLoading = didChangeIsLoading;
    stateClient.didChangeEstimatedProgress = didChangeEstimatedProgress;
    stateClient.didChangeActiveURL = didChangeActiveURL;
    WKPageSetPageStateClient(page, &stateClient.base);

    resetZoom();
}

HWND WebKitBrowserWindow::hwnd()
{
    return WKViewGetWindow(m_view.get());
}

HRESULT WebKitBrowserWindow::loadURL(const BSTR& url)
{
    auto page = WKViewGetPage(m_view.get());
    WKPageLoadURL(page, createWKURL(_bstr_t(url)).get());
    return true;
}

void WebKitBrowserWindow::reload()
{
    auto page = WKViewGetPage(m_view.get());
    WKPageReload(page);
}

void WebKitBrowserWindow::setUserAgent(_bstr_t& customUAString)
{
    auto page = WKViewGetPage(m_view.get());
    auto ua = createWKString(customUAString);
    WKPageSetCustomUserAgent(page, ua.get());
}

static WebKitBrowserWindow& toWebKitBrowserWindow(const void* clientInfo)
{
    return *const_cast<WebKitBrowserWindow*>(static_cast<const WebKitBrowserWindow*>(clientInfo));
}

void WebKitBrowserWindow::didChangeTitle(const void* clientInfo)
{
    auto& thisWindow = toWebKitBrowserWindow(clientInfo);
    auto page = WKViewGetPage(thisWindow.m_view.get());
    WKRetainPtr<WKStringRef> title = adoptWK(WKPageCopyTitle(page));
    std::wstring titleString = createString(title.get()) + L" [WebKit]";
    SetWindowText(thisWindow.m_hMainWnd, titleString.c_str());
}

void WebKitBrowserWindow::didChangeIsLoading(const void* clientInfo)
{
    auto& thisWindow = toWebKitBrowserWindow(clientInfo);
    thisWindow.m_client.progressFinished();
}

void WebKitBrowserWindow::didChangeEstimatedProgress(const void* clientInfo)
{
    auto& thisWindow = toWebKitBrowserWindow(clientInfo);
    auto page = WKViewGetPage(thisWindow.m_view.get());
    thisWindow.m_client.progressChanged(WKPageGetEstimatedProgress(page));
}

void WebKitBrowserWindow::didChangeActiveURL(const void* clientInfo)
{
    auto& thisWindow = toWebKitBrowserWindow(clientInfo);
    auto page = WKViewGetPage(thisWindow.m_view.get());
    WKRetainPtr<WKURLRef> url = adoptWK(WKPageCopyActiveURL(page));
    thisWindow.m_client.activeURLChanged(createString(url.get()));
}

void WebKitBrowserWindow::close(WKPageRef, const void* clientInfo)
{
    auto& thisWindow = toWebKitBrowserWindow(clientInfo);
    PostMessage(thisWindow.hwnd(), WM_CLOSE, 0, 0);
}


void WebKitBrowserWindow::didNotHandleKeyEvent(WKPageRef, WKNativeEventPtr event, const void* clientInfo)
{
    auto& thisWindow = toWebKitBrowserWindow(clientInfo);
    PostMessage(thisWindow.m_hMainWnd, event->message, event->wParam, event->lParam);
}

WKRect WebKitBrowserWindow::getWindowFrame(WKPageRef, const void* clientInfo)
{
    auto& thisWindow = toWebKitBrowserWindow(clientInfo);
    RECT rect;
    GetWindowRect(thisWindow.hwnd(), &rect);
    return WKRectMake(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
}

void WebKitBrowserWindow::runJavaScriptAlert(WKPageRef, WKStringRef alertText, WKFrameRef, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptAlertResultListenerRef listener, const void* clientInfo)
{
    auto& thisWindow = toWebKitBrowserWindow(clientInfo);
    std::wstring title = L"Alert: ";
    title += createString(adoptWK(WKSecurityOriginCopyToString(securityOrigin)).get());
    auto text = createString(alertText);
    MessageBox(thisWindow.m_hMainWnd, text.c_str(), title.c_str(), MB_OK);
    WKPageRunJavaScriptAlertResultListenerCall(listener);
}

void WebKitBrowserWindow::runJavaScriptConfirm(WKPageRef, WKStringRef message, WKFrameRef, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptConfirmResultListenerRef listener, const void* clientInfo)
{
    auto& thisWindow = toWebKitBrowserWindow(clientInfo);
    std::wstring title = L"Confirm: ";
    title += createString(adoptWK(WKSecurityOriginCopyToString(securityOrigin)).get());
    auto text = createString(message);
    bool result = MessageBox(thisWindow.m_hMainWnd, text.c_str(), title.c_str(), MB_OKCANCEL) == IDOK;
    WKPageRunJavaScriptConfirmResultListenerCall(listener, result);
}

void WebKitBrowserWindow::runJavaScriptPrompt(WKPageRef, WKStringRef message, WKStringRef defaultValue, WKFrameRef, WKSecurityOriginRef securityOrigin, WKPageRunJavaScriptPromptResultListenerRef listener, const void* clientInfo)
{
    auto& thisWindow = toWebKitBrowserWindow(clientInfo);
    std::wstring title = L"Prompt: ";
    title += createString(adoptWK(WKSecurityOriginCopyToString(securityOrigin)).get());
    auto text = createString(message);
    text += L"\nDefault Value: " + createString(defaultValue);
    MessageBox(thisWindow.m_hMainWnd, text.c_str(), title.c_str(), MB_OK);
    WKPageRunJavaScriptPromptResultListenerCall(listener, defaultValue);
}

BrowserWindow.cpp

#include "stdafx.h"
#include "BrowserWindow.h"

void BrowserWindow::setUserAgent()
{
    _bstr_t customUserAgent;
    customUserAgent = L"Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1";

    setUserAgent(customUserAgent);
}

WebkitBrowser.cpp

#include "stdafx.h"
#include "Common.h"
#include "WebKitBrowserWindow.h"
#include <wtf/win/SoftLinking.h>
#include "WebkitBrowser.h"

BrowserMiddleware::BrowserMiddleware(HWND parentHWND):m_parentHWND(parentHWND)
{
	::SetProcessDPIAware();

	auto factory = WebKitBrowserWindow::create;
	m_mainWindow = &MainWindow::create().leakRef();
	static_cast<MainWindow*>(m_mainWindow)->init(factory, m_parentHWND);
}

HWND WINAPI BrowserMiddleware::GetBrowserHWND()
{
	if (m_mainWindow) {
		return static_cast<MainWindow*>(m_mainWindow)->browserHwnd();
	}
	else {
		return nullptr;
	}
}

void WINAPI BrowserMiddleware::loadURL(std::wstring url)
{
	if(m_mainWindow){
		static_cast<MainWindow*>(m_mainWindow)->loadURL(url);
	}
}

void BrowserMiddleware::resetZoom()
{
	if (m_mainWindow) {
		static_cast<MainWindow*>(m_mainWindow)->resetZoom();
	}
}

#########solunar项目##############################################

stdafx.h

#pragma once

// C runtime header
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>

// base header
#include "base/base.h"

solunar_form.h

#pragma once

class SolunarForm : public ui::WindowImplBase
{
public:
	SolunarForm();
	~SolunarForm();

	virtual std::wstring GetSkinFolder() override;
	virtual std::wstring GetSkinFile() override;
	virtual std::wstring GetWindowClassName() const override;

	virtual LRESULT OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

	virtual ui::Control* CreateControl(const std::wstring& pstrClass);

	virtual void InitWindow() override;

	virtual LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) override;

	static const std::wstring kClassName;

private:
	bool OnSelected(ui::EventArgs* arg);
};

webkit_browser.h

#pragma once
#include "/VSProject/solunar/MiniBrowser/WebkitBrowser.h"

class WebkitBrowser : public ui::Control
{
public:
	WebkitBrowser(HWND hwnd);
	~WebkitBrowser();

	virtual void SetInternVisible(bool bVisible = true);
	virtual void SetPos(ui::UiRect rc) override;

	void SetUrl(std::wstring url, ui::Progress *progress);
	void resetZoom();

	bool isPage(HWND hwnd, int value);
	virtual void Paint(ui::IRenderContext* pRender, const ui::UiRect& rcPaint);

protected:
	HWND m_hWnd{ nullptr };
private:
	int m_patch{ 0 };
	BrowserMiddleware* m_browsermiddleware{ nullptr };
	std::wstring m_url;
	ui::Progress* m_progress{nullptr};
};

main.h

#pragma once

class MainThread : public nbase::FrameworkThread
{
public:
	MainThread() : nbase::FrameworkThread("MainThread") {}
	virtual ~MainThread() {}

private:
	/**
	* 虚函数,初始化主线程
	* @return void	无返回值
	*/
	virtual void Init() override;

	/**
	* 虚函数,主线程退出时,做一些清理工作
	* @return void	无返回值
	*/
	virtual void Cleanup() override;
};

solunar_form.cpp

#include "duilib/UIlib.h"
#include "solunar_form.h"
#include "webkit_browser.h"

const std::wstring SolunarForm::kClassName = L"Solunar";

SolunarForm::SolunarForm()
{
}


SolunarForm::~SolunarForm()
{
}

std::wstring SolunarForm::GetSkinFolder()
{
	return L"solunar";
}

std::wstring SolunarForm::GetSkinFile()
{
	return L"solunar.xml";
}

std::wstring SolunarForm::GetWindowClassName() const
{
	return kClassName;
}

LRESULT SolunarForm::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	PostQuitMessage(0L);
	return __super::OnClose(uMsg, wParam, lParam, bHandled);
}

ui::Control* SolunarForm::CreateControl(const std::wstring& pstrClass) {
	if (pstrClass == L"WebkitBrowser")
	{
		return new WebkitBrowser(GetHWND());
	}
	return NULL;
}

void SolunarForm::InitWindow()
{
	auto wb_baidu = static_cast<WebkitBrowser*>(FindControl(L"wb_baidu"));
	auto wb_douyin = static_cast<WebkitBrowser*>(FindControl(L"wb_douyin"));

	auto progress_baidu = static_cast<ui::Progress*>(FindControl(L"progress_baidu"));
	auto progress_douyin = static_cast<ui::Progress*>(FindControl(L"progress_douyin"));

	wb_baidu->SetUrl(L"http://baidu.com/", progress_baidu);
	wb_douyin->SetUrl(L"http://douyin.com/", progress_douyin);

	auto option_baidu = static_cast<ui::Option*>(FindControl(L"option_baidu"));
	auto option_douyin = static_cast<ui::Option*>(FindControl(L"option_douyin"));

	option_baidu->AttachSelect(nbase::Bind(&SolunarForm::OnSelected, this, std::placeholders::_1));
	option_douyin->AttachSelect(nbase::Bind(&SolunarForm::OnSelected, this, std::placeholders::_1));

	AddMessageFilter(this);
}

#define IDT_TIMER 1

LRESULT SolunarForm::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	switch (uMsg)
	{
	case WM_PROGRESS_CHANGE: {
		auto wb_baidu = static_cast<WebkitBrowser*>(FindControl(L"wb_baidu"));
		auto wb_douyin = static_cast<WebkitBrowser*>(FindControl(L"wb_douyin"));
		if (wb_baidu->isPage((HWND)lParam, wParam));
		else if (wb_douyin->isPage((HWND)lParam, wParam));
	}
		break;
	case WM_MOVE: {
		static bool flag = false;
		RECT rect;
		GetWindowRect(GetHWND(), &rect);

		int screenWidth = GetSystemMetrics(SM_CXSCREEN);
		int screenHeight = GetSystemMetrics(SM_CYSCREEN);

		if (rect.left < 0 || rect.top < 0 || rect.right > screenWidth || rect.bottom > screenHeight) {
			if (flag) {
				KillTimer(GetHWND(), IDT_TIMER);
				flag = false;
			}
			flag = true;
			SetTimer(GetHWND(), IDT_TIMER, 200, NULL);
		}
	}
		break;
	case WM_TIMER:
		if (wParam == IDT_TIMER) {
			KillTimer(GetHWND(), IDT_TIMER);

			auto wb_baidu = static_cast<WebkitBrowser*>(FindControl(L"wb_baidu"));
			auto wb_douyin = static_cast<WebkitBrowser*>(FindControl(L"wb_douyin"));
			wb_baidu->SetPos(wb_baidu->GetPos());
			wb_douyin->SetPos(wb_douyin->GetPos());
		}
		break;
	default:
		break;
	}
	return false;
}

bool SolunarForm::OnSelected(ui::EventArgs* arg)
{
	auto option = static_cast<ui::Option*>(arg->pSender);
	std::wstring text = option->GetText();
	auto tab_browser = static_cast<ui::TabBox*>(FindControl(L"tab_browser"));

	if (text == L"百度") {
		tab_browser->SelectItem(0);
	}
	else if (text == L"抖音") {
		tab_browser->SelectItem(1);
	}

	return true;
}

webkit_browser.cpp

#include "duilib/UIlib.h"
#include "/VSProject/solunar/MiniBrowser/WebkitBrowser.h"
#include "webkit_browser.h"

#pragma comment(lib, "D:/VSProject/duilib-netease/libs/x64/base_d.lib")
#pragma comment(lib, "D:/VSProject/duilib-netease/libs/x64/duilib_d.lib")
#pragma comment(lib, "D:/VSProject/solunar/x64/Debug/webkitbrowser.lib")

WebkitBrowser::WebkitBrowser(HWND hwnd)
{
	m_browsermiddleware = new BrowserMiddleware(hwnd);
	if (m_browsermiddleware)
		m_hWnd = m_browsermiddleware->GetBrowserHWND();
}

WebkitBrowser::~WebkitBrowser()
{
	if (m_browsermiddleware)
		delete m_browsermiddleware;
}

void WebkitBrowser::SetInternVisible(bool bVisible)
{
	__super::SetInternVisible(bVisible);
	if (m_hWnd) {
		::ShowWindow(m_hWnd, bVisible);
	}
}
void WebkitBrowser::SetPos(ui::UiRect rc)
{
	__super::SetPos(rc);
	if (m_hWnd) {
		::MoveWindow(m_hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top + m_patch, true);
		m_patch = (++m_patch) % 2;
	}
}

void WebkitBrowser::SetUrl(std::wstring url, ui::Progress *progress)
{
	m_url = url;
	m_progress = progress;
	if (m_browsermiddleware)
		m_browsermiddleware->loadURL(url);
}

void WebkitBrowser::resetZoom()
{
	if (m_browsermiddleware)
		m_browsermiddleware->resetZoom();
}

bool WebkitBrowser::isPage(HWND hwnd, int value)
{
	if (m_hWnd == hwnd) {
		if (m_progress) {
			wchar_t progress[200];
			swprintf_s(progress, L"%s %lld\n", m_url.c_str(), value);
			OutputDebugString(progress);
			m_progress->SetValue(value);
		}
		return true;
	}
	return false;
}

void WebkitBrowser::Paint(ui::IRenderContext* pRender, const ui::UiRect& rcPaint)
{
	if( !::IntersectRect(&m_rcPaint, &rcPaint, &m_rcItem) ) return;
	if (m_hWnd) {
		HDC hDC = pRender->GetDC();
		HDC hdcSrc = ::GetDC(m_hWnd);
		::StretchBlt(hDC, m_rcItem.left, m_rcItem.top, m_rcItem.right - m_rcItem.left, m_rcItem.bottom - m_rcItem.top,
			hdcSrc, 0, 0, m_rcItem.right - m_rcItem.left, m_rcItem.bottom - m_rcItem.top, SRCCOPY);
		::ReleaseDC(m_hWnd, hdcSrc);
	}
	return;
}

main.cpp

#include "stdafx.h"
#include "duilib/UIlib.h"
#include "main.h"
#include "Solunar_form.h"

enum ThreadId
{
	kThreadUI
};

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(lpCmdLine);

	// 创建主线程
	MainThread thread;

	// 执行主线程循环
	thread.RunOnCurrentThreadWithLoop(nbase::MessageLoop::kUIMessageLoop);

	return 0;
}

void MainThread::Init()
{
	INITCOMMONCONTROLSEX InitCtrlEx;

	InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
	InitCtrlEx.dwICC = 0x00004000; // ICC_STANDARD_CLASSES;
	InitCommonControlsEx(&InitCtrlEx);

	// Init COM
	OleInitialize(nullptr);

	nbase::ThreadManager::RegisterThread(kThreadUI);

	// 获取资源路径,初始化全局参数
	std::wstring theme_dir = nbase::win32::GetCurrentModuleDirectory();
#ifdef _DEBUG
	// Debug 模式下使用本地文件夹作为资源
	// 默认皮肤使用 resources\\themes\\default
	// 默认语言使用 resources\\lang\\zh_CN
	// 如需修改请指定 Startup 最后两个参数
	ui::GlobalManager::Startup(theme_dir + L"resources\\", ui::CreateControlCallback(), true);
#else
	// Release 模式下使用资源中的压缩包作为资源
	// 资源被导入到资源列表分类为 THEME,资源名称为 IDR_THEME
	// 如果资源使用的是本地的 zip 文件而非资源中的 zip 压缩包
	// 可以使用 OpenResZip 另一个重载函数打开本地的资源压缩包
	ui::GlobalManager::OpenResZip(MAKEINTRESOURCE(IDR_THEME), L"THEME", "");
	// ui::GlobalManager::OpenResZip(L"resources.zip", "");
	ui::GlobalManager::Startup(L"resources\\", ui::CreateControlCallback(), false);
#endif

	SolunarForm* window = new SolunarForm();

	window->Create(NULL, SolunarForm::kClassName.c_str(), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, 0, false);
	window->CenterWindow();
	window->ShowWindow();
}

void MainThread::Cleanup()
{
	ui::GlobalManager::Shutdown();
	SetThreadWasQuitProperly(true);
	nbase::ThreadManager::UnregisterThread();

	// Shut down COM.
	OleUninitialize();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值