Skip to content

Commit cba76cd

Browse files
committed
Add support for removing the app from the Alt+Tab
and the taskbar fixes #14
1 parent b6044b2 commit cba76cd

File tree

6 files changed

+84
-34
lines changed

6 files changed

+84
-34
lines changed

.github/workflows/build.yml

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,20 @@ jobs:
1010
- name: Checkout Code
1111
uses: actions/checkout@v4
1212

13-
- name: Add msbuild to PATH
14-
uses: microsoft/[email protected]
15-
1613
- name: Build Project
17-
run: |
18-
msbuild Invisiwind.sln /p:Configuration=Release /p:Platform=x64 -m
19-
msbuild Invisiwind.sln /p:Configuration=Release /p:Platform=x86 -m
14+
run: cargo build --release
2015

2116
- name: Generate zip bundle
22-
run: 7z a -tzip Invisiwind.zip .\hide.ahk .\Build\bin\Release\*.dll .\Build\bin\Release\*.exe
17+
run: 7z a -tzip Invisiwind.zip .\hide.ahk .\target\release\*.dll .\target\release\*.exe
2318

2419
- name: Build Installer
2520
run: iscc .\Misc\inno.iss
2621

2722
- name: Publish latest pre-release
28-
uses: marvinpinto/action-automatic-releases@latest
23+
uses: softprops/action-gh-release@v2
2924
with:
30-
repo_token: "${{ secrets.GITHUB_TOKEN }}"
31-
automatic_release_tag: "latest"
25+
token: "${{ secrets.GITHUB_TOKEN }}"
26+
tag_name: latest
3227
prerelease: true
3328
files: |
3429
Invisiwind.zip

Misc/inno.iss

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
33

44
#define MyAppName "Invisiwind"
5-
#define MyAppVersion "1.1.4"
5+
#define MyAppVersion "2.0.0"
66
#define MyAppPublisher "Radiantly"
77
#define MyAppURL "https://github.com/radiantly/Invisiwind"
88

@@ -46,8 +46,8 @@ Name: "english"; MessagesFile: "compiler:Default.isl"
4646
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
4747

4848
[Files]
49-
Source: "..\Build\bin\Release\*.exe"; DestDir: "{app}"; Flags: ignoreversion
50-
Source: "..\Build\bin\Release\*.dll"; DestDir: "{app}"; Flags: ignoreversion
49+
Source: "..\target\release\*.exe"; DestDir: "{app}"; Flags: ignoreversion
50+
Source: "..\target\release\*.dll"; DestDir: "{app}"; Flags: ignoreversion
5151

5252
[Icons]
5353
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{code:MyAppExeName}"

