Memperbarui:
Menurut @donovan, WPF modern mendukung ini secara asli, melalui pengaturan
ShowInTaskbar="False"
dan Visibility="Hidden"
di XAML. (Saya belum menguji ini, tetapi memutuskan untuk meningkatkan visibilitas komentar)
Jawaban asli:
Ada dua cara untuk menyembunyikan jendela dari pengalih tugas di Win32 API:
- untuk menambahkan
WS_EX_TOOLWINDOW
gaya jendela yang diperluas - itulah pendekatan yang tepat.
- untuk menjadikannya jendela anak dari jendela lain.
Sayangnya, WPF tidak mendukung kontrol fleksibel atas gaya jendela seperti Win32, sehingga jendela dengan WindowStyle=ToolWindow
berakhir dengan gaya WS_CAPTION
dan default WS_SYSMENU
, yang menyebabkannya memiliki keterangan dan tombol tutup. Di sisi lain, Anda dapat menghapus dua gaya ini dengan mengatur WindowStyle=None
, namun itu tidak akan mengatur WS_EX_TOOLWINDOW
gaya yang diperluas dan jendela tidak akan disembunyikan dari pengalih tugas.
Untuk memiliki jendela WPF WindowStyle=None
yang juga tersembunyi dari pengalih tugas, salah satu dari dua cara dapat dilakukan:
- gunakan kode contoh di atas dan jadikan jendela sebagai jendela anak dari jendela alat kecil yang tersembunyi
- memodifikasi gaya jendela agar juga menyertakan
WS_EX_TOOLWINDOW
gaya yang diperluas.
Saya pribadi lebih suka pendekatan kedua. Kemudian lagi, saya melakukan beberapa hal lanjutan seperti memperluas kaca di area klien dan mengaktifkan gambar WPF di caption, jadi sedikit interop bukanlah masalah besar.
Berikut kode contoh untuk pendekatan solusi interop Win32. Pertama, bagian XAML:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300"
ShowInTaskbar="False" WindowStyle="None"
Loaded="Window_Loaded" >
Tidak ada yang terlalu mewah di sini, kami hanya mendeklarasikan jendela dengan WindowStyle=None
dan ShowInTaskbar=False
. Kami juga menambahkan penangan ke acara Loaded di mana kami akan memodifikasi gaya jendela diperpanjang. Kami tidak dapat melakukan pekerjaan itu di konstruktor, karena belum ada pegangan jendela pada saat itu. Pengendali acara itu sendiri sangat sederhana:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WindowInteropHelper wndHelper = new WindowInteropHelper(this);
int exStyle = (int)GetWindowLong(wndHelper.Handle, (int)GetWindowLongFields.GWL_EXSTYLE);
exStyle |= (int)ExtendedWindowStyles.WS_EX_TOOLWINDOW;
SetWindowLong(wndHelper.Handle, (int)GetWindowLongFields.GWL_EXSTYLE, (IntPtr)exStyle);
}
Dan deklarasi interop Win32. Saya telah menghapus semua gaya yang tidak perlu dari enum, hanya untuk menjaga kode contoh di sini tetap kecil. Juga, sayangnya SetWindowLongPtr
titik masuk tidak ditemukan di user32.dll pada Windows XP, oleh karena itu trik dengan merutekan panggilan melalui SetWindowLong
alih - alih.
#region Window styles
[Flags]
public enum ExtendedWindowStyles
{
// ...
WS_EX_TOOLWINDOW = 0x00000080,
// ...
}
public enum GetWindowLongFields
{
// ...
GWL_EXSTYLE = (-20),
// ...
}
[DllImport("user32.dll")]
public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
{
int error = 0;
IntPtr result = IntPtr.Zero;
// Win32 SetWindowLong doesn't clear error on success
SetLastError(0);
if (IntPtr.Size == 4)
{
// use SetWindowLong
Int32 tempResult = IntSetWindowLong(hWnd, nIndex, IntPtrToInt32(dwNewLong));
error = Marshal.GetLastWin32Error();
result = new IntPtr(tempResult);
}
else
{
// use SetWindowLongPtr
result = IntSetWindowLongPtr(hWnd, nIndex, dwNewLong);
error = Marshal.GetLastWin32Error();
}
if ((result == IntPtr.Zero) && (error != 0))
{
throw new System.ComponentModel.Win32Exception(error);
}
return result;
}
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
private static extern IntPtr IntSetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
private static extern Int32 IntSetWindowLong(IntPtr hWnd, int nIndex, Int32 dwNewLong);
private static int IntPtrToInt32(IntPtr intPtr)
{
return unchecked((int)intPtr.ToInt64());
}
[DllImport("kernel32.dll", EntryPoint = "SetLastError")]
public static extern void SetLastError(int dwErrorCode);
#endregion