明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 638|回复: 0

Implementing drag & drop of an image at a location and size using .NET

[复制链接]
发表于 2011-3-1 10:25:05 | 显示全部楼层 |阅读模式

原文地址:http://through-the-interface.typepad.com/through_the_interface/2011/02/implementing-drag-drop-of-an-autocad-raster-image-at-a-specified-location-and-size-using-net.html

I’m in Las Vegas, running between meetings, presentations and performance reviews, so just a quick post, today (it’s just before midnight here, but already Monday morning in Europe).

I promised in the last post and the one before that I’d extend the code we’ve been looking at to enable drag & drop of raster images into AutoCAD with resizing of the dropped image via a jig, using the code in this previous post as a foundation.

The below C# code does just that, with the new/modified lines in red (and the complete, unnumbered source file here):

    1 using Autodesk.AutoCAD.ApplicationServices;

    2 using Autodesk.AutoCAD.DatabaseServices;

    3 using Autodesk.AutoCAD.EditorInput;

    4 using Autodesk.AutoCAD.Geometry;

    5 using Autodesk.AutoCAD.Runtime;

    6 using Autodesk.AutoCAD.Windows;

    7 using System.Runtime.InteropServices;

    8 using System.Windows.Forms;

    9 using System.Drawing;

   10 using System.IO;

   11 using System;

   12 

   13 namespace DragAndDrop

   14 {

   15   public enum Msgs

   16   {

   17     WM_DRAWCLIPBOARD = 0x0308,

   18     WM_CHANGECBCHAIN = 0x030D

   19   }

   20 

   21   public class ClipboardView : UserControl

   22   {

   23     [DllImport("user32.dll")]

   24     public static extern IntPtr SetClipboardViewer(

   25       IntPtr hWndNewViewer

   26     );

   27 

   28     [DllImport("user32.dll", CharSet = CharSet.Auto)]

   29     public static extern IntPtr SendMessage(

   30       IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam

   31     );

   32 

   33     private IntPtr _nxtVwr;

   34     private PictureBox _img;

   35     private PaletteSet _ps;

   36 

   37     public System.Drawing.Image Contents

   38     {

   39       get { return _img.Image; }

   40     }

   41 

   42     public ClipboardView(PaletteSet ps)

   43     {

   44       _img = new PictureBox();

   45       _img.Anchor =

   46         (AnchorStyles)(AnchorStyles.Top |

   47                       AnchorStyles.Bottom |

   48                       AnchorStyles.Left |

   49                       AnchorStyles.Right);

   50       _img.Location = new Point(0, 0);

   51       _img.Size = this.Size;

   52       _img.SizeMode = PictureBoxSizeMode.StretchImage;

   53       Controls.Add(_img);

   54 

   55       // Add our event handler to launch a new drag event

   56       // when someone clicks on the control

   57 

   58       _img.MouseDown +=

   59         delegate(object sender, MouseEventArgs e)

   60         {

   61           // Simply initiate the drag & drop in AutoCAD,

   62           // specifying an instance of our custom "drop

   63           // target" class

   64 

   65           Autodesk.AutoCAD.ApplicationServices.

   66           Application.DoDragDrop(

   67             _img, this.Contents, DragDropEffects.Copy,

   68             new MyDropTarget()

   69           );

   70         };

   71 

   72       _nxtVwr = SetClipboardViewer(this.Handle);

   73       _ps = ps;

   74     }

   75 

   76     private void ExtractImage()

   77     {

   78       IDataObject iData;

   79       try

   80       {

   81         iData = Clipboard.GetDataObject();

   82       }

   83       catch (System.Exception ex)

   84       {

   85         MessageBox.Show(ex.ToString());

   86         return;

   87       }

   88 

   89       if (iData.GetDataPresent("Bitmap"))

   90       {

   91         object o = iData.GetData("Bitmap");

   92         Bitmap b = o as Bitmap;

   93         if (b != null)

   94         {

   95           _img.Image = b;

   96           if (_ps != null)

   97           {

   98             _ps.Size =

   99               new Size(b.Size.Width / 3, b.Size.Height / 3);

  100           }

  101         }

  102       }

  103     }

  104 

  105     protected override void WndProc(ref Message m)

  106     {

  107       switch ((Msgs)m.Msg)

  108       {

  109         case Msgs.WM_DRAWCLIPBOARD:

  110           ExtractImage();

  111           SendMessage(_nxtVwr, m.Msg, m.WParam, m.LParam);

  112           break;

  113         case Msgs.WM_CHANGECBCHAIN:

  114           if (m.WParam == _nxtVwr)

  115             _nxtVwr = m.LParam;

  116           else

  117             SendMessage(_nxtVwr, m.Msg, m.WParam, m.LParam);

  118           break;

  119         default:

  120           base.WndProc(ref m);

  121           break;

  122       }

  123     }

  124   }

  125 

  126   // Our custom drop target class

  127 

  128   public class MyDropTarget : DropTarget

  129   {

  130     public override void OnDrop(DragEventArgs e)

  131     {

  132       Document doc =

  133         Autodesk.AutoCAD.ApplicationServices.Application.

  134         DocumentManager.MdiActiveDocument;

  135 

  136       // If we have a valid bitmap, save it and send

  137       // our custom command (RINS)

  138 

  139       if (e.Data.GetDataPresent("Bitmap"))

  140       {

  141         object o = e.Data.GetData("Bitmap");

  142         Bitmap b = o as Bitmap;

  143         if (b != null)

  144         {

  145           // We'll save the bitmap as a "temp" file

  146           // (as its unique - a better approach

  147           // would probably to create a unique file

  148           // in the same folder as the drawing, but

  149           // that's left to the reader)

  150 

  151           string path = Path.GetTempFileName();

  152           b.Save(path);

  153 

  154           // Call our command

  155 

  156           string cmd =

  157             String.Format(

  158               "_RINS {0}\n{1},{2},0\n", path, e.X, e.Y

  159             );

  160           doc.SendStringToExecute(

  161             cmd, false, false, false

  162           );

  163         }

  164       }

  165     }

  166   }

  167 

  168   public class Commands

  169   {

  170     private PaletteSet _ps = null;

  171     private ClipboardView _cv = null;

  172     static private Point3d _pt = Point3d.Origin;

  173 

  174     [CommandMethod("DRAGDROP")]

  175     public void DragAndDropClipboardRaster()

  176     {

  177       if (_ps == null)

  178       {

  179         _ps = new PaletteSet(

  180           "DRAGDROP",

  181           new Guid("5C8FC28C-45ED-4796-BD40-28D235B6D7DA")

  182         );

  183 

  184         if (_cv == null)

  185         {

  186           _cv = new ClipboardView(_ps);

  187         }

  188 

  189         _ps.Text = "Clipboard";

  190         _ps.DockEnabled =

  191           DockSides.Left | DockSides.Right | DockSides.None;

  192         _ps.Size = new System.Drawing.Size(300, 500);

  193         _ps.Add("ClipboardView", _cv);

  194       }

  195       _ps.Visible = true;

  196     }

  197 

  198 

  199     // Our custom command to insert a raster image

  200 

  201     [CommandMethod("RINS")]

  202     public void RasterInsert()

  203     {

  204       Document doc =

  205       Autodesk.AutoCAD.ApplicationServices.Application.

  206       DocumentManager.MdiActiveDocument;

  207       Database db = doc.Database;

  208       Editor ed = doc.Editor;

  209 

  210       // Pick up the location of the bitmap image

  211 

  212       PromptStringOptions pso =

  213         new PromptStringOptions(

  214           "\nPath of raster image: "

  215         );

  216       pso.AllowSpaces = true;

  217       PromptResult pr = ed.GetString(pso);

  218       if (pr.Status != PromptStatus.OK)

  219         return;

  220 

  221       if (!File.Exists(pr.StringResult))

  222       {

  223         ed.WriteMessage(

  224           "\nFile does not exist."

  225         );

  226         return;

  227       }

  228 

  229       string path = pr.StringResult;

  230 

  231       // Pick up the position of the drop in screen coords

  232 

  233       PromptPointOptions ppo =

  234         new PromptPointOptions(

  235           "\nPosition of raster image: "

  236         );

  237       PromptPointResult ppr = ed.GetPoint(ppo);

  238       if (pr.Status != PromptStatus.OK)

  239         return;

  240 

  241       Point3d pos = ppr.Value;

  242 

  243       // Calculate the displacement vector

  244 

  245       Point3d pt =

  246         ed.PointToWorld(new Point((int)pos.X, (int)pos.Y));

  247       Matrix3d disp =

  248         Matrix3d.Displacement(pt - Point3d.Origin);

  249 

  250       Transaction tr =

  251         db.TransactionManager.StartTransaction();

  252       using (tr)

  253       {

  254         // Get or create our raster image dictionary

  255 

  256         ObjectId dictId =

  257           RasterImageDef.GetImageDictionary(db);

  258         if (dictId == ObjectId.Null)

  259           dictId = RasterImageDef.CreateImageDictionary(db);

  260 

  261         // And open it for write

  262 

  263         DBDictionary dict =

  264           (DBDictionary)tr.GetObject(

  265             dictId, OpenMode.ForWrite

  266           );

  267 

  268         // Get a unique name for our definition object

  269 

  270         string name = RasterImageDef.SuggestName(dict, path);

  271 

  272         // Create the definition and add it to the dictionary

  273 

  274         RasterImageDef rid = new RasterImageDef();

  275         rid.SourceFileName = path;

  276         rid.Load();

  277         ObjectId ridId = dict.SetAt(name, rid);

  278         tr.AddNewlyCreatedDBObject(rid, true);

  279 

  280         // Now we'll add our raster image reference

  281         // to the current space

  282 

  283         BlockTableRecord btr =

  284           (BlockTableRecord)tr.GetObject(

  285             db.CurrentSpaceId,

  286             OpenMode.ForWrite

  287           );

  288 

  289         // Call our jig to define the raster

  290 

  291         RasterJig jig =

  292           new RasterJig(

  293             ridId,

  294             rid.Size,

  295             ed.CurrentUserCoordinateSystem,

  296             pt

  297           );

  298         PromptResult prj = ed.Drag(jig);

  299 

  300         if (prj.Status != PromptStatus.OK)

  301         {

  302           rid.Erase();

  303           return;

  304         }

  305 

  306         // Get our entity and add it to the modelspace

  307 

  308         RasterImage ri = (RasterImage)jig.GetEntity();

  309         ri.ImageDefId = ridId;

  310         ri.SetClipBoundaryToWholeImage();

  311         btr.AppendEntity(ri);

  312         tr.AddNewlyCreatedDBObject(ri, true);

  313 

  314         // Create a reactor between the RasterImage and the

  315         // RasterImageDef to avoid the "unreferenced"

  316         // warning in the XRef palette

  317 

  318         RasterImage.EnableReactors(true);

  319         ri.AssociateRasterDef(rid);

  320 

  321         // Of course we commit

  322 

  323         tr.Commit();

  324       }

  325     }

  326   }

  327 

  328   class RasterJig : EntityJig

  329   {

  330     Matrix3d _ucs;

  331     Vector2d _sz;

  332     Point3d _start = Point3d.Origin;

  333     Point3d _end = Point3d.Origin;

  334 

  335     public RasterJig(

  336       ObjectId defId,

  337       Vector2d sz,

  338       Matrix3d ucs,

  339       Point3d start

  340     )

  341       : base(new RasterImage())

  342     {

  343       _sz = sz;

  344       _start = start;

  345       _ucs = ucs;

  346 

  347       RasterImage ri = (RasterImage)Entity;

  348       ri.ImageDefId = defId;

  349 

  350       // Create a near zero size default image,

  351       // to avoid the boundary flicker

  352 

  353       double size = Tolerance.Global.EqualPoint;

  354       ri.Orientation =

  355         new CoordinateSystem3d(

  356           _start,

  357           new Vector3d(size, 0, 0),

  358           new Vector3d(0, size, 0)

  359         );

  360       ri.ShowImage = true;

  361     }

  362 

  363     protected override SamplerStatus Sampler(

  364       JigPrompts prompts

  365     )

  366     {

  367       JigPromptPointOptions opts =

  368         new JigPromptPointOptions();

  369       opts.UserInputControls =

  370         (UserInputControls.Accept3dCoordinates |

  371         UserInputControls.NoNegativeResponseAccepted);

  372       opts.Message = "\nSecond corner of raster image: ";

  373 

  374       // Get the point itself

  375 

  376       PromptPointResult res = prompts.AcquirePoint(opts);

  377 

  378       if (res.Status == PromptStatus.OK)

  379       {

  380         // Convert the supplied point into UCS

  381 

  382         Point3d tmp =

  383           res.Value.TransformBy(_ucs.Inverse());

  384 

  385         // Check if changed (reduces flicker)

  386 

  387         if (_end == tmp)

  388         {

  389           return SamplerStatus.NoChange;

  390         }

  391         else

  392         {

  393           _end = tmp;

  394           return SamplerStatus.OK;

  395         }

  396       }

  397       return SamplerStatus.Cancel;

  398     }

  399 

  400     protected override bool Update()

  401     {

  402       RasterImage ri = (RasterImage)Entity;

  403 

  404       // Get offset between the two corners

  405 

  406       Vector3d diff = _end - _start;

  407 

  408       // Get the ratios of the dimensions of the dragged

  409       // image with the source

  410 

  411       double sizeX = Math.Abs(diff.X),

  412             sizeY = Math.Abs(diff.Y),

  413             ratX = sizeX / _sz.X,

  414             ratY = sizeY / _sz.Y;

  415 

  416       // Find out which is bigger and use that to decide

  417       // which size should change to keep the proportion

  418 

  419       bool biggerX = (ratX > ratY);

  420 

  421       if (biggerX)

  422         sizeY = ratX * _sz.Y;

  423       else

  424         sizeX = ratY * _sz.X;

  425 

  426       // Determine the image's orientation...

  427 

  428       // The original will depend on the order of the corners

  429       // It will be offset to the left and/or down depending

  430       // on the values of the vector between the two points

  431 

  432       Point3d orig;

  433 

  434       // The axes stay the same, as we will always keep the

  435       // image oriented the same way relative to the UCS

  436 

  437       Vector3d xAxis = new Vector3d(sizeX, 0, 0);

  438       Vector3d yAxis = new Vector3d(0, sizeY, 0);

  439 

  440       if (diff.X > 0 && diff.Y > 0) // Dragging top-right

  441         orig = _start;

  442       else if (diff.X < 0 && diff.Y > 0) // Top-left

  443         orig = _start + new Vector3d(-sizeX, 0, 0);

  444       else if (diff.X > 0 && diff.Y < 0) // Bottom-right

  445         orig = _start + new Vector3d(0, -sizeY, 0);

  446       else // if (diff.X < 0 && diff.Y < 0) // Bottom-left

  447         orig = _start - new Vector3d(sizeX, sizeY, 0);

  448 

  449       // Set the image's orientation in WCS

  450 

  451       ri.Orientation =

  452         new CoordinateSystem3d(

  453           orig.TransformBy(_ucs),

  454           xAxis.TransformBy(_ucs),

  455           yAxis.TransformBy(_ucs)

  456         );

  457 

  458       return true;

  459     }

  460 

  461     public Entity GetEntity()

  462     {

  463       return Entity;

  464     }

  465   }

  466 }

When we run the new DRAGDROP command and drag & drop from our palette onto the drawing, we see the raster images are now inserted and sized by the jig proportionally to the original image’s size:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
"觉得好,就打赏"
还没有人打赏,支持一下

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-12-24 20:25 , Processed in 0.193486 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表