2017-09-02 6 views
0

Ich habe eine Beispielvorlage für ein zukünftiges Projekt erstellt, das IDeskBand2 implementiert.IDeskBand2-Implementierung stürzt ab

Die Anmeldung mit gacuti und regasm funktioniert, ist es auch in der Symbolleiste angezeigt. Wenn ich es anzeigen/ausführen möchte, stürzt der Explorer ab.

Für die Erstellung habe ich die Dokumentation von Mircosoft und pinvoke verwendet.

ich mein Projekt mit media-control-deskband verglichen und versucht, einige Dinge (ComInterop Datei in meinem Projekt, zu vergleichen, Code etc.) Aber kann die Ursache nicht finden, denke, es aufgrund einer fehlerhaften Implementierung ist.

Hier ist meine Implementierung.

IDeskBand2 Schnittstelle:

/// <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 im Einsatz: (GetBandInfo Funktion ist getestet und funktioniert einwandfrei.)

/// <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"; 
    } 
} 
} 

Die eigentliche Erweiterung ohne Designer-Code:

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(); 
     } 

    } 
} 

Vielen Dank für Ihre Zeit

Brocken files

+0

Die Interface-Deklarationen sind falsch, die CLR ist gimpy über COM-Schnittstellen, erben Sie eine andere Schnittstelle als IUnknown oder IDispatch. Die Art und Weise, wie die CLR Schnittstellen implementiert, ist inkompatibel mit der Art, wie es ein C++ - Compiler macht, sie ist viel flexibler beim Binden ohne Nachfrage, dass eine Klasse sie in der von der Schnittstelle angegebenen Reihenfolge implementiert. Zu flexibel für einen COM-Client, der die Methoden in der richtigen Reihenfolge erwartet, müssen Sie die Methoden einbeziehen, die von der Basisschnittstelle als Problemumgehung "geerbt" werden. Einfach nur langweilig kopieren und einfügen. Oder einfach die Oberfläche abflachen. –

+0

Danke für die Antwort, ich habe das Interface wie im 2. Beispiel von Simon Mourier geändert. _ (In IDeskBand2 die IOleWindow, IDockingWindow etc. Schnittstellen hinzugefügt) _ Jetzt kann ich die Erweiterung jetzt ohne Absturz starten, aber das Formular wird nicht in der Taskleiste angezeigt. Ist es möglich, die Erweiterung mit Visual Studio (2017) zu debuggen oder die Fehlermeldung von Explorer zu lesen? – patbec

+0

Das Problem gefunden, zusätzlich muss die Schnittstelle IObjectWithSite in der Basisklasse enthalten sein. Danke für deine Erklärung :) Ich werde mich weiter in das Thema COM einlesen. – patbec

Antwort

1

Sie haben nicht den ursprünglichen Code richtig kopieren/einfügen.

In .NET, wenn Sie eine abgeleitete Schnittstelle sagen IDeskBand2 von IDeskBand erklären, Sie müssen neu deklarieren alle Methoden der Basisschnittstelle (und rekursiv können Sie nur IUnknown natürlich weglassen).

wie diese (wenn Sie die Ableitung wollen erscheinen in .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); 
    .... 
} 

oder einfach so:

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

Danke für die Antwort, ich habe die Schnittstelle geändert. Ich kann jetzt die Erweiterung ohne Absturz starten, aber das Formular wird nicht in der Taskleiste angezeigt. Ist es genug, nur IDeskBand2 in der Basisklasse zu implementieren? ** Klasse DeskBand: UserControl, IDeskBand2 ** Ist es möglich, die Erweiterung zu debuggen oder den Fehler aus Explorer zu lesen? – patbec

+0

Das ist eine andere Frage. Allerdings sagt offizielles Dokument "Bands [...] werden nicht von Windows 7 unterstützt" https://msdn.microsoft.com/en-us/library/windows/desktop/bb762064.aspx –

+0

Ich habe hier ein Beispiel dafür funktioniert unter Windows 10 ohne Probleme. Bisher habe ich keine echte Alternative zu DeskBands gefunden. – patbec