2017-09-02 85 views
0

我为将来实施IDeskBand2的项目创建了一个示例模板。IDeskBand2实施崩溃

gacutiregasm作品登记,这也显示在工具栏中。如果我想显示/执行它,资源管理器崩溃。

对于创作,我使用了Mircosoft的文档和pinvoke。

我将我的项目与media-control-deskband进行了比较,并尝试了一些东西(我的项目中的COMInterop文件,比较代码等) 但是找不到原因,猜测是因为实施错误。

这是我的实现。

IDeskBand2接口:

/// <summary> 
/// Gets information about a band object. 
/// </summary> 
[ComImport] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
[Guid("EB0FE172-1A3A-11D0-89B3-00A0C90A90AC")] 
public interface IDeskBand : IDockingWindow 
{ 
    /// <summary> 
    /// Gets state information for a band object. 
    /// </summary> 
    /// <param name="dwBandID">The identifier of the band, assigned by the container. The band object can retain this value if it is required.</param> 
    /// <param name="dwViewMode">The view mode of the band object. One of the following values: DBIF_VIEWMODE_NORMAL, DBIF_VIEWMODE_VERTICAL, DBIF_VIEWMODE_FLOATING, DBIF_VIEWMODE_TRANSPARENT.</param> 
    /// <param name="pdbi">Pointer to a DESKBANDINFO structure that receives the band information for the object. The dwMask member of this structure indicates the specific information that is being requested.</param> 
    /// <returns></returns> 
    [PreserveSig] 
    int GetBandInfo(UInt32 dwBandID, DeskBandInfoViewMode dwViewMode, ref DESKBANDINFO pdbi); 
} 


/// <summary> 
/// Exposes methods to enable and query translucency effects in a deskband object. 
/// </summary> 
[ComImport] 
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 
[Guid("79D16DE4-ABEE-4021-8D9D-9169B261D657")] 
public interface IDeskBand2 : IDeskBand 
{ 
    /// <summary> 
    /// Indicates the deskband's ability to be displayed as translucent. 
    /// </summary> 
    /// <param name="pfCanRenderComposited">When this method returns, contains a BOOL indicating ability.</param> 
    /// <returns>If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.</returns> 
    [PreserveSig] 
    int CanRenderComposited(out bool pfCanRenderComposited); 

    /// <summary> 
    /// Gets the composition state. 
    /// </summary> 
    /// <param name="pfCompositionEnabled">When this method returns, contains a BOOL that indicates state.</param> 
    /// <returns>If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.</returns> 
    [PreserveSig] 
    int GetCompositionState(out bool pfCompositionEnabled); 

    /// <summary> 
    /// Sets the composition state. 
    /// </summary> 
    /// <param name="fCompositionEnabled">TRUE to enable the composition state; otherwise, FALSE.</param> 
    /// <returns>If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.</returns> 
    [PreserveSig] 
    int SetCompositionState(bool fCompositionEnabled); 
} 

IDeskBand2使用:(GetBandInfo功能测试,工作正常。)

/// <summary> 
/// Basic class for a DeskBand object 
/// </summary> 
/// <example> 
/// [Guid("00000000-0000-0000-0000-000000000000")] 
/// [DeskBandInfo("Beispiel Erweiterung", "Diese ist eine Beispiel Erweiterung für die Taskleiste.")] 
/// public class SampleExtension : DeskBand 
/// { /*...*/ } 
/// </example> 
public class DeskBand : UserControl, IDeskBand2 
{ 
    #region Constants 

    private const int S_OK = 0; 
    private const int E_NOTIMPL = unchecked((int)0x80004001); 

    #endregion 

    #region Properties 

    /// <summary> 
    /// Title of the band object, displayed by default on the left or top of the object. 
    /// </summary> 
    [Browsable(true)] 
    [DefaultValue("")] 
    public String Title { get; set; } 

    /// <summary> 
    /// Minimum size of the band object. Default value of -1 sets no minimum constraint. 
    /// </summary> 
    [Browsable(true)] 
    [DefaultValue(typeof(Size), "-1,-1")] 
    public Size MinSize { get; set; } 

