Skip to content

Commit

Permalink
Use icon in window title/taskbar
Browse files Browse the repository at this point in the history
  • Loading branch information
MolotovCherry committed Sep 20, 2023
1 parent 9872821 commit e3aef4a
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 2 deletions.
3 changes: 3 additions & 0 deletions virtual-display-driver-control/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ features = [
"Win32_UI_WindowsAndMessaging",
"Win32_UI_Input_KeyboardAndMouse",
"Win32_Foundation",

"Win32_System_LibraryLoader",
"Win32_Graphics_Gdi",
]

[build-dependencies]
Expand Down
2 changes: 1 addition & 1 deletion virtual-display-driver-control/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ fn main() {
if cfg!(target_os = "windows") {
let mut res = winres::WindowsResource::new();

res.set_icon("icon.ico");
res.set_icon_with_id("icon.ico", "virtual");

// allow high dpi scaling
res.set_manifest(r#"
Expand Down
110 changes: 110 additions & 0 deletions virtual-display-driver-control/src/load_icon.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
use eframe::IconData;
use windows::{
core::w,
Win32::{
Graphics::Gdi::{
CreateCompatibleDC, DeleteDC, GetDIBits, GetObjectA, SelectObject, BITMAP, BITMAPINFO,
BITMAPINFOHEADER, BI_RGB, DIB_RGB_COLORS,
},
System::LibraryLoader::GetModuleHandleW,
UI::WindowsAndMessaging::{
GetIconInfo, LoadImageW, HICON, ICONINFO, IMAGE_ICON, LR_DEFAULTCOLOR,
},
},
};

// Grab the icon from the exe and hand it over to egui
pub fn load_app_icon() -> IconData {
let (mut buffer, width, height) = unsafe {
let h_instance = GetModuleHandleW(None).expect("Failed to get HINSTANCE");
let icon = LoadImageW(
h_instance,
w!("virtual"),
IMAGE_ICON,
512,
512,
LR_DEFAULTCOLOR,
)
.expect("Failed to load icon");

let mut icon_info = ICONINFO::default();
let res = GetIconInfo(HICON(icon.0), &mut icon_info as *mut _);
if res.is_err() {
panic!("Failed to load icon info");
}

let mut bitmap = BITMAP::default();
GetObjectA(
icon_info.hbmColor,
std::mem::size_of::<BITMAP>() as i32,
Some(&mut bitmap as *mut _ as *mut _),
);

let width = bitmap.bmWidth;
let height = bitmap.bmHeight;

let b_size = (width * height * 4) as usize;
let mut buffer = Vec::<u8>::with_capacity(b_size);

let h_dc = CreateCompatibleDC(None);
let h_bitmap = SelectObject(h_dc, icon_info.hbmColor);

let mut bitmap_info = BITMAPINFO::default();
bitmap_info.bmiHeader.biSize = std::mem::size_of::<BITMAPINFOHEADER>() as u32;
bitmap_info.bmiHeader.biWidth = width;
bitmap_info.bmiHeader.biHeight = height;
bitmap_info.bmiHeader.biPlanes = 1;
bitmap_info.bmiHeader.biBitCount = 32;
bitmap_info.bmiHeader.biCompression = BI_RGB.0;
bitmap_info.bmiHeader.biSizeImage = 0;

let res = GetDIBits(
h_dc,
icon_info.hbmColor,
0,
height as u32,
Some(buffer.spare_capacity_mut().as_mut_ptr() as *mut _),
&mut bitmap_info,
DIB_RGB_COLORS,
);
if res == 0 {
panic!("Failed to get RGB DI bits");
}

SelectObject(h_dc, h_bitmap);
DeleteDC(h_dc);

assert_eq!(
bitmap_info.bmiHeader.biSizeImage as usize, b_size,
"returned biSizeImage must equal to b_size"
);

// set the new size
buffer.set_len(bitmap_info.bmiHeader.biSizeImage as usize);

(buffer, width as u32, height as u32)
};

// RGBA -> BGRA
for pixel in buffer.as_mut_slice().chunks_mut(4) {
pixel.swap(0, 2);
}

// Flip the image vertically
let row_size = width as usize * 4; // number of pixels in each row
let row_count = buffer.len() / row_size; // number of rows in the image
for row in 0..row_count / 2 {
// loop through half of the rows
let start = row * row_size; // index of the start of the current row
let end = (row_count - row - 1) * row_size; // index of the end of the current row
for i in 0..row_size {
buffer.swap(start + i, end + i);
}
}

IconData {
rgba: buffer,
width,
height,
}
}
5 changes: 4 additions & 1 deletion virtual-display-driver-control/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod app;
#[cfg(debug_assertions)]
mod backtrace;
mod ipc;
mod load_icon;
mod monitor;
mod panic;
mod popup;
Expand All @@ -16,12 +17,14 @@ use std::error::Error;
use eframe::{epaint::Vec2, NativeOptions};
use panic::set_hook;

use self::load_icon::load_app_icon;

fn main() -> Result<(), Box<dyn Error>> {
set_hook();

let options = NativeOptions {
//min_window_size: Some(Vec2::new(500.0, 400.0)),
icon_data: None,
icon_data: Some(load_app_icon()),
initial_window_size: Some(Vec2::new(1000.0, 800.0)),
transparent: true,
resizable: true,
Expand Down

0 comments on commit e3aef4a

Please sign in to comment.