狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

.NET 窗口置于最頂層

freeflydom
2025年1月9日 9:24 本文熱度 51

本文介紹如何將窗口置于最頂層,以及解決在頂層顯示時對鎖屏登錄界面的影響等問題。用于實現類似Launcher、系統工具等應用需要窗口層級比Windows開始菜單以及置頂任務欄還要高的場景

一般情況下的窗口置頂,可以設置WPF窗口屬性Topmost=true

也可以使用WIN32-SetWindowPos函數SetWindowPos 函數 (winuser.h) - Win32 apps | Microsoft Learn,設置窗口層級:


 1     /// <summary>設置窗口位置</summary>
 2     /// <param name="hwnd">窗口句柄</param>
 3     /// <param name="hWndInsertAfter">跟隨的窗口句柄</param>
 4     /// <param name="x">X軸坐標</param>
 5     /// <param name="y">Y軸坐標</param>
 6     /// <param name="width"></param>
 7     /// <param name="height"></param>
 8     /// <param name="uFlags">標志位</param>
 9     /// <returns></returns>
10     [DllImport("user32.dll", SetLastError = true)]
11     public static extern bool SetWindowPos(IntPtr hwnd, IntPtr hWndInsertAfter, int x, int y, int width, int height, uint uFlags);

hWndInsertAfter,需要置頂可以傳入參數HWND_TOPMOST(-1)。設置后會在任務欄上方顯示(注意:不是開始菜單顯示時的任務欄,開始菜單顯示后任務欄層級是超級高的,置頂層級需要再次提升,下面會講到)

如果你軟件的置頂需求是常駐,需要解決與其它置頂窗口的層級沖突、搶他們的層級,可以加個定時器:


 1     private nint _handle;
 2     private void MainWindow_Loaded(object sender, RoutedEventArgs e)
 3     {
 4         _handle = new WindowInteropHelper(this).Handle;
 5         SetWindowPos(_handle, -1, 0, 0, 0, 0, 1);
 6         //定時器置頂
 7         var timer = new Timer();
 8         timer.Interval = 100;
 9         timer.Elapsed += Timer_Elapsed;
10         timer.Start();
11     }
12     private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
13     {
14         SetWindowPos(_handle, -1, 0, 0, 0, 0, 1);
15     }

當然,這種窗口置頂方案,遇上比你更流氓的軟件就GG了,會搶來搶去。

最上層置頂(比Windows開始菜單以及置頂任務欄還要高),根據我們MVP毅仔提供的方案 讓你的程序置頂到比系統界面都更上層,就像任務管理器/放大鏡一樣絕對置頂 - walterlv,我們簡單補充整理:

1. 添加app.manifest,并修改requestedExecutionLevel為管理員啟動權限、添加UI置頂權限,詳細的可以了解 /MANIFESTUAC(將 UAC 信息嵌入到清單中) | Microsoft Learn

<requestedExecutionLevel level="requireAdministrator" uiAccess="true" />

這里的窗口置頂可以設置比系統界面更高的置頂,也就是說可以比一些系統級別的置頂還要高,效果同任務管理器的絕對置頂。UiAccess可以幫應用程序繞過用戶界面保護級別、并將輸入引導到桌面上的更高權限窗口

2. 給Windows設置屬性ShowInTaskbar="True"、Topmost="True",

3. 添加程序簽名

4. 將程序放在安裝目錄下C:\Program Files、C:\Program Files (x86)。確保應用程序是從受信任的位置啟動的,因為 Windows 對 UIAccess 應用程序的啟動位置有嚴格限制。

啟動后,窗口層級就比Windows開始菜單以及設置置頂的任務管理器,都要高。窗口層級關系如下,桌面<一般應用窗口<Windows開始菜單<置頂的任務管理器<當前置頂應用Demo:

層級設置沒問題。我們來說下這個方案的幾個問題

1. Windows鎖屏/登錄界面,置頂窗口也會顯示,影響了用戶操作

解決:監聽鎖屏/解鎖屏的事件,添加窗口Topmost修改


 1     public MainWindow()
 2     {
 3         InitializeComponent();
 4         //當前登錄的用戶變化
 5         SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
 6     }
 7     private void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
 8     {
 9         switch (e.Reason)
10         {
11             //解鎖屏
12             case SessionSwitchReason.SessionUnlock:
13                 Topmost = true;
14                 break;
15             //鎖屏
16             case SessionSwitchReason.SessionLock:
17                 Topmost = false;
18                 break;
19         }
20     }

鎖屏后窗口層級隱藏效果:

2. 任務欄圖標如果有需求需要隱藏的話,設置窗口ShowInTaskbar=false無法隱藏圖標

這種情況下,我磨了下代碼,可以這么操作:


1     int exStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
2     // 設置窗口樣式為工具窗口, 不在任務欄顯示
3     exStyle |= WS_EX_TOOLWINDOW;
4     SetWindowLong(hWnd, GWL_EXSTYLE, exStyle);
5     //二次設置任務欄不顯示
6     ShowInTaskbar = false;

使用SetWindowLong來設置窗口為工具窗口樣式,然后更新窗口屬性ShowInTaskbar=false:

WS_EX_TOOLWINDOW 樣式 - 此擴展窗口樣式用于創建工具窗口。Windows 不將此類工具窗口視為常規應用程序窗口,因此默認情況下不在任務欄中顯示

ShowInTaskbar = false - WPF是通過設置ShowInTaskbar來實現不在任務欄中顯示。

注意:需要倆個同時設置,有uiAccess的置頂應用才能隱藏任務欄

我猜測,是uiAccess會影響窗口樣式的應用方式,而WS_EX_TOOLWINDOW結合ShowInTaskbar,明確告訴 WPF 不要在任務欄中顯示此窗口,進一步確保了圖標不顯示出來。

此類場景置頂代碼如下:


 1     public void SetTopmost()
 2     {
 3         IntPtr hWnd = _hWnd;
 4         // 將窗口設置為頂層窗口
 5         Topmost = true;
 6 
 7         int exStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
 8         // 設置窗口樣式為工具窗口, 不在任務欄顯示
 9         exStyle |= WS_EX_TOOLWINDOW;
10         SetWindowLong(hWnd, GWL_EXSTYLE, exStyle);
11         //二次設置任務欄不顯示
12         ShowInTaskbar = false;
13     }

也可以看github倉庫完整代碼  kybs00/WindowsShowTopDemo,需要快速驗證置頂可以用這個WindowShowTopDemo.exe

3. 根據小伙伴反饋,應用設置了uiAccess后,在此進程打開其它軟件,其它軟件內部調用SetParent實現相關功能時會失敗

這個我驗證了下確實如此。目前暫無解決方案、需要具體分析,不過保底可以通過創建子進程、以進程通信去啟動相關應用,來規避。

?轉自https://www.cnblogs.com/kybs0/p/18658281


該文章在 2025/1/9 9:24:52 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved