线程内键盘钩子实现Winforn快捷键(组合键)代码全都在这里.比较简单..需要的朋友可以拷贝去用.. 发现网上的钩子例子都是使用C++的,C#线程内的钩子很少可以不出错正常运行的.. 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Windows.Forms;

namespace WindowsFormsApplication6
{
    
public class KeyboardHook
    {
        HookProc KeyboardHookProcedure; 
//声明键盘钩子事件类型.
        
//装置钩子的函数 
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
        
//卸下钩子的函数 
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        
public static extern bool UnhookWindowsHookEx(int idHook);
        
//下一个钩挂的函数 
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        
public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
        [DllImport(
"Kernel32.dll")]
        
public static extern int GetLastError();
        [DllImport(
"kernel32.dll", CharSet = CharSet.Auto,
            CallingConvention 
= CallingConvention.StdCall)]
        
private static extern IntPtr GetModuleHandle(string lpModuleName);
        
//取线程
        [DllImport("kernel32.dll")]
        
public static extern int GetCurrentThreadId();
        
static int hKeyboardHook = 0//键盘钩子句柄
        public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
        
public const int WH_KEYBOARD = 2;   // 键盘消息钩子(线程钩子)
        public event KeyEventHandler OnKeyDownEvent;
        
public KeyboardHook()
        {
            Start();
        }
        
~KeyboardHook()
        {
            Stop();
        }
        
/// <summary>
        
/// 安装钩子
        
/// </summary>
        public void Start()
        {
            
//安装一个线程键盘钩子 
            if (hKeyboardHook == 0)
            {
                KeyboardHookProcedure 
= new HookProc(KeyboardHookProc);
                Process curProcess 
= Process.GetCurrentProcess();
                ProcessModule curModule 
= curProcess.MainModule;
                hKeyboardHook 
= SetWindowsHookEx(WH_KEYBOARD, KeyboardHookProcedure,
                    IntPtr.Zero, GetCurrentThreadId());
                
if (hKeyboardHook == 0)
                {
                    Stop();
                    Console.WriteLine(GetLastError());
                    
throw new Exception("SetWindowsHookEx ist failed.");
                }
            }
        }
        
/// <summary>
        
/// 卸载钩子
        
/// </summary>
        public void Stop()
        {
            
bool retKeyboard = true;
            
if (hKeyboardHook != 0)
            {
                retKeyboard 
= UnhookWindowsHookEx(hKeyboardHook);
                hKeyboardHook 
= 0;
            }
            
//如果卸下钩子失败 
            if (!(retKeyboard))
            {
                Console.WriteLine(GetLastError());
                
throw new Exception("UnhookWindowsHookEx failed.");
            }
        }

        
private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
        { 
            
if (nCode >= 0)
            {
                
if (lParam.ToInt32()<0)
                {
//如果小于0那么是抬起
                    return 1;
                }
                Keys keyData 
= (Keys)wParam;
                
foreach (ShortKey keyModel in ShortCenter.Instance.Keys)
                {
                    
if (keyModel.Key == keyData && (int)Control.ModifierKeys == (int)keyModel.ControlKey)
                    {
                        keyModel.DoEvent();
                        
return 1;
                    }
                }
            }
            
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
        }
    }

} 

上面是一个钩子类,主要实现键盘消息拦截,而且是拦截线程内部的..

 

