2017-09-02 86 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