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版本的俄罗斯方块游戏)

posted @ 2010-03-25 09:42  勇者归来  阅读(724)  评论(2编辑  收藏  举报