使用

 

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication6
{
    
public partial class Form3 : Form
    {
        KeyboardHook hook;
        
public Form3()
        {
            InitializeComponent();
            hook 
= new KeyboardHook();
        }


        
private void Form3_Load(object sender, EventArgs e)
        {
            ShortKey @short 
= new ShortKey();
            @short.Key 
= Keys.S;
            @short.ControlKey 
= Keys.Control;
            @short.ExecuteEvent 
+= (object o, EventArgs arg) => { MessageBox.Show( string.Format("你按下了Key:{0},Control:{1}", ((ShortKey)o).Key ,((ShortKey)o).ControlKey)); };
            ShortCenter.Instance.Keys.Add(@short);

            @short 
= new ShortKey();
            @short.Key 
= Keys.F1;
            @short.ExecuteEvent 
+= (object o, EventArgs arg) => { MessageBox.Show(string.Format("你按下了Key:{0},Control:{1}", ((ShortKey)o).Key, ((ShortKey)o).ControlKey)); };
            ShortCenter.Instance.Keys.Add(@short);

            @short 
= new ShortKey();
            @short.Key 
= Keys.F1;
            @short.ControlKey 
= Keys.Alt;
            @short.ExecuteEvent 
+= (object o, EventArgs arg) => { MessageBox.Show(string.Format("你按下了Key:{0},Control:{1}", ((ShortKey)o).Key, ((ShortKey)o).ControlKey)); };
            ShortCenter.Instance.Keys.Add(@short);

        }
    }
    
public class ShortCenter
    {
        
public ShortCenter()
        {
            _keys 
= new List<ShortKey>();
        }
        
private static ShortCenter _instance = new ShortCenter();
        
public static ShortCenter Instance
        {
            
get { return _instance; }
        }
        
private List<ShortKey> _keys;
        
public List<ShortKey> Keys
        {
            
get { return _keys; }
            
set { _keys = value; }
        }
    }

    
public class ShortKey
    {
        
public ShortKey()
        {

        }
        
private Keys _key;
        
private Keys _controlKey = Keys.None;

        
/// <summary>
        
/// 按下的普通键
        
/// </summary>
        public Keys Key
        {
            
get { return _key; }
            
set
            {
                _key 
= value;
            }
        }
        
/// <summary>
        
/// 控制键
        
/// </summary>
        public Keys ControlKey
        {
            
get { return _controlKey; }
            
set
            {
                _controlKey 
= value;
            }
        }
        
/// <summary>
        
/// 按下快捷键以后执行的操作
        
/// </summary>
        public event EventHandler ExecuteEvent;
        
/// <summary>
        
/// 执行事件
        
/// </summary>
        public void DoEvent()
        {
            
if (ExecuteEvent != null)
                ExecuteEvent(
this,new EventArgs());
        }
    }

}

 

 

 

 

posted @ 2011-06-04 16:02 索马 阅读(691) 评论(0) 编辑
反射判断 某个对象 是否 是泛型集合的类型
 public bool isCollection(object o) 
    { 
        
return typeof(ICollection).IsAssignableFrom(o.GetType()) 
            
|| typeof(ICollection<>).IsAssignableFrom(o.GetType()); 
    } 

 获取类实例

        public static object Load(string assembly, string className)
        {
            
return Assembly.Load(assembly).CreateInstance(className);
        }

 

获取指定属性

代码
        public static PropertyInfo GetPropertyByName(Type type, string propertyName)
        {
            
return type.GetProperty(propertyName, BindingFlags.Public
                
| BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.FlattenHierarchy);
        }

 

 反射创建泛型集合

代码
        public static IList CreateList(Type listType)
        {
            
//Type type = listType;
            
//反射创建普通对象
            object o = Activator.CreateInstance(listType);
            
//反射创建泛型集合
            Type generic = typeof(List<>);
            Type[] typeArgs 
= { listType };
            generic 
= generic.MakeGenericType(typeArgs);
            
return Activator.CreateInstance(generic) as IList;
        }

 

反射调用方法

代码
                    Type dataType = Type.GetType(ClassName);
                    MethodInfo parseMethod 
= dataType.GetMethod("Parse", BindingFlags.Public | BindingFlags.IgnoreCase
                        
| BindingFlags.Static | BindingFlags.FlattenHierarchy, nullnew Type[] { typeof(string) }, null);

 反射获取某个属性集合(如获取DataTable的columns属性,并且遍历它)

                DataTable dtSource = (DataTable)data;
                Type type 
= dtSource.GetType();
                PropertyInfo pi 
= type.GetProperty("Columns");
                IEnumerable listObject 
