C#实现窗口禁止固定到任务栏的完整指南

转载好友:https://www.cnblogs.com/wuty/p/19027532 

Windows应用程序开发中,有时我们需要控制窗口的某些系统级行为,比如禁止用户将应用程序窗口固定到任务栏。本文将详细介绍如何使用C#和Windows API实现这一功能,并深入解析相关技术原理

默认状态

image

 

通过 SHGetPropertyStoreForWindow 设置 System.AppUserModel.PreventPinning 属性 (System.AppUserModel.PreventPinning - Win32 apps | Microsoft Learn),达到如下效果 

 

 

image

 

 

 

  public class NativeWin32
  {
      [DllImport("shell32.dll")]
      public static extern int SHGetPropertyStoreForWindow(IntPtr hwnd, ref Guid riid, out IPropertyStore propertyStore);

      [DllImport("ole32.dll")]
      public static extern int PropVariantClear(ref PROPVARIANT pvar);

      // Define IPropertyStore interface
      [ComImport]
      [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
      [Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
      public interface IPropertyStore
      {
          void GetCount(out uint cProps);
          void GetAt(uint iProp, out PROPERTYKEY pkey);
          void GetValue(ref PROPERTYKEY key, out PROPVARIANT pv);
          void SetValue(ref PROPERTYKEY key, ref PROPVARIANT pv);
          void Commit();
      }

      // Define IID for IPropertyStore
      public static Guid IID_IPropertyStore = new Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99");

      // Define PROPERTYKEY struct
      [StructLayout(LayoutKind.Sequential, Pack = 4)]
      public struct PROPERTYKEY
      {
          public Guid fmtid;
          public uint pid;

          public PROPERTYKEY(Guid fmtid, uint pid)
          {
              this.fmtid = fmtid;
              this.pid = pid;
          }
      }

      // Define PROPVARIANT structure (simplified, we'll use a simple one for bool)
      [StructLayout(LayoutKind.Explicit)]
      public struct PROPVARIANT
      {
          // We'll only implement the necessary part for boolean
          [FieldOffset(0)] public ushort vt;
          [FieldOffset(8)] public byte boolVal;

          public void SetValue(bool value)
          {
              // VT_BOOL
              vt = 11;
              boolVal = value ? (byte)1 : (byte)0;
          }
      }
  } 

 应用使用:

/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        SourceInitialized += MainWindow_SourceInitialized;
    }

    private void MainWindow_SourceInitialized(object sender, EventArgs e)
    {
        SetPinning();
    }

    private void SetPinning()
    {
        IntPtr hwnd = new WindowInteropHelper(this).Handle;

        // Define the property key for System.AppUserModel.PreventPinning
        NativeWin32.PROPERTYKEY propKey = new NativeWin32.PROPERTYKEY(new Guid("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}"), 9);

        // Get the IPropertyStore for the window
        NativeWin32.IPropertyStore propStore;
        int hr = NativeWin32.SHGetPropertyStoreForWindow(hwnd, ref NativeWin32.IID_IPropertyStore, out propStore);
        if (hr != 0) // if failed
        {
            Marshal.ThrowExceptionForHR(hr);
        }

        try
        {
            // Create a PROPVARIANT with bool value: true
            NativeWin32.PROPVARIANT pv = new NativeWin32.PROPVARIANT();
            pv.SetValue(true);

            // Set the property
            propStore.SetValue(ref propKey, ref pv);

            // We must free the PROPVARIANT
            NativeWin32.PropVariantClear(ref pv);
        }
        finally
        {
            // Release the IPropertyStore
            Marshal.ReleaseComObject(propStore);
        }
    }
}

参考资料:System.AppUserModel.PreventPinning - Win32 apps | Microsoft Learn

posted on 2025-08-08 11:03  TanZhiWei  阅读(16)  评论(0)    收藏  举报