• CAD—Keyboard事件处理


          在之前的博客随笔中提到过CAD中鼠标的悬浮功能,后来就一直在想可不可以在CAD中触发Key事件,之后在Kean的一篇博文中提到过关于捕捉键盘事件,可惜不太实用,比如想通过键盘的上下键来移动一个实体。效果就像下面这样

     

         后来就想用钩子实现吧,然后在网上找KeyHook之类的信息,现成的代码真是太多了,现在贴出这部分网上找到的代码

    代码
     1     public class KeyboardHook
     
    2     {
     
    3         public event KeyEventHandler KeyDownEvent;
     
    4 
     
    5         public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
     
    6 
     
    7         static int hKeyboardHook = 0;//声明键盘钩子处理的初始值
     8 
     
    9         public const int WH_KEYBOARD_LL = 13;
    10 
    11         HookProc KeyboardHookProcedure;
    12 
    13         [StructLayout(LayoutKind.Sequential)]
    14         public class KeyboardHookStruct
    15         {
    16             public int vkCode;
    17             public int scanCode;
    18             public int flags;
    19             public int time;
    20             public int dwExtraInfo;
    21         }
    22 
    23         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    24         public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
    25 
    26         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    27         public static extern bool UnhookWindowsHookEx(int idHook);
    28 
    29         [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    30         public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
    31 
    32         public void Start()
    33         {
    34             if (hKeyboardHook == 0)
    35             {
    36                 KeyboardHookProcedure = new HookProc(KeyboardHookProc);
    37                 hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);
    38 
    39                 if (hKeyboardHook == 0)
    40                 {
    41                     Stop();
    42                     throw new Exception("安装键盘钩子失败 ");
    43                 }
    44             }
    45         }
    46 
    47         public void Stop()
    48         {
    49             bool retKeyboard = true;
    50 
    51             if (hKeyboardHook != 0)
    52             {
    53                 retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
    54                 hKeyboardHook = 0;
    55             }
    56             if (!retKeyboard) throw new Exception("卸载钩子失败!");
    57         }
    58 
    59         [DllImport("user32")]
    60         public static extern int ToAscii(int uVirtKey,
    61             int uScanCode,
    62             byte[] lpbKeyState,
    63             byte[] lpwTransKey,
    64             int fuState);
    65 
    66         [DllImport("user32")]
    67         public static extern int GetKeyboardState(byte[] pbKeyState);
    68 
    69         private const int WM_KEYDOWN = 0x100;
    70         private const int WM_KEYUP = 0x101;
    71         private const int WM_SYSKEYDOWN = 0x104;
    72         private const int WM_SYSKEYUP = 0x105;
    73 
    74         private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
    75         {
    76             if ((nCode >= 0&& (KeyDownEvent != null || KeyUpEvent != null || KeyPressEvent != null))
    77             {
    78                 KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
    79 
    80                 //键盘压下事件
    81                 if (KeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN))
    82                 {
    83                     Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
    84                     KeyEventArgs e = new KeyEventArgs(keyData);
    85                     KeyDownEvent(this, e);
    86                 }
    87             }
    88 
    89             return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
    90         }
    91 
    92         ~KeyboardHook()
    93         {
    94             Stop();
    95         }
    96     }
         编译成dll,然后将其加载到你的CAD项目中,在CAD中要实现的代码很容易。
    代码
      1         private KeyboardHook k_hook;
      
    2         Document doc = AsApp.DocumentManager.MdiActiveDocument;
      
    3         Database db = AsApp.DocumentManager.MdiActiveDocument.Database;
      
    4         Editor ed = AsApp.DocumentManager.MdiActiveDocument.Editor;
      
    5         ObjectId entId = ObjectId.Null;
      
    6 
      
    7         [CommandMethod("MoveEnt", CommandFlags.UsePickSet)]
      
    8         public void MoveEnt()
      
    9         {
     
    10 
     
    11             PromptSelectionResult res = ed.SelectImplied();
     
    12             if (PromptStatus.OK != res.Status) return;
     
    13 
     
    14             ObjectIdCollection ids = new ObjectIdCollection(res.Value.GetObjectIds());
     
    15             if (ids.Count <= 0return;
     
    16 
     
    17             //注册键盘事件
     18             try
     
    19             {
     
    20                 k_hook = new KeyboardHook();
     
    21                 k_hook.KeyDownEvent += new KeyEventHandler(hook_KeyDown);
     
    22                 k_hook.Start();
     
    23             }
     
    24             catch(System.Exception ex)
     
    25             {
     
    26                 ed.WriteMessage("\n注册键盘事件错误信息:" + ex.Message);
     
    27                 return;
     
    28             }
     
    29 
     
    30             Transaction tr = db.TransactionManager.StartTransaction();
     
    31             using (tr)
     
    32             {
     
    33                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
     
    34                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead);
     
    35 
     
    36                 //先仅考虑一个实体
     37                 entId = ids[0];
     
    38             }
     
    39         }
     
    40 
     
    41         private void hook_KeyDown(object sender, KeyEventArgs e)
     
    42         {
     
    43             if (ObjectId.Null == entId) return;
     
    44             Transaction tr = db.TransactionManager.StartTransaction();
     
    45             try
     
    46             {
     
    47                 using (tr)
     
    48                 {
     
    49                     using (DocumentLock docLock = doc.LockDocument())
     
    50                     {
     
    51                         BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
     
    52                         BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead);
     
    53                         Entity ent = tr.GetObject(entId, OpenMode.ForWrite) as Entity; //待移动的实体
     54 
     
    55                         Point3d entPos = Point3d.Origin;
     
    56                         if (ent is Circle) //移动一个圆
     57                         {
     
    58                             Circle c = ent as Circle;
     
    59                             entPos = c.Center;
     
    60                         }
     
    61                         if (e.KeyCode == Keys.Up) //向上移
     62                         { 
     
    63                             Matrix3d matrix = Matrix3d.Displacement(new Vector3d(0100));
     
    64                             ent.TransformBy(matrix);
     
    65                         }
     
    66                         else if (e.KeyCode == Keys.Down)
     
    67                         {
     
    68                             Matrix3d matrix = Matrix3d.Displacement(new Vector3d(0-100));
     
    69                             ent.TransformBy(matrix);
     
    70                         }
     
    71                         else if (e.KeyCode == Keys.Left)
     
    72                         {
     
    73                             Matrix3d matrix = Matrix3d.Displacement(new Vector3d(-1000));
     
    74                             ent.TransformBy(matrix);
     
    75                         }
     
    76                         else if (e.KeyCode == Keys.Right)
     
    77                         {
     
    78                             Matrix3d matrix = Matrix3d.Displacement(new Vector3d(1000));
     
    79                             ent.TransformBy(matrix);
     
    80                         }
     
    81                         else if (e.KeyCode == Keys.Escape)
     
    82                         {
     
    83                             ed.WriteMessage("\n按键操作取消");
     
    84                             k_hook.Stop();
     
    85                         }
     
    86                         else
     
    87                         {
     
    88                             ed.WriteMessage("\n可以通过上下键来控制实体的移动!");
     
    89                         }
     
    90 
     
    91                         //提交
     92                         tr.Commit();
     
    93                         ed.UpdateScreen();
     
    94                     }
     
    95                 }
     
    96             }
     
    97             catch (Autodesk.AutoCAD.Runtime.Exception ex)
     
    98             {
     
    99                 ed.WriteMessage(" \n异常:" + ex.Message);
    100             }
    101         }
    102 
    103         ~KeyMoveEn()
    104         {
    105             k_hook.Stop();
    106         }

         运行以后便是上面的贴图展现出来的效果。(看了上面的效果,感觉是不是可以实现一个CAD版本的俄罗斯方块游戏)

  • 相关阅读:
    Fancybox丰富的弹出层效果
    oracle wm_concat(column)函数的使用
    asp.net下ajax.ajaxMethod使用方法
    sql2008 附加数据库出错解决方法
    关于mysql-5.7.13-winx64服务无法启动的解决方法
    解决懒加载异常
    学生各科成绩,平均分,总分的展示
    docker desktop v20 设置文件路径,windows docker 设置设置路径
    自动化运维工具:jumpserver/jms_all
    linux kill 进程正则表达式
  • 原文地址:https://www.cnblogs.com/wangyong/p/1694603.html
Copyright © 2020-2023  润新知