= (IEnumerable)pi.GetValue(dtSource, null); 

 反射设置属性

        public static void SetPropertyValue(this PropertyInfo property, object target, object value)
        {
            
if (null != property && property.CanWrite)
            {
                
if (value.GetType() == typeof(string))
                {
                    
// 对换行符进行转换
                    value = value.ToString().Replace("\\r""\r").
                        Replace(
"\\n""\n").Replace("<br>""\n");
                }
                value 
= GetObjectInstance(property.PropertyType, value.ToString());
                property.SetValue(target, value, 
null);
            }
        }

 

 

 

 

 

 

posted @ 2011-02-12 18:09 索马 阅读(179) 评论(0) 编辑

最近在群里有人说用Win32 Api不能对文本框设置内容(是别人写的一个程序,设置它的文本框的值).但是搞过win32的人都会说.这个应该不难啊,大概是搞.net的人,被微软 宠坏了.基本都不要用win32 api,这里我也不讨论用这个东西好不好,反正有人有这个需求,就要去做这个东西,我就自己建了一个工程,只要得到这个窗体的句柄,然后向他发送消息就搞定了,用到FindWindow,SendMessage搞定就可以了,我们所做的最核心的内容就是要找句柄.

要在win32 api下面使用FindWindow,SendMessage,必须这2个声明