injector/src/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub fn start() {
9090

9191
processes.into_iter().for_each(|(pid, process)| {
9292
if let Some(hwnds) = windows.remove(&pid) {
93-
injector::set_window_props(process, &hwnds, cli.hide_args.hide);
93+
injector::set_window_props(process, &hwnds, cli.hide_args.hide, false);
9494
} else {
9595
print_error(format!(
9696
"Cannot find any top level windows for pid {:?}",

injector/src/gui.rs

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ use std::thread;
88
#[derive(Debug)]
99
enum WorkerEvents {
1010
UPDATE,
11-
HIDE(u32, u32),
12-
SHOW(u32, u32),
11+
HIDE(u32, u32, bool),
12+
SHOW(u32, u32, bool),
1313
}
1414

1515
#[derive(Debug)]
1616
struct Gui {
1717
windows: Arc<Mutex<Vec<WindowInfo>>>,
1818
sender: crossbeam_channel::Sender<WorkerEvents>,
19+
hide_taskbar_icons: bool,
1920
}
2021

2122
impl Gui {
@@ -34,19 +35,23 @@ impl Gui {
3435
*windowst.lock().unwrap() = mem::take(&mut w);
3536
println!("populating done");
3637
}
37-
WorkerEvents::HIDE(pid, hwnd) => {
38+
WorkerEvents::HIDE(pid, hwnd, show_on_taskbar) => {
3839
println!("wanna hide {:?}", hwnd);
39-
injector::set_window_props_with_pid(pid, hwnd, true);
40+
injector::set_window_props_with_pid(pid, hwnd, true, show_on_taskbar);
4041
}
41-
WorkerEvents::SHOW(pid, hwnd) => {
42+
WorkerEvents::SHOW(pid, hwnd, show_on_taskbar) => {
4243
println!("wanna show {:?}", hwnd);
43-
injector::set_window_props_with_pid(pid, hwnd, false);
44+
injector::set_window_props_with_pid(pid, hwnd, false, show_on_taskbar);
4445
}
4546
}
4647
}
4748
});
4849

49-
Gui { windows, sender }
50+
Gui {
51+
windows,
52+
sender,
53+
hide_taskbar_icons: false,
54+
}
5055
}
5156
}
5257

@@ -67,6 +72,7 @@ impl eframe::App for Gui {
6772
}
6873
egui::CentralPanel::default().show(ctx, |ui| {
6974
ui.heading("Hide applications");
75+
ui.add_space(4.0);
7076

7177
egui::ScrollArea::vertical().show(ui, |ui| {
7278
for window_info in self.windows.lock().unwrap().iter_mut() {
@@ -75,13 +81,28 @@ impl eframe::App for Gui {
7581
ui.checkbox(&mut window_info.hidden, &window_info.title);
7682
if checkbox_response.changed() {
7783
let event = if window_info.hidden {
78-
WorkerEvents::HIDE(window_info.pid, window_info.hwnd)
84+
WorkerEvents::HIDE(
85+
window_info.pid,
86+
window_info.hwnd,
87+
!self.hide_taskbar_icons,
88+
)
7989
} else {
80-
WorkerEvents::SHOW(window_info.pid, window_info.hwnd)
90+
WorkerEvents::SHOW(
91+
window_info.pid,
92+
window_info.hwnd,
93+
!self.hide_taskbar_icons,
94+
)
8195
};
8296
self.sender.send(event).unwrap();
8397
}
8498
}
99+
ui.add_space(10.0);
100+
ui.collapsing("Advanced settings", |ui| {
101+
ui.checkbox(
102+
&mut self.hide_taskbar_icons,
103+
"Hide from Alt+Tab and Taskbar",
104+
)
105+
});
85106
});
86107
});
87108
}

injector/src/injector.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,39 +95,53 @@ pub fn get_top_level_windows() -> Vec<WindowInfo> {
9595
top_level_windows
9696
}
9797

98-
pub fn inject_and_get_remote_proc<F>(
99-
target_process: OwnedProcess,
100-
proc_name: &str,
101-
) -> RemoteRawProcedure<F>
98+
pub fn inject_and_get_remote_proc<F>(syringe: &Syringe, proc_name: &str) -> RemoteRawProcedure<F>
10299
where
103100
F: RawRpcFunctionPtr,
104101
{
105-
let syringe = Syringe::for_process(target_process);
106-
107102
let mut dll_path = env::current_exe().unwrap();
108103
dll_path.pop();
109104
dll_path.push("payload.dll");
110105

111106
let injected_payload = syringe.find_or_inject(dll_path).unwrap();
107+
112108
return unsafe { syringe.get_raw_procedure::<F>(injected_payload, proc_name) }
113109
.unwrap()
114110
.unwrap();
115111
}
116112

117-
pub fn set_window_props(target_process: OwnedProcess, hwnds: &[u32], hide: bool) {
113+
pub fn set_window_props(
114+
target_process: OwnedProcess,
115+
hwnds: &[u32],
116+
hide: bool,
117+
show_on_taskbar: bool,
118+
) {
119+
let syringe = Syringe::for_process(target_process);
120+
118121
let remote_proc = inject_and_get_remote_proc::<extern "system" fn(HWND, bool) -> bool>(
119-
target_process,
122+
&syringe,
120123
"SetWindowVisibility",
121124
);
122125

126+
let remote_proc2 = inject_and_get_remote_proc::<extern "system" fn(HWND, bool) -> bool>(
127+
&syringe,
128+
"ShowOnTaskBar",
129+
);
130+
123131
for hwnd in hwnds {
124132
remote_proc
125133
.call(HWND(hwnd.clone() as *mut _), hide)
126134
.unwrap();
135+
136+
if !show_on_taskbar {
137+
remote_proc2
138+
.call(HWND(hwnd.clone() as *mut _), !hide)
139+
.unwrap();
140+
}
127141
}
128142
}
129143

130-
pub fn set_window_props_with_pid(pid: u32, hwnd: u32, hide: bool) {
144+
pub fn set_window_props_with_pid(pid: u32, hwnd: u32, hide: bool, show_on_taskbar: bool) {
131145
let target_process = OwnedProcess::from_pid(pid).unwrap();
132-
set_window_props(target_process, &[hwnd], hide);
146+
set_window_props(target_process, &[hwnd], hide, show_on_taskbar);
133147
}

payload/src/lib.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use windows::Win32::{
22
Foundation::HWND,
3-
UI::WindowsAndMessaging::{SetWindowDisplayAffinity, WDA_EXCLUDEFROMCAPTURE, WDA_NONE},
3+
UI::WindowsAndMessaging::{
4+
GWL_EXSTYLE, GetWindowLongW, SetWindowDisplayAffinity, SetWindowLongW,
5+
WDA_EXCLUDEFROMCAPTURE, WDA_NONE, WS_EX_APPWINDOW, WS_EX_TOOLWINDOW,
6+
},
47
};
58

69
#[unsafe(no_mangle)]
@@ -13,3 +16,20 @@ pub extern "system" fn SetWindowVisibility(hwnd: HWND, hide: bool) -> bool {
1316
let result = unsafe { SetWindowDisplayAffinity(hwnd, dwaffinity) };
1417
return !result.is_err();
1518
}
19+
20+
#[unsafe(no_mangle)]
21+
pub extern "system" fn ShowOnTaskBar(hwnd: HWND, show: bool) -> bool {
22+
let mut style = unsafe { GetWindowLongW(hwnd, GWL_EXSTYLE) };
23+
if style == 0 {
24+
return false;
25+
}
26+
if show {
27+
style |= WS_EX_APPWINDOW.0 as i32;
28+
style &= (!WS_EX_TOOLWINDOW.0) as i32;
29+
} else {
30+
style |= WS_EX_TOOLWINDOW.0 as i32;
31+
style &= (!WS_EX_APPWINDOW.0) as i32;
32+
}
33+
unsafe { SetWindowLongW(hwnd, GWL_EXSTYLE, style) };
34+
true
35+
}

0 commit comments

Comments
 (0)