    /// <summary> 
    /// Maximum size of the band object. Default value of -1 sets no maximum constraint. 
    /// </summary> 
    [Browsable(true)] 
    [DefaultValue(typeof(Size), "-1,-1")] 
    public Size MaxSize { get; set; } 

    /// <summary> 
    /// Minimum vertical size of the band object. Default value of -1 sets no maximum constraint. (Used when the taskbar is aligned horinzortal.) 
    /// </summary> 
    [Browsable(true)] 
    [DefaultValue(typeof(Size), "-1,-1")] 
    public Size MinSizeVertical { get; set; } 

    /// <summary> 
    /// Says that band object's size must be multiple of this size. Defauilt value of -1 does not set this constraint. 
    /// </summary> 
    [Browsable(true)] 
    [DefaultValue(typeof(Size), "-1,-1")] 
    public Size IntegralSize { get; set; } 

    #endregion 

    #region IDeskBand2 

    public virtual int CanRenderComposited(out bool pfCanRenderComposited) 
    { 
     pfCanRenderComposited = true; 
     return S_OK; 
    } 

    public int GetCompositionState(out bool pfCompositionEnabled) 
    { 
     pfCompositionEnabled = false; 
     return S_OK; 
    } 

    public int SetCompositionState(bool fCompositionEnabled) 
    { 
     fCompositionEnabled = true; 
     return S_OK; 
    } 

    public int GetBandInfo(uint dwBandID, DeskBandInfoViewMode dwViewMode, ref DESKBANDINFO pdbi) 
    { 
     if (pdbi.dwMask.HasFlag(DeskBandInfoMasks.DBIM_MINSIZE)) 
     { 
      // Support for a vertical taskbar 
      // Most examples have no support for a vertical taskbar. Who in hell uses their taskbar vertically? Me! Very practical on a 21:9 monitor. 
      if (dwViewMode.HasFlag(DeskBandInfoViewMode.DBIF_VIEWMODE_FLOATING) || dwViewMode.HasFlag(DeskBandInfoViewMode.DBIF_VIEWMODE_VERTICAL)) 
      { 
       pdbi.ptMinSize.Y = this.MinSizeVertical.Width; 
       pdbi.ptMinSize.X = this.MinSizeVertical.Height; 
      } 
      else 
      { 
       pdbi.ptMinSize.X = this.MinSize.Width; 
       pdbi.ptMinSize.Y = this.MinSize.Height; 
      } 
     } 
     if (pdbi.dwMask.HasFlag(DeskBandInfoMasks.DBIM_MAXSIZE)) 
     { 
      if (dwViewMode.HasFlag(DeskBandInfoViewMode.DBIF_VIEWMODE_FLOATING) || dwViewMode.HasFlag(DeskBandInfoViewMode.DBIF_VIEWMODE_VERTICAL)) 
      { 
       pdbi.ptMaxSize.Y = this.MaxSize.Width; 
       pdbi.ptMaxSize.X = this.MaxSize.Height; 
      } 
      else 
      { 
       pdbi.ptMaxSize.X = this.MaxSize.Width; 
       pdbi.ptMaxSize.Y = this.MaxSize.Height; 
      } 
     } 
     if (pdbi.dwMask.HasFlag(DeskBandInfoMasks.DBIM_INTEGRAL)) 
     { 
      if (dwViewMode.HasFlag(DeskBandInfoViewMode.DBIF_VIEWMODE_FLOATING) || dwViewMode.HasFlag(DeskBandInfoViewMode.DBIF_VIEWMODE_VERTICAL)) 
      { 
       pdbi.ptIntegral.Y = this.IntegralSize.Width; 
       pdbi.ptIntegral.X = this.IntegralSize.Height; 
      } 
      else 
      { 
       pdbi.ptIntegral.X = this.IntegralSize.Width; 
       pdbi.ptIntegral.Y = this.IntegralSize.Height; 
      } 
     } 

     if (pdbi.dwMask.HasFlag(DeskBandInfoMasks.DBIM_ACTUAL)) 
     { 
      if (dwViewMode.HasFlag(DeskBandInfoViewMode.DBIF_VIEWMODE_FLOATING) || dwViewMode.HasFlag(DeskBandInfoViewMode.DBIF_VIEWMODE_VERTICAL)) 
      { 
       pdbi.ptActual.Y = this.Size.Width; 
       pdbi.ptActual.X = this.Size.Height; 
      } 
      else 
      { 
       pdbi.ptActual.X = this.Size.Width; 
       pdbi.ptActual.Y = this.Size.Height; 
      } 
     } 

     if (pdbi.dwMask.HasFlag(DeskBandInfoMasks.DBIM_TITLE)) 
     { 
      pdbi.wszTitle = this.Title; 
     } 

     pdbi.dwModeFlags = DeskBandInfoModeFlag.DBIMF_ALWAYSGRIPPER | DeskBandInfoModeFlag.DBIMF_NORMAL | DeskBandInfoModeFlag.DBIMF_VARIABLEHEIGHT; 
     pdbi.dwMask = pdbi.dwMask | DeskBandInfoMasks.DBIM_BKCOLOR | DeskBandInfoMasks.DBIM_TITLE; // Testen 

     return S_OK; 
    } 