代码
        [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError =true)]
        
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport(
"User32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
        
public static extern int SendTextMessage(
            IntPtr hWnd, 
            
int Msg, 
            
int wParam, 
            
string lParam
        );

 

记得这里要加上CharSet,否则发送中文可能是乱码,调用的时候

查找窗体的句柄,然后再在这个窗体下面查找这个文本框的句柄,窗口我们是根据窗体的标题文本来查找,文本控件时根据控件的类型来找.

IntPtr hwndCalc = WinAPIuser32.FindWindow(null"Form1aa");

IntPtr hwndtext 
= WinAPIuser32.FindWindowEx(hwndCalc, 0,"Edit",null);

 

 设置文本

WinAPIuser32.SendTextMessage(hwndtext, MSCODE.WM_SETTEXT, 0"mextb1860第一个文本框");

 

轻松搞定了.很简单.

 

这个时候我想,窗体上只有一个文本框,也就是说一个Edit,查找起来是很方便,可是往往,我们在实际情况中,一个窗体上有很多文本框,我们要找到其中一个文本框设置它的值,这个时候你在用WinAPIuser32.FindWindowEx(hwndCalc, 0,"Edit",null);就做不到了.因为他得到的,始终是最后一个 文本框的句柄,也就是说如果页面上有

3个文本,你使用这个时候只会获取到最后一个文本框的 句柄,如果你要设置第2个文本框你是做不到的,我们有2个办法,一个是EnumChildWindows方法来遍历下面的所有文本框,对这些文本框进行赋值,第2中方法就是 根据控件ID来查找句柄,在一个程序编译完成以后,也就是发布给客户用的时候,窗体上的控件ID就是固定的了,不可改变,我这里说的控件ID不是指.net的立面一个TextBox控件的ID,而是在windows下面,显现出来的ID,这样我们就可以通过固定的ID来查找,注意ID是固定的,不会再改变,这样我们就可以用GetDlgItem的方法来通过ID号来获取句柄,这里我们先讲第2中方法,第一种方法,比较复杂,而且后面我会用第一种方法来做一个非常特殊的演示,那就是如果控件ID时动态的时候,我们也如何获取句柄

 

        [DllImport("user32.dll ", EntryPoint = "GetDlgItem")]
        
public static extern IntPtr GetDlgItem(
        IntPtr hDlg,
        
int nIDDlgItem
        );

 

 

当然得到了句柄还有什么做不到的,对这3个文本发送消息,设置文本内容

 

代码
                IntPtr hwndtext = WinAPIuser32.GetDlgItem(hwndCalc, 1247226);
                WinAPIuser32.SendTextMessage(hwndtext, MSCODE.WM_SETTEXT, 
0"mextb1860第一个文本框");

                hwndtext 
= WinAPIuser32.GetDlgItem(hwndCalc, 1181678);
                WinAPIuser32.SendTextMessage(hwndtext, MSCODE.WM_SETTEXT, 
0"mextb1860第二个文本框");

                hwndtext 
= WinAPIuser32.GetDlgItem(hwndCalc, 919180);
                WinAPIuser32.SendTextMessage(hwndtext, MSCODE.WM_SETTEXT, 
0"mextb1860第三个文本框");

 

 

一切很顺利,就像我们想的一样,3个文本框的内容都改变了,太好了,不过不要太高兴了,因为我们这里的ID是固定所以都硬编码进去了,在一般情况下是没有问题,因为大部分的都是固定的,这个时候我发现.net的程序的控件ID时随时改变的,而且每次运行一次ID都不一样,这个ID是跟着句柄改变,句柄是多少ID就是多少,老火啊.这回要根据ID来获取句柄是获取是行不通了,现在的情况是 一个页面多个Edit类控件的ID是动态的,程序每次运行都不一样,不固定. 

关闭程序,再重新打开,在看下ID

那么我现在用第二种办法来解决,请出EnumChildWindows方法,这个方法比较特殊,有个一个参数是一个回调函数

 

        [DllImport("user32.dll")]
        
public static extern int EnumChildWindows(int hWndParent, CallBack lpfn, int lParam);

 

 

CallBack是一个委托

 

代码
        [DllImport("user32.dll")]
        
public static extern int EnumChildWindows(int hWndParent, CallBack lpfn, int lParam);
        
/// <summary>
        
/// 回调业务
        
/// </summary>
        public delegate void CallBusiness(IntPtr hwnd);
        
public delegate bool CallBack(IntPtr hwnd, int lParam);
        
/// <summary>
        
/// 遍历子窗体的父窗体句柄
        
/// </summary>
        public static CallBack callBackEnumChildWindows = new CallBack(ChildWindowProcess);
        
/// <summary>
        
/// 委托业务,需要客户端添加
        
/// </summary>
        public static CallBusiness CallFuntion;
        
/// <summary>
        
/// 遍历子窗体或控件
        
/// </summary>
        
/// <param name="hWnd"></param>
        
/// <param name="lParam"></param>
        
/// <returns></returns>
        public static bool EnumChildWindows(IntPtr hWnd, int lParam)
        {
            EnumChildWindows(hWnd.ToInt32(), callBackEnumChildWindows, 
0);
            
return true;
        }
        
/// <summary>
        
/// 获取类名字
        
/// </summary>
        
/// <param name="hwnd">需要获取类名的句柄</param>
        
/// <param name="lpClassName">类名(执行完成以后查看)</param>
        
/// <param name="nMaxCount">缓冲区</param>
        
/// <returns></returns>
        [DllImport("user32.dll", EntryPoint = "GetClassName")]
        
public static extern int GetClassName(
            IntPtr hwnd,
            StringBuilder lpClassName,
            
int nMaxCount
        );
        
/// <summary>
        
/// 遍历子控件
        
/// </summary>
        
/// <param name="hwnd"></param>
        
/// <param name="lParam"></param>
        
/// <returns></returns>
        public static bool ChildWindowProcess(IntPtr hwnd, int lParam)
        {
            
if (CallFuntion != null)
            {
                CallFuntion(hwnd);
            }
            
return true;
        }

 

 

EnumChildWindows用来遍历所有的子控件的句柄,有一个回调函数,CallBusiness也是一个代理,是提供给客户端调用的时候来编写逻辑的.代码很简单,应该很容易理解,客户端调用的代码,因为是.net开发的程序 所以 Edit的控件类型有点不一样,不过没关系,不影响我们查找

 

 

代码
                List<IntPtr> list = new List<IntPtr>();
                WinAPIuser32.CallFuntion 
= delegate(IntPtr enumIntPtr)
                {
                    StringBuilder s 
= new StringBuilder(2000);
                    WinAPIuser32.GetClassName(enumIntPtr, s, 
255);
                    
if (s.ToString() == "WindowsForms10.EDIT.app.0.378734a")
                    {
                        list.Add(enumIntPtr);
                    }
                };
                WinAPIuser32.EnumChildWindows(hwndCalc, 
0);
                WinAPIuser32.CallFuntion 
= null;
                
//第1个文本框
                WinAPIuser32.SendTextMessage(list[2], MSCODE.WM_SETTEXT, 0"mextb1860第一个文本框");
                
//第2个文本框
                WinAPIuser32.SendTextMessage(list[1], MSCODE.WM_SETTEXT, 0"mextb1860第二个文本框");
                
//第3个文本框
                WinAPIuser32.SendTextMessage(list[0], MSCODE.WM_SETTEXT, 0"mextb1860第三个文本框");

 

 

代码会提供下载,不明白的可以自己仔细看看.

/Files/mextb1860/WinAPITest.rar

posted @ 2010-06-12 18:57 索马 阅读(2547) 评论(3) 编辑

我以前段时间写了一个小项目。是VS2008写的,后来公司有同事想看看,当时公司用的是VS2005,可是VS2005是默认无法打开VS2008的项目的,这样就需要修改一点点东西,复制一个sln文件出来,改名为 **-VS2005.sln.


 然后修改sln里面的

Microsoft Visual Studio Solution File, Format Version 10.00

# Visual Studio 2008

修改为

Microsoft Visual Studio Solution File, Format Version 9.00

# Visual Studio 2005 

 

 然后在找到.csproj文件

把里面的 

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> 

修改为 

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> 

posted @ 2009-12-07 11:27 索马 阅读(2612) 评论(11) 编辑
摘要: 代码生成器是提高生产力的工具,目前的代码生成器太多了,CodeSmith,MyGeneration,动软,应该是目前用的比较多的几个代码生成器,但是东西往往不尽人意,复杂的东西太麻烦,简单的又不灵活,我现在像大家介绍一个简单而有强大的代码生成方法,简单的你无法想象,我前段时间也在写代码生成器,发现有几种方法可以实现代码生成器,一种是用字符串直接连接起来,这个可太难看,而且应该要修改也不方便,还有就...阅读全文
posted @ 2008-12-01 14:10 索马 阅读(3499) 评论(21) 编辑
摘要: RadControls Q3 2008开始集成了jquery,加上jquery视觉效果是帅多了..代码非常简单,首先导入jquery的js <telerik:RadScriptManager runat="server" ID="RadScriptManager1"> <Scripts> <asp:ScriptReference Assembly="Telerik.W...阅读全文
posted @ 2008-11-22 21:18 索马 阅读(1380) 评论(14) 编辑
摘要: 效果图我们看下分页传输了一些什么数据post的数据就只有一点参数.返回的数据就是json数据不会有大家都讨厌的viewstaterad的grid还是不错的.功能相当强大!大家看看代码绑定linq[代码]客户端js绑定[代码]aspx 页面代码[代码]阅读全文
posted @ 2008-11-22 20:36 索马 阅读(1305) 评论(4) 编辑
摘要: [代码]阅读全文
posted @ 2008-11-22 00:13 索马 阅读(514) 评论(4) 编辑
摘要: radconfirm,radprompt都支持回调函数,可是radalert以后就不做任何事情,可是我们有时候想在radalert以后还做一点小动作,比如我们在验证一个form表单的时候,如果有textbox为空,我们这个时候就需要radalert提示,有textbox为空,必须填写,然后为空的textbox获取焦点,这样一样人性化就更佳了,radalert以后执行js然后让哪个为空的textbo...阅读全文
posted @ 2008-11-20 22:42 索马 阅读(407) 评论(0) 编辑
摘要: 我们经常在RadComboBox中放上RadTreeView当做分类使用,是挺帅的.可是有的时候我们要做父节点不可以选择,而子节点才能选择!下面我就开始吧!当然页面上必须需要 <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager>没有这个运行不了.因为randcontrol也是用...阅读全文
posted @ 2008-11-14 22:19 索马 阅读(1031) 评论(1) 编辑