1
- use anyhow:: Context ;
1
+ use anyhow:: { bail , Context } ;
2
2
use tracing:: warn;
3
3
use windows:: {
4
4
core:: PWSTR ,
@@ -23,17 +23,19 @@ use windows::{
23
23
} ,
24
24
Shell :: { ITaskbarList , TaskbarList } ,
25
25
WindowsAndMessaging :: {
26
- EnumWindows , GetClassNameW , GetWindow , GetWindowLongPtrW ,
27
- GetWindowRect , GetWindowTextW , GetWindowThreadProcessId , IsIconic ,
28
- IsWindowVisible , IsZoomed , SendNotifyMessageW ,
29
- SetForegroundWindow , SetWindowLongPtrW , SetWindowPlacement ,
26
+ EnumWindows , GetClassNameW , GetLayeredWindowAttributes , GetWindow ,
27
+ GetWindowLongPtrW , GetWindowRect , GetWindowTextW ,
28
+ GetWindowThreadProcessId , IsIconic , IsWindowVisible , IsZoomed ,
29
+ SendNotifyMessageW , SetForegroundWindow ,
30
+ SetLayeredWindowAttributes , SetWindowLongPtrW , SetWindowPlacement ,
30
31
SetWindowPos , ShowWindowAsync , GWL_EXSTYLE , GWL_STYLE , GW_OWNER ,
31
- HWND_NOTOPMOST , HWND_TOPMOST , SWP_ASYNCWINDOWPOS ,
32
- SWP_FRAMECHANGED , SWP_NOACTIVATE , SWP_NOCOPYBITS , SWP_NOMOVE ,
33
- SWP_NOOWNERZORDER , SWP_NOSENDCHANGING , SWP_NOSIZE , SWP_NOZORDER ,
34
- SW_HIDE , SW_MAXIMIZE , SW_MINIMIZE , SW_RESTORE , SW_SHOWNA ,
35
- WINDOWPLACEMENT , WINDOW_EX_STYLE , WINDOW_STYLE , WM_CLOSE ,
36
- WPF_ASYNCWINDOWPLACEMENT , WS_CAPTION , WS_CHILD , WS_DLGFRAME ,
32
+ HWND_NOTOPMOST , HWND_TOPMOST , LAYERED_WINDOW_ATTRIBUTES_FLAGS ,
33
+ LWA_ALPHA , LWA_COLORKEY , SWP_ASYNCWINDOWPOS , SWP_FRAMECHANGED ,
34
+ SWP_NOACTIVATE , SWP_NOCOPYBITS , SWP_NOMOVE , SWP_NOOWNERZORDER ,
35
+ SWP_NOSENDCHANGING , SWP_NOSIZE , SWP_NOZORDER , SW_HIDE ,
36
+ SW_MAXIMIZE , SW_MINIMIZE , SW_RESTORE , SW_SHOWNA , WINDOWPLACEMENT ,
37
+ WINDOW_EX_STYLE , WINDOW_STYLE , WM_CLOSE , WPF_ASYNCWINDOWPLACEMENT ,
38
+ WS_CAPTION , WS_CHILD , WS_DLGFRAME , WS_EX_LAYERED ,
37
39
WS_EX_NOACTIVATE , WS_EX_TOOLWINDOW , WS_MAXIMIZEBOX , WS_THICKFRAME ,
38
40
} ,
39
41
} ,
@@ -42,7 +44,7 @@ use windows::{
42
44
43
45
use super :: { iapplication_view_collection, iservice_provider, COM_INIT } ;
44
46
use crate :: {
45
- common:: { Color , LengthValue , Memo , Rect , RectDelta } ,
47
+ common:: { Color , LengthValue , Memo , OpacityValue , Rect , RectDelta } ,
46
48
user_config:: { CornerStyle , HideMethod } ,
47
49
windows:: WindowState ,
48
50
} ;
@@ -394,6 +396,68 @@ impl NativeWindow {
394
396
Ok ( ( ) )
395
397
}
396
398
399
+ pub fn set_opacity (
400
+ & self ,
401
+ opacity_value : OpacityValue ,
402
+ ) -> anyhow:: Result < ( ) > {
403
+ // Make the window layered if it isn't already.
404
+ let ex_style =
405
+ unsafe { GetWindowLongPtrW ( HWND ( self . handle ) , GWL_EXSTYLE ) } ;
406
+
407
+ if ex_style & WS_EX_LAYERED . 0 as isize == 0 {
408
+ unsafe {
409
+ SetWindowLongPtrW (
410
+ HWND ( self . handle ) ,
411
+ GWL_EXSTYLE ,
412
+ ex_style | WS_EX_LAYERED . 0 as isize ,
413
+ ) ;
414
+ }
415
+ }
416
+
417
+ // Get the window's opacity information.
418
+ let mut previous_opacity = u8:: MAX ; // Use maximum opacity as a default.
419
+ let mut flag = LAYERED_WINDOW_ATTRIBUTES_FLAGS :: default ( ) ;
420
+ unsafe {
421
+ GetLayeredWindowAttributes (
422
+ HWND ( self . handle ) ,
423
+ None ,
424
+ Some ( & mut previous_opacity) ,
425
+ Some ( & mut flag) ,
426
+ ) ?;
427
+ }
428
+
429
+ // Fail if window uses color key.
430
+ if flag. contains ( LWA_COLORKEY ) {
431
+ bail ! (
432
+ "Window uses color key for its transparency. The transparency window effect cannot be applied."
433
+ ) ;
434
+ }
435
+
436
+ // Calculate the new opacity value.
437
+ let new_opacity = if opacity_value. is_delta {
438
+ previous_opacity as i16 + opacity_value. amount
439
+ } else {
440
+ opacity_value. amount
441
+ } ;
442
+
443
+ // Clamp new_opacity to a u8.
444
+ let new_opacity =
445
+ new_opacity. clamp ( u8:: MIN as i16 , u8:: MAX as i16 ) as u8 ;
446
+
447
+ // Set the new opacity if needed.
448
+ if new_opacity != previous_opacity {
449
+ unsafe {
450
+ SetLayeredWindowAttributes (
451
+ HWND ( self . handle ) ,
452
+ None ,
453
+ new_opacity,
454
+ LWA_ALPHA ,
455
+ ) ?;
456
+ }
457
+ }
458
+ Ok ( ( ) )
459
+ }
460
+
397
461
/// Gets the window's position, including the window's frame. Excludes
398
462
/// the window's shadow borders.
399
463
///
0 commit comments