Узел IDeskBand в форме Windows

#c# #.net #winforms #interop #winforms-interop

#c# #.net #winforms #взаимодействие #winforms-взаимодействие

Вопрос:

Я пытаюсь отобразить адресную панель инструментов с панели задач Windows в моей собственной WinForm. Я могу получить CLSID адреса toobar ( {01E04581-4EEE-11d0-BFE9-00AA005B4383} ), и я могу получить IDeskBand ссылку на него. Но … что тогда?

 Guid bandCLSID = new Guid("{01E04581-4EEE-11d0-BFE9-00AA005B4383}");
Type bandType = Type.GetTypeFromCLSID(bandCLSID);
IDeskBand deskband = (IDeskBand)Activator.CreateInstance(bandType);
  

Я пытался разместить его в AxHost , но адресная панель инструментов не является элементом управления ActiveX. Я пытался вызвать

 (deskband as IOleObjectWithSite).SetSite(various interfaces);
  

или

 (deskband as IDockingWindow).ShowDW(true);
  

а также различные другие интерфейсы и их методы, но, похоже, ничто из того, что я делаю, меня никуда не приводит. Я был бы вне себя от радости, если бы действительно мог видеть, что панель инструментов появляется где угодно. Но, похоже, я не могу преодолеть разрыв между наличием IDeskBand ссылки и подключением ее к моей форме Windows.

Кто-нибудь пробовал это раньше и продвинулся дальше, чем я?

Комментарии:

1. Можете ли вы предоставить более подробную информацию о том, какие функциональные возможности вам нужны из адресной панели инструментов DeskBand? Начиная с Windows 7, этот интерфейс устарел, поэтому в любом случае он может не поддерживаться в будущих версиях Windows.

2. Я хочу иметь возможность помещать адресную панель и другие настольные группы, такие как ссылки или даже пользовательские, в мою WinForm, и отображать их так, как они отображаются на панели задач.

3. Так что, возможно, это не IDeskBand то, что я хочу реализовать. Я почти уверен, что панели инструментов адреса и ссылки являются COM-объектами DeskBand, поэтому я перешел к IDeskBand . Итак, что я действительно пытаюсь сделать, это запросить целевой COM-объект, что я могу сделать, чтобы получить соответствующий Guid, создать его экземпляр, что я и делаю с Activator.CreateInstance . У меня все рушится, когда я пытаюсь перейти к размещению COM-объекта в моей WinForm.

Ответ №1:

Я не думаю, что это поддерживается, поскольку предполагается, что DeskBand размещается в Explorer, но вот пример кода формы, который демонстрирует, как это сделать, и должен помочь вам начать.

Идея в том, что вы должны быть «Сайтом», а не проводником. Если вы посмотрите на документацию здесь, создающую пользовательские панели проводника, группы инструментов и настольные группы, вам нужно убедиться, что ваш код ведет себя так, как ведет себя проводник. Итак, первое, что нужно сделать, это предоставить объекту desk band реализацию «Site», и первый интерфейс, который должна предоставить эта реализация, — это IOleWindow. Объект desk band спросит ваш «Сайт», каков родительский дескриптор Windows. Просто укажите дескриптор формы (например), и рабочий стол band отобразится как дочерний элемент формы:

введите описание изображения здесь

ПРИМЕЧАНИЕ: Вы не можете использовать какую-либо форму или класс управления в качестве разработчика IOleWindow, потому что он уже реализует его за сценой (реализация Winforms), и эта реализация очень специфична, поэтому вам понадобится пользовательский сайт, как показано здесь .

 namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private IObjectWithSite _band = (IObjectWithSite)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("{01E04581-4EEE-11d0-BFE9-00AA005B4383}")));
        private BandSite _site;

        public Form1()
        {
            InitializeComponent();
        }

        protected override void CreateHandle()
        {
            base.CreateHandle();
            if (_site == null)
            {
                _site = new BandSite(Handle);
                _band.SetSite(_site);
            }
        }

        private class BandSite : IOleWindow
        {
            private IntPtr _hwnd;

            public BandSite(IntPtr hwnd)
            {
                _hwnd = hwnd;
            }

            void IOleWindow.GetWindow(out IntPtr hwnd)
            {
                hwnd = _hwnd;
            }

            void IOleWindow.ContextSensitiveHelp(int fEnterMode)
            {
                throw new NotImplementedException();
            }
        }
    }

    [ComImport, Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IObjectWithSite
    {
        void SetSite([MarshalAs(UnmanagedType.IUnknown)] object pUnkSite);

        [return: MarshalAs(UnmanagedType.IUnknown)]
        object GetSite(ref Guid riid);
    }

    [ComImport, Guid("00000114-0000-0000-C000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IOleWindow
    {
        void GetWindow(out IntPtr hwnd);
        void ContextSensitiveHelp(int fEnterMode);
    }
}
  

Комментарии:

1. Ну, святые угодники, это сработало! Я только что разместил панель инструментов Address, а затем панель инструментов Tablet PC Input Panel. По какой-то причине ссылки у меня не работают. Если у вас есть какие-либо идеи, почему это так, я бы воспользовался любыми советами. Мне также нужно выяснить, как изменить размер этих элементов управления, но, по крайней мере, я могу видеть их сейчас. Спасибо, Саймон!

2. У кого-нибудь есть идеи, как бы я изменил размер этой панели инструментов? Я перепробовал кучу разных вызовов, но безуспешно.