【问题标题】:How to set a window property through the Windows API (VARIANT_TRUE)?如何通过 Windows API (VARIANT_TRUE) 设置窗口属性?
【发布时间】:2013-05-29 09:47:40
【问题描述】:

我正在使用 Windows 8,我想尝试在我的桌面应用全屏时禁用默认的边缘手势行为。

我找到了这个page,它解释了如何在 C++ 中做到这一点。

我的应用程序是一个 WPF/C# 应用程序,我找到了 Windows Code API PackSetWindowProperty 方法来完成这项工作。

问题

我不知道如何传递正确的参数,这是一个布尔值:

PropertyKey 键 = 新 PropertyKey("32CE38B2-2C9A-41B1-9BC5-B3784394AA44", 2); WindowProperties.SetWindowProperty(this, key, "true");

PropertyKey 键 = 新 PropertyKey("32CE38B2-2C9A-41B1-9BC5-B3784394AA44", 2); WindowProperties.SetWindowProperty(this, key, "-1");

PropertyKey 键 = 新 PropertyKey("32CE38B2-2C9A-41B1-9BC5-B3784394AA44", 2); WindowProperties.SetWindowProperty(this, key, "VARIANT_TRUE");

如你所见,参数必须是一个字符串,但没有人可以工作。

如果有人有想法,请提前致谢!

【问题讨论】:

    标签: c# windows-8 desktop-application gesture windows-api-code-pack


    【解决方案1】:

    更简单的解决方案是使用Windows API Code Pack

    设置System.AppUserModel.PreventPinning属性的代码很简单:

    public static void PreventPinning(Window window)
    {
        var preventPinningProperty = new PropertyKey(new Guid("9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3"), 9);
        WindowProperties.SetWindowProperty(window, preventPinningProperty, "1");
    }
    

    【讨论】:

      【解决方案2】:

      如果您查看原始签名,该函数需要一个 IntPtr 句柄、一个 Guid id 和一个将由数据填充的 PropertyStore 对象。

      HRESULT SHGetPropertyStoreForWindow(
        _In_   HWND hwnd,
        _In_   REFIID riid,
        _Out_  void **ppv
      );
      

      将其翻译成 c# 如下所示:

      [DllImport("shell32.dll", SetLastError = true)]
       static extern int SHGetPropertyStoreForWindow(
              IntPtr handle,
              ref Guid riid,
              out IPropertyStore propertyStore);
      

      你可以从PInvoke.net获取IPropertyStore接口:

      [ComImport, Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
          interface IPropertyStore
          {
              [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
              void GetCount([Out] out uint cProps);
      
              [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
              void GetAt([In] uint iProp, out PropertyKey pkey);
      
              [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
              void GetValue([In] ref PropertyKey key, out object pv);
      
              [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
              void SetValue([In] ref PropertyKey key, [In] ref object pv);
      
              [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
              void Commit();
          }
      

      剩下的唯一事情就是实际实现PropertyStore。 .net 框架中的类似实现可以在例如PrintSystemObject.

      实现这个之后,你应该能够简单地调用方法并设置属性:

      IPropertyStore store = new PropertyStore(); 
      
      //your propery id in guid
      var g = new Guid("32CE38B2-2C9A-41B1-9BC5-B3784394AA44");
      SHGetPropertyStoreForWindow(this.Handle, ref g, out store);
      

      【讨论】:

      • 感谢您的回答!我已经实现了 PropertyStore(感谢 Dictionary)。我在 MainWindow.xaml.cs 中使用了你的最后三行(所以 this.Handle 变成了新的 WindowInteropHelper(this).Handle)。但是 SHGetPropertyStoreForWindow 返回的商店是空的,而我的三个参数不是......知道吗?
      • 您可以先捕获函数的返回值并将其与常见结果进行比较:int result = SHGetPropertyStoreForWindow(this.Handle, ref g, out store); 并将其与常见的HRESULTS进行比较
      • 结果是-2147024809,“无效参数”。我的句柄永远是0,也许是它来的吧。
      • 对了,示例代码仍然适用于旧的 winforms。对于 wpf,您需要:IntPtr windowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle;
      • 是的,我已经尝试过了。我已将代码移到窗口的“已加载”事件中,并且不再出现此错误。但我有一个新的,“不支持这样的接口”:)
      【解决方案3】:

      我不知道如何传递正确的参数,这是一个布尔值。如您所见,参数必须是一个字符串,但没有人可以工作。

      将字符串"1" 传递给true,或将"0" 传递给false

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-26
        • 1970-01-01
        • 1970-01-01
        • 2014-11-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多