026.(娱乐)魔改浏览器-任务栏图标右上角加提示徽章

一、目标:

  • windows中,打开chromium,任务栏中会出现一个chromium的图标。
  • 我们的目标是给这个图标的右上角,加上"有1条新消息"的小提示图标,也叫徽章(badge)
  • 注意:本章节纯属娱乐,有需要的集帅可以学习模仿。

具体效果如下:

二、修改源码:

  • 打开:\ui\views\view.cc
1.头部追加:
c 复制代码
#include <Shobjidl.h>
#include <windows.h>
#include <shellapi.h>
2.找到:
c 复制代码
bool View::OnMousePressed(const ui::MouseEvent& event) {
  return false;
}

OnMousePressed()函数是可以点击事件,每次点击浏览器头部时都会触发这个函数。

3.替换为:
c 复制代码
void UpdateTaskbarIcon(HWND hwnd, HICON hIcon) {
    ITaskbarList3* pTaskbarList = nullptr;
	HRESULT hr = CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pTaskbarList));
	if (SUCCEEDED(hr)) {
		pTaskbarList->SetOverlayIcon(hwnd, hIcon, L"有1条新消息");
		pTaskbarList->Release();  
		LOG(ERROR) << "SetOverlayIcon成功调用"; 
	}else{
		LOG(ERROR) << "ERRORERRORERROR"; 
	}
}