    public int CloseDW([In] uint dwReserved) 
    { 
     Dispose(true); 
     return S_OK; 
    } 

    public int ResizeBorderDW(IntPtr prcBorder, [In, MarshalAs(UnmanagedType.IUnknown)] object punkToolbarSite, bool fReserved) 
    { 
     return E_NOTIMPL; 
    } 

    public int ShowDW([In] bool fShow) 
    { 
     if (fShow) 
      Show(); 
     else 
      Hide(); 

     return S_OK; 
    } 

    public int GetWindow(out IntPtr phwnd) 
    { 
     phwnd = Handle; 
     return S_OK; 
    } 

    public int ContextSensitiveHelp(bool fEnterMode) 
    { 
     return S_OK; 
    } 

    #endregion 

    #region COM 

    [ComRegisterFunctionAttribute] 
    public static void Register(Type t) 
    { 
     string guid = t.GUID.ToString("B"); 

     RegistryKey rkClass = Registry.ClassesRoot.CreateSubKey(@"CLSID\" + guid); 
     RegistryKey rkCat = rkClass.CreateSubKey("Implemented Categories"); 

     DeskBandInfoAttribute[] deskBandInfo = (DeskBandInfoAttribute[]) 
      t.GetCustomAttributes(typeof(DeskBandInfoAttribute), false); 

     string _displayName = t.Name; 
     string _helpText = t.Name; 

     if (deskBandInfo.Length == 1) 
     { 
      if (deskBandInfo[0].DisplayName != null) 
      { 
       _displayName = deskBandInfo[0].DisplayName; 
      } 

      if (deskBandInfo[0].HelpText != null) 
      { 
       _helpText = deskBandInfo[0].HelpText; 
      } 
     } 

     rkClass.SetValue(null, _displayName); 
     rkClass.SetValue("MenuText", _displayName); 
     rkClass.SetValue("HelpText", _helpText); 

     // TaskBar 
     rkCat.CreateSubKey("{00021492-0000-0000-C000-000000000046}"); 
    } 

    [ComUnregisterFunctionAttribute] 
    public static void Unregister(Type t) 
    { 
     string guid = t.GUID.ToString("B"); 

     DeskBandInfoAttribute[] deskBandInfo = (DeskBandInfoAttribute[]) 
      t.GetCustomAttributes(typeof(DeskBandInfoAttribute), false); 

     Registry.ClassesRoot.CreateSubKey(@"CLSID").DeleteSubKeyTree(guid); 
    } 

    #endregion 

    public DeskBand() 
    { 
     InitializeComponent(); 
    } 

    private void InitializeComponent() 
    { 
     this.Name = "DeskBand"; 
    } 
} 
} 

