C#:钩子、委托、匿名、事件、结构体转字节数组、多线程操纵控件、UDP

事件

C#事件分为几个步骤:

定义事件

定义处理函数

为事件添加处理函数

激活事件

事件被激活后自动调用处理函数。


        public event messagehandleer shenzhijianglin;

    public void ooohelp(object sender, EventArgs e)
        {
            MessageBox.Show("IM be clicked! help!");
        }

newf.shenzhijianglin += newf.ooohelp;
            shenzhijianglin.Invoke(sender, e);

激活事件可以使用Invoke激活,也可以使用别的方式激活,因为.NET有很多的东西都可以激活自己本身的事件。

而且为事件添加处理函数需要使用+=操作符,这个操作符也太难看了,太丑了。

 

匿名方法和定义委托类型都需要delegate,也就是说一个关键字其实有两种意思,是有歧义的。

匿名:正常来说,为事件添加处理函数,语法为:

        public event MouseEventHandler MouseDown;
            MouHook.MouseDown += mh_OnMouEvent;

  void mh_OnMouEvent(object sender, MouseEventArgs e)//任何鼠标事件
        {}

也就是说先定

义一个事件,然后为这个事件添加处理函数,然后定义一个函数。

但是通过匿名,可以不声明函数,直接将事件处理函数定义出来:
 


        public event messagehandleer shenzhijianglin;
        newf.shenzhijianglin += delegate { MessageBox.Show("IM be clicked! help!"); };//匿名 和托管无关

这样方便一点。

委托

C#是没有指针的。

所以说,想要实现函数指针,就需要用到委托。

我的理解是,委托就是一个函数指针。

先声明一个委托类型
        protected delegate int HookProc(int nCode, int wParam, IntPtr lParam);

然后声明一个委托类型的 委托变量


        protected HookProc _hookCallback;

最后将这个委托变量指向一个函数,注意参数要与委托类型一致

             _hookCallback = new HookProc(HookCallbackProcedure);

这样就可以实现动态的改变委托变量指向的函数。



钩子

钩子比较麻烦,怎么说呢,其实看看那代码就行了。总的来说,就是调用WINDOWS自己的库函数,系统会捕获鼠标键盘的动作事件,然后调用这些一个事件处理函数,来处理捕获到的消息。然后再写一个事件在处理捕获之后的详细的处理。

  public void Start()
        {

            if (!_isStarted &&
                _hookType != 0)
            {

                //确保_hookCallback不是一个空的引用
                //如果是,GC会随机回收它,并且一个空的引用会爆出异常
                _hookCallback = new HookProc(HookCallbackProcedure);
                using (Process curPro = Process.GetCurrentProcess())
                {
                    using (ProcessModule curMod = curPro.MainModule)
                    {
                        _handleToHook = (int)SetWindowsHookExW(
                            _hookType,
                            _hookCallback,
                             GetModuleHandle(curMod.ModuleName),
                            0);
                    }
                }
                // 钩成功
                if (_handleToHook != 0)
                {
                    _isStarted = true;
                }

            }

        }

        public void Stop()
        {

            if (_isStarted)
            {
                UnhookWindowsHookEx(_handleToHook);
                _isStarted = false;
            }

        }

 

UDP:


using System.Net.Sockets;
using System.Net;

        IPEndPoint localIpep;
        private UdpClient udpcRecv;
            localIpep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888); // 本机IP,指定的端口号
                byte[] bytRecv = udpcRecv.Receive(ref remoteIpep);
            udpcRecv.Close();

多线程操纵控件:

 

 

经常会遇到跨线程访问的情况,很多人就说要用到委托;比如在辅助线程中要去更新一个UI界面上的label控件,通常会有一个if else判断语句:

if (label1.InvokeRequired)
这句是在判断label1控件是否是调用线程创建的,即判断是否跨线程调用,是则返回true,否则返回false;注意,这里判断的是调用线程是否是创建该控件的线程,因为调用线程是用户自己新建的一个辅助线程,下文中的mythread,而label控件是由主线程创建,因此,if语句的条件成立,执行该语句块的内容。注意该语句块的内容,首先实例化了一个用户自定义的委托,并把threadHandler方法绑定到该实例上,之后调用Invoke方法执行该委托,避免了子线程直接调用主线程的控件。
 

子线程给编辑框赋值则报错,需要使用此方式来赋值。原理:定义一个委托,指向一个新的SetText,然后触发此事件。


    public delegate void SetTextCallback(string text, string text2);

        private void SetText(string text, string text2)  
        {
            if (this.textBox1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text, text2 });
            }
            else
            {
                //在此设置textBox1的文本
                this.textBox1.Text = text;
                this.textBox2.Text = text2;
            }
        }
        private void SetText2(string text, string text2)
        {
            if (this.textBox1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text, text2 });
            }
            else
            {
                //在此设置textBox1的文本
                this.textBox5.Text = text;
                this.textBox7.Text = text2;
            }
        }

 


Action 与 Func是.NET类库中增加的内置委托,以便更加简洁方便的使用委托。

最初使用委托时,均需要先定义委托类型,然后定义一个符合委托类型签名的函数,
在调用前,需声明并创建委托对象,将指定函数与委托进行关联。
如例1:
public delegate int Math(int param1,int param2);定义委托类型
Public int Add(int param1,int param2)//定义同签名函数
{
  Return param1+param2;
}
Math math;//声明委托
math=new Math(Add);创建委托对象,与指定进行关联
math(3,4);//调用委托函数

例1通过简单改造:
Func<int,int,int> math=Add;//指定委托对象并关联函数
math(3,4);//调用委托函数
Lambda:
Func<int,int,int> math=(param1,param2)=>
{
  Return param1+param2;
}

Action的使用如同上面Func的使用一样,只是缺少了返回类型,直接调用委托函数。

 if (UnAllocGrid.InvokeRequired)
            {
                UnAllocGrid.Invoke(new Action(() =>
                {
                    UnAllocGrid.DataSource = DatasourUnAlloc;
                    UnAllocView.RefreshData();
                    //UnAllocView.ExpandAllGroups();
                    this.RightUnAllocCheck.Checked = false;
                }));
            }

 

结构体转字节数组:

 


        /// <summary>  
        /// 发送的时候先要把结构转换成字节数组
        /// 将结构转换为字节数组,结构对象字节数组
        /// </summary>  
        public byte[] StructToBytes(object obj)
        {
            //得到结构体的大小
            int size = Marshal.SizeOf(obj);
            //创建byte数组
            byte[] bytes = new byte[size];
            //分配结构体大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将结构体拷到分配好的内存空间
            Marshal.StructureToPtr(obj, structPtr, false);
            //从内存空间拷到byte数组
            Marshal.Copy(structPtr, bytes, 0, size);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            //返回byte数组
            return bytes;
        }

        /// <summary>  
        /// byte数组转结构        
        /// byte数组
        /// 结构类型
        /// 转换后的结构
        /// </summary>  
        public object BytesToStruct(byte[] bytes, Type type)
        {
            //得到结构的大小
            int size = Marshal.SizeOf(type);
            //Log(size.ToString(), 1);
            //byte数组长度小于结构的大小
            if (size > bytes.Length)
            {
                //返回空
                return null;
            }
            //分配结构大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);


            //将byte数组拷到分配好的内存空间
            Marshal.Copy(bytes, 0, structPtr, size);
            //将内存空间转换为目标结构
            object obj = Marshal.PtrToStructure(structPtr, type);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            //返回结构
            return obj;
        }

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值