среда, 10 октября 2012 г.

Создание плавающей панельки возле курсора, во время работы команды в AutoCAD

Ниже приведён простой пример на тему того, как во время работы команды в AutoCAD, создать возле курсора мыши прозрачную плавающую панельку с произвольным набором элементов. Для реализации данной задачи я воспользовался технологией WPF.

Для того, чтобы имелась возможность выбрать элементы на плавающей палитре, её нужно как-то на время зафиксировать. Этот момент я реализовал так: нужно нажать и удерживать клавишу Ctrl. До тех пор, пока вы удерживаете эту клавишу, палитра не будет перемещаться вслед за курсором мыши и, как следствие, вы можете воспользоваться этой палитрой, кликая мышкой по нужным контролам.

Окно палитры я сделал невидимым, а всем контролам назначил прозрачность 70%. Когда вы наводите мышку на тот или иной контрол плавающей панельки, он становится полностью непрозрачным. Как только мышка покидает контрол, его прозрачность восстанавливается в исходное состояние.

Пример носит демонстрационный характер.  Видео:




Исходный код примера:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using wf = System.Windows.Forms;
using System.Windows.Input;
using System.Runtime.InteropServices;
//Autodesk ***************
using acad = Autodesk.AutoCAD.ApplicationServices.Application;
using AcApp = Autodesk.AutoCAD.ApplicationServices;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
using AcEd = Autodesk.AutoCAD.EditorInput;
using AcRtm = Autodesk.AutoCAD.Runtime;
using System.Windows.Media;
//************************************

namespace FloatingPalette {
    public class Class1 {
        static Window win;

        [AcRtm.CommandMethod("fpStart")]
        public void Start() {
            AcApp.Document doc = acad.DocumentManager.MdiActiveDocument;
            doc.CommandWillStart += doc_CommandWillStart;
            doc.CommandEnded += doc_CommandEnded;
            doc.CommandCancelled += doc_CommandEnded;
            doc.CommandFailed += doc_CommandEnded;
        }

        void doc_CommandWillStart(object sender, AcApp.CommandEventArgs e) {

            String[] commands = new String[] { "OPEN", "SAVE", "QSAVE", "SAVEAS",
                "QUIT", "CLOSE", "FPEND" };

            if (commands.Contains(e.GlobalCommandName.ToUpper()))
                return;

            win = new Window();
            win.WindowStyle = WindowStyle.None;
            win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            win.SizeToContent = SizeToContent.WidthAndHeight;
            win.ResizeMode = ResizeMode.NoResize;
            win.Left = System.Windows.Forms.Cursor.Position.X + offset;
            win.Top = System.Windows.Forms.Cursor.Position.Y + offset;
            win.AllowsTransparency = true;
            win.Background = Brushes.Transparent;

            Button btn = new Button();
            btn.Content = "Кнопка 1";
            btn.Margin = new Thickness(2, 2, 1, 2);
            btn.Opacity = opacity;
            btn.Click += btn_Click;
            btn.MouseEnter += btn_MouseEnter;
            btn.MouseLeave += btn_MouseLeave;

            Button btn2 = new Button();
            btn2.Content = "Кнопка 2";
            btn2.Margin = new Thickness(1, 2, 2, 2);
            btn2.Opacity = opacity;
            btn2.Click += btn2_Click;
            btn2.MouseEnter += btn_MouseEnter;
            btn2.MouseLeave += btn_MouseLeave;

            ComboBox cb = new ComboBox();
            cb.Margin = new Thickness(1, 2, 2, 2);
            cb.Width = 150;
            cb.Opacity = opacity;

            List<String> data = new List<String>();
            data.Add("Вася");
            data.Add("Петя");
            data.Add("Коля");

            cb.ItemsSource = data;
            cb.SelectedIndex = 0;

            cb.SelectionChanged += cb_SelectionChanged;
            cb.MouseEnter += btn_MouseEnter;
            cb.MouseLeave += btn_MouseLeave;

            StackPanel sp = new StackPanel();
            sp.Orientation = Orientation.Horizontal;
            sp.Children.Add(btn);
            sp.Children.Add(btn2);
            sp.Children.Add(cb);

            win.Content = sp;

            acad.ShowModelessWindow(win);

            AcApp.Document doc = acad.DocumentManager.MdiActiveDocument;

            doc.Editor.PointMonitor += Editor_PointMonitor;
            SetFocus(acad.MainWindow.Handle);
        }

        void btn_MouseLeave(object sender, MouseEventArgs e) {
            FrameworkElement x = (FrameworkElement)sender;
            x.Opacity = opacity;
        }

        void btn_MouseEnter(object sender, MouseEventArgs e) {
            FrameworkElement x = (FrameworkElement)sender;
            x.Opacity = 1;
        }

        void doc_CommandEnded(object sender, AcApp.CommandEventArgs e) {
            if (null != win)
                win.Close();
        }

        void btn_Click(object sender, RoutedEventArgs e) {
            acad.ShowAlertDialog("Hello World!");
            wf.Cursor.Position = new System.Drawing.Point(x, y);
            SetFocus(acad.MainWindow.Handle);
        }

        void btn2_Click(object sender, RoutedEventArgs e) {
            acad.ShowAlertDialog("Привет Мир!");
            wf.Cursor.Position = new System.Drawing.Point(x, y);
            SetFocus(acad.MainWindow.Handle);
        }

        void cb_SelectionChanged(object sender, SelectionChangedEventArgs e) {
            acad.ShowAlertDialog(String.Format("Выбран: {0}", e.AddedItems[0].ToString()));
            wf.Cursor.Position = new System.Drawing.Point(x, y);
            SetFocus(acad.MainWindow.Handle);
        }

        const Double opacity = 0.3;
        const Int32 offset = 10;
        Int32 x;
        Int32 y;

        void Editor_PointMonitor(object sender, AcEd.PointMonitorEventArgs e) {
            if ((wf.Control.ModifierKeys & wf.Keys.Control) != wf.Keys.Control) {
                win.Left = wf.Cursor.Position.X + offset;
                win.Top = wf.Cursor.Position.Y + offset;
            }
            else {
                x = wf.Cursor.Position.X;
                y = wf.Cursor.Position.Y;
            }
        }

        [AcRtm.CommandMethod("fpEnd")]
        public void End() {
            AcApp.Document doc = acad.DocumentManager.MdiActiveDocument;
            doc.CommandWillStart -= doc_CommandWillStart;
            doc.CommandEnded -= doc_CommandEnded;
            doc.CommandCancelled -= doc_CommandEnded;
            doc.CommandFailed -= doc_CommandEnded;
            doc.Editor.PointMonitor -= Editor_PointMonitor;
        }

        [DllImport("user32.dll")]
        static extern IntPtr SetFocus(IntPtr hWnd);
    }
}





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