实际扩展没有设计器代码:

namespace TaskbarSampleExt 
{ 
    [Guid("2D53D9CC-0288-4511-A387-B330044C63EA")] 
    [DeskBandInfo("Beispiel Erweiterung", "Diese ist eine Beispiel Erweiterung für die Taskleiste.")] 
    public partial class SampleExtension : DeskBand 
    { 

     public SampleExtension() 
     { 
      this.MinSize = new Size(90, 40); 
      this.MinSizeVertical = new Size(90, 40); 
      this.Title = "Beispiel Erweiterung"; 

      InitializeComponent(); 
     } 

    } 
} 

谢谢你的时间

Brocken files

+0

接口的声明是不正确的,在CLR是gimpy有关COM接口,它们继承除IUnknown或IDispatch之外的接口。 CLR实现接口的方式与C++编译器执行接口的方式不兼容,它在绑定时更灵活,并且不需要按照接口指定的顺序实现它们。对于期望按正确顺序的方法的COM客户端来说太灵活了,您必须包含从基础接口“继承”的方法作为解决方法。只是无聊的复制和粘贴。或者只是简化界面。 –

+0

感谢您的回答,我改变了界面,就像Simon Mourier的第二个例子。 _(在IDeskBand2中添加了IOleWindow,IDockingWindow等接口)现在我可以立即启动扩展程序而不会崩溃,但窗体不显示在任务栏中。 是否可以使用Visual Studio(2017)调试扩展或从资源管理器中读取错误消息? – patbec

+0

发现问题,另外IObjectWithSite接口必须包含在基类中。 谢谢你的解释:)我会继续阅读我自己的主题COM。 – patbec

回答

1

你没有复制/原代码粘贴正确。

在.NET在声明派生接口说IDeskBand2从IDeskBand,你必须重新声明底座接口的所有方法(和递归,你可以省略当然的IUnknown)。

像这样(如果你想派生出现在.NET):

public interface IDeskBand2 : IDeskBand 
{ 
    // IOleWindow 
    new int GetWindow(out IntPtr phwnd); 
    new int ContextSensitiveHelp(bool fEnterMode); 

    // IDockingWindow 
    new int ShowDW(bool bShow); 
    new int CloseDW(UInt32 dwReserved); 
    new int ResizeBorderDW(RECT rcBorder, IntPtr punkToolbarSite, bool fReserved); 

    // IDeskBand 
    new int GetBandInfo(UInt32 dwBandID, DESKBANDINFO.DBIF dwViewMode, ref DESKBANDINFO pdbi); 

    // IDeskBand2 
    int CanRenderComposited(out bool pfCanRenderComposited); 
    .... 
} 

或者干脆像这样:

public interface IDeskBand2 
{ 
    // IOleWindow 
    int GetWindow(out IntPtr phwnd); 
    int ContextSensitiveHelp(bool fEnterMode); 

    // IDockingWindow 
    int ShowDW(bool bShow); 
    int CloseDW(UInt32 dwReserved); 
    int ResizeBorderDW(RECT rcBorder, IntPtr punkToolbarSite, bool fReserved); 

    // IDeskBand 
    int GetBandInfo(UInt32 dwBandID, DESKBANDINFO.DBIF dwViewMode, ref DESKBANDINFO pdbi); 

    // IDeskBand2 
    int CanRenderComposited(out bool pfCanRenderComposited); 
    .... 
} 
+0

感谢您的回答,我改变了界面。 我可以立即启动扩展程序而不会崩溃,但窗体不显示在任务栏中。 仅在基类中实现IDeskBand2就足够了吗? ** class DeskBand:UserControl,IDeskBand2 ** 是否可以调试扩展或从资源管理器读取错误? – patbec

+0

这是另一个问题。然而,官方文档称“从Windows 7起不支持波段”https://msdn.microsoft.com/en-us/library/windows/desktop/bb762064.aspx –

+0

我在这里有一个例子,在Windows 10下没有任何问题。到目前为止,我还没有找到DeskBands的真正替代品。 – patbec