среда, 10 декабря 2008 г.

Creating ActiveX in .NET

Creating ActiveX in .NET

Сегодня пришлось создавать ActiveX control в Visual Studio 2008. Очень интересный опыт получился. Сразу замечу, что по моему скромному мнению, данные контролы стоит создавать с использованием библиотеки ATL.

В данном уроке мы будем использовать C#, но данную методику можно применять и на языке VB#. Данный контрол позволяет перехватывать событие Drag & Drop и отображать  изображение в окне своего представления.

Примечание любые не статические, публичные члены становятся доступны при указании атрибута ComVisible

  [ComVisible(true)]

public string FilePath

{

    get { return m_filepath; }

    set { m_filepath = value; }

}

Для начала создайте проект типа Class Library и назовите его DragNDrop

clip_image002[3]

После этого перейдите на вкладку Build в свойствах проекта и отметьте галочку Register for COM Interopt

clip_image004[3]

Подпишите сборку перейдя на вкладку Signing и выбрав чек бокс Sign the Assembly и выберите пункт New

clip_image006[3]

Удалите файл Class1.cs и добавьте новый пользовательский контрол под именем DragNDrop

clip_image008[3]

Добавьте обработчики событий DragDrop, DragEnter

clip_image010[3]


Переключитесь на представление кода и добавьте следующие атрибуты к классу DragNDrop

 

    [

     ProgId("DnDControl.DragNDrop"),

     Guid("31DCDFBA-6C3C-40b8-9BD9-E4B376BD56BC"),// Внимание измените данное значение на созданный вами GUID

     ComVisible(true),

     ClassInterface(ClassInterfaceType.AutoDual)

     ]

    public partial class DragNDrop : UserControl

переопределите метод OnPaint

protected override void OnPaint(PaintEventArgs e)

        {

 

            // If there is an image and it has a location,

            // paint it when the Form is repainted.

            base.OnPaint(e);

            if (this.picture != null && this.pictureLocation != Point.Empty)

            {

                e.Graphics.DrawImage(this.picture, this.pictureLocation);

            }

        }

Добавьте 2 переменных:

private Image picture;

private Point pictureLocation;

Измените методы

private void DragNDrop_DragEnter(object sender, DragEventArgs e)

        {

            // If the data is a file or a bitmap, display the copy cursor.

            if (e.Data.GetDataPresent(DataFormats.Bitmap) ||

               e.Data.GetDataPresent(DataFormats.FileDrop))

            {

                e.Effect = DragDropEffects.Copy;

            }

            else

            {

                e.Effect = DragDropEffects.None;

            }

        }

        private void DragNDrop_DragDrop(object sender, DragEventArgs e)

        {

            // Handle FileDrop data.

            if (e.Data.GetDataPresent(DataFormats.FileDrop))

            {

                // Assign the file names to a string array, in

                // case the user has selected multiple files.

                string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);

                try

                {

                    // Assign the first image to the picture variable.

                    this.picture = Image.FromFile(files[0]);

                    // Set the picture location equal to the drop point.

                    this.pictureLocation = this.PointToClient(new Point(e.X, e.Y));

                }

                catch (Exception ex)

                {

                    MessageBox.Show(ex.Message);

                    return;

                }

            }

 

            // Handle Bitmap data.

            if (e.Data.GetDataPresent(DataFormats.Bitmap))

            {

                try

                {

                    // Create an Image and assign it to the picture variable.

                    this.picture = (Image)e.Data.GetData(DataFormats.Bitmap);

                    // Set the picture location equal to the drop point.

                    this.pictureLocation = this.PointToClient(new Point(e.X, e.Y));

                }

                catch (Exception ex)

                {

                    MessageBox.Show(ex.Message);

                    return;

                }

            }

            // Force the form to be redrawn with the image.

            this.Invalidate();

 

        }

После этого добавьте 2 метода для регистрации вашего контрола:

#region Регистрация контрола

 

        [ComRegisterFunction()]

        public static void RegisterClass(string key)

        {

            // Strip off HKEY_CLASSES_ROOT\ from the passed key as I don't need it

 

            StringBuilder sb = new StringBuilder(key);

            sb.Replace(@"HKEY_CLASSES_ROOT\", "");

 

            // Open the CLSID\{guid} key for write access

 

            RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);

 

            // And create the 'Control' key - this allows it to show up in

 

            // the ActiveX control container

 

            RegistryKey ctrl = k.CreateSubKey("Control");

            ctrl.Close();

 

            // Next create the CodeBase entry - needed if not string named and GACced.

 

            RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);

            inprocServer32.SetValue("CodeBase", Assembly.GetExecutingAssembly().CodeBase);

            inprocServer32.Close();

 

            // Finally close the main key

 

            k.Close();

        }

        [ComUnregisterFunction()]

        public static void UnregisterClass(string key)

        {

            StringBuilder sb = new StringBuilder(key);

            sb.Replace(@"HKEY_CLASSES_ROOT\", "");

 

            // Open HKCR\CLSID\{guid} for write access

 

            RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);

 

            // Delete the 'Control' key, but don't throw an exception if it does not exist

 

            k.DeleteSubKey("Control", false);

 

            // Next open up InprocServer32

 

            RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);

 

            // And delete the CodeBase key, again not throwing if missing

 

            k.DeleteSubKey("CodeBase", false);

 

            // Finally close the main key

 

            k.Close();

        }

        #endregion

 

 

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