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;
}
  • 效果:

五、优化

  • 还需要优化的是想改成,白色圆形,透明背景。但稍微尝试了下,没改对。
  • 就这样吧,调试太费时间了。题主懒,集帅自行优化吧
相关推荐
代码的乐趣26 分钟前
支持selenium的chrome driver更新到131.0.6778.204
chrome·python·selenium
路人甲ing..3 小时前
jupyter切换内核方法配置问题总结
chrome·python·jupyter
搬码后生仔4 小时前
asp.net core webapi项目中 在生产环境中 进不去swagger
chrome·后端·asp.net
小马哥编程12 小时前
原型链(Prototype Chain)入门
css·vue.js·chrome·node.js·原型模式·chrome devtools
金创想18 小时前
chrome主页被被篡改的修复方法
chrome·主页篡改
东方隐侠安全团队-千里19 小时前
网安瞭望台第17期:Rockstar 2FA 故障催生 FlowerStorm 钓鱼即服务扩张现象剖析
网络·chrome·web安全
m0_7482370520 小时前
Chrome 关闭自动添加https
前端·chrome
张声录11 天前
【ETCD】【实操篇(三)】【ETCDCTL】如何向集群中写入数据
数据库·chrome·etcd
m0_748240021 天前
Chromium 中chrome.webRequest扩展接口定义c++
网络·c++·chrome
冬天vs不冷1 天前
Linux用户与权限管理详解
linux·运维·chrome