void SetTaskbarIconOverlay(HWND hwnd) {
	wchar_t className[256];
	GetClassName(hwnd, className, sizeof(className) / sizeof(wchar_t));
	LOG(ERROR) << "窗口类名"; 
	LOG(ERROR) << className; 
    LPCWSTR iconPath = L"C:/Users/Administrator/Desktop/favicon.ico";
	HICON hIcon = (HICON)LoadImage(NULL, iconPath, IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
    if (!hIcon) {
		MessageBox(hwnd, L"无法加载图标。", L"错误", MB_OK | MB_ICONERROR);
    } else {
        UpdateTaskbarIcon(hwnd, hIcon);
    }
}


bool View::OnMousePressed(const ui::MouseEvent& event) {
	CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
	
    LPCWSTR className = L"Chrome_WidgetWin_1";
    LPCWSTR windowName = nullptr; // 如果你不知道窗口的标题,可以设置为nullptr

    // 获取窗口句柄
    HWND hwnd = FindWindow(className, windowName);
	if (hwnd != NULL) {
		HWND parentHwnd = GetParent(hwnd);
		if (parentHwnd == NULL) {
			LOG(ERROR) << "hwnd 是一个顶级窗口"; 
		} else {
			LOG(ERROR) << "hwnd 不是一个顶级窗口"; 
		}
	}
	LOG(ERROR) << hwnd;
	
	wchar_t windowTitle[256];
	GetWindowText(hwnd, windowTitle, sizeof(windowTitle) / sizeof(wchar_t));
	LOG(ERROR) << "窗口标题"; 
	LOG(ERROR) << windowTitle; 
	
	bool isVisible = IsWindowVisible(hwnd);
	LOG(ERROR) << "isVisible"; 
	LOG(ERROR) << isVisible; 
	
	DWORD processId;
	GetWindowThreadProcessId(hwnd, &processId);
	LOG(ERROR) << "processId"; 
	LOG(ERROR) << processId; 

	SetTaskbarIconOverlay(hwnd);
	CoUninitialize();
  return false;
}

注意:

  1. 将ico图标位置(变量iconPath )替换成你图标的位置,必须是ico其他格式不行。
  2. LOG(ERROR)是用来打印错误日志的,可以忽略
  3. 最终实现原理是调用win32编程api里的SetOverlayIcon()函数。
4.编译
复制代码
ninja  -C  out/Default chrome
  • 编译完成后,打开浏览器,一旦点击浏览器头部,图标就出现啦!

三、代码生成数字ico

  • 有的同学想到要右上角希望是数字图标,我们总不能准备99张ico图标吧。
  • 于是我们用代码在内存中生成ico

将上面的代码改成:

c 复制代码
HICON CreateNumberIcon(int number) {
    if (number > 99) {
        number = 99;
    }

    // 创建一个16x16的位图
    HDC hdcScreen = GetDC(NULL);
    HDC hdcMem = CreateCompatibleDC(hdcScreen);
    BITMAPINFO bmi = {};
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = 16;
    bmi.bmiHeader.biHeight = -16; // 负值表示自上而下
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 32; // 32位带透明通道
    bmi.bmiHeader.biCompression = BI_RGB;
    bmi.bmiHeader.biSizeImage = 0;
    bmi.bmiHeader.biXPelsPerMeter = 0;
    bmi.bmiHeader.biYPelsPerMeter = 0;
    bmi.bmiHeader.biClrUsed = 0;
    bmi.bmiHeader.biClrImportant = 0;

    void* pBits;
    HBITMAP hBitmap = CreateDIBSection(hdcMem, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0);
    HBITMAP hOldBitmap = (HBITMAP)SelectObject(hdcMem, hBitmap);

    // 设置背景为透明
    memset(pBits, 0, 16 * 16 * 4); // 初始化位图为透明

    // 设置字体和颜色
    HFONT hFont = CreateFont(14, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial");
    HFONT hOldFont = (HFONT)SelectObject(hdcMem, hFont);
    SetTextColor(hdcMem, RGB(255, 0, 0)); // 设置数字颜色为红色
    SetBkMode(hdcMem, TRANSPARENT);

    // 计算数字的居中位置
    std::wstring text = std::to_wstring(number);
    RECT rect = {0, 0, 16, 16};
    DrawText(hdcMem, text.c_str(), text.length(), &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

    // 清理
    SelectObject(hdcMem, hOldFont);
    DeleteObject(hFont);
    SelectObject(hdcMem, hOldBitmap);
    DeleteDC(hdcMem);
    ReleaseDC(NULL, hdcScreen);

    // 将位图转换为图标
    ICONINFO iconInfo = { TRUE, 0, 0, hBitmap, hBitmap };
    HICON hIcon = CreateIconIndirect(&iconInfo);
    DeleteObject(hBitmap);

    return hIcon;
}

void UpdateTaskbarIcon(HWND hwnd, HICON hIcon) {
    ITaskbarList3* pTaskbarList = nullptr;
	HRESULT hr = CoCreateInstance(CLSID_TaskbarList, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pTaskbarList));
	if (SUCCEEDED(hr)) {
		pTaskbarList->SetOverlayIcon(hwnd, hIcon, L"新消息");
		pTaskbarList->Release();  
		LOG(ERROR) << "SetOverlayIcon成功调用"; 
	}else{
		LOG(ERROR) << "ERRORERRORERROR"; 
	}
}


void SetTaskbarIconOverlay(HWND hwnd) {
	wchar_t className[256];
	GetClassName(hwnd, className, sizeof(className) / sizeof(wchar_t));
	LOG(ERROR) << "窗口类名"; 
	LOG(ERROR) << className; 
    //LPCWSTR iconPath = L"C:/Users/Administrator/Desktop/favicon.ico";
	//HICON hIcon = (HICON)LoadImage(NULL, iconPath, IMAGE_ICON, 16, 16, LR_LOADFROMFILE);
	HICON hIcon = CreateNumberIcon(72);
    if (!hIcon) {
		MessageBox(hwnd, L"无法加载图标。", L"错误", MB_OK | MB_ICONERROR);
    } else {
        UpdateTaskbarIcon(hwnd, hIcon);
    }
}


bool View::OnMousePressed(const ui::MouseEvent& event) {
	CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
	
    LPCWSTR className = L"Chrome_WidgetWin_1";
    LPCWSTR windowName = nullptr; // 如果你不知道窗口的标题,可以设置为nullptr
    // 获取窗口句柄
    HWND hwnd = FindWindow(className, windowName);
	SetTaskbarIconOverlay(hwnd);
	
	bool isVisible = IsWindowVisible(hwnd);
	LOG(ERROR) << "isVisible"; 
	LOG(ERROR) << isVisible; 
	
	CoUninitialize();
  return false;
}
  • 效果:

五、优化

  • 还需要优化的是想改成,白色圆形,透明背景。但稍微尝试了下,没改对。
  • 就这样吧,调试太费时间了。题主懒,集帅自行优化吧
相关推荐
耳边轻语99920 小时前
chrome升级,只能手动添加网站搜索引擎 网站格式怎么写
chrome
小比特_蓝光20 小时前
从环境变量到进程地址空间:Linux系统学习笔记
前端·chrome
kyriewen111 天前
项目做了一半想重写?这套前端架构让你少走3年弯路
前端·javascript·chrome·架构·ecmascript·html5
土拨鼠爱coding1 天前
Chrome插件 - DIY Theme
前端·chrome
|晴 天|2 天前
从零打造现代化个人博客:Vue 3 + TypeScript + Element Plus 完整实战
javascript·css·chrome·typescript·html5·webstorm
啃玉米的艺术家2 天前
监控项目------(boa移植问题)
前端·chrome
不搞数学的汤老师2 天前
WSL 连接宿主机 Chrome DevTools
chrome·chrome devtools
zhuyan1083 天前
Linux 系统磁盘爆满导致无法启动修复指南
前端·chrome
Watermelo6173 天前
理解 JavaScript 中的“ / ”:路径、资源与目录、nginx配置、请求、转义的那些事
前端·javascript·vue.js·chrome·nginx·正则表达式·seo
L.Cheng4 天前
谷歌浏览器如何禁用自动更新_Chrome关闭后台升级程序
前端·chrome