• Windows API 调用示例


    Ø  简介

    本文主要记录 Windows API 的调用示例,因为这项技术并不常用,属于 C# 中比较孤僻或接触底层的技术,并不常用。但是有时候也可以借助他完成一些 C# 本身不能完成的功能,例如:通过句柄获取其他程序数据,或者向操作系统发出指定的消息等等。

    提示:关于 Windows API 的函数有很多,不需要将所有的函数都非常了解,笔者也只是将用到过的函数记录下来,方便以后需要时可以快速编写。

     

    1.   鼠标事件 API

    1)   函数原型:void mouse_event(

    long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo)

    2)   函数说明:该函数合成鼠标的移动和点击事件,并将其插入到事件队列中。

    3)   参数:

    cButtons, 正数表示向上滚动,负数表示向下滚动。

    其他:参考Windows API 函数参考手册】

    4)   典型示例:

    1.   模拟鼠标(滚轮)滚动事件(C# Code)

    1)   函数声明

    [DllImport("user32.dll")]

    private static extern int mouse_event(int dwFlags, int dx, int dy, int cButtons, int dwExtraInfo);

    2)   调用代码

    const int MOUSEEVENTF_WHEEL = 0x0800;

    var timer = new System.Threading.Timer(new TimerCallback(o =>

    {

        mouse_event(MOUSEEVENTF_WHEEL, 0, 0, 500, 0);

        WriteLine(string.Format("鼠标已滚动,线程:{0}", GetThreadId()));

    }), null, 0, 50);

    3)   运行结果

    clip_image001[1]

     

    2.   钩子(Hook) API

    1)   什么是钩子:钩子实际是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。

    2)   典型示例

    1.   使用鼠标钩子,获取其他窗体句柄中的文本

    注意:钩子只能运行在 Winform(窗体应用程序)中,不能运行在 ConsoleApplication(控制台应用程序)中!

    1)   函数声明

    /// <summary>

    /// 钩子委托声明。

    /// </summary>

    public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

     

    /// <summary>

    /// 安装钩子。

    /// </summary>

    [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]

    public static extern IntPtr SetWindowsHookEx(IntPtr idHook, HookProc lpfn, IntPtr pInstance, uint threadId);

     

    /// <summary>

    /// 卸载钩子。

    /// </summary>

    [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]

    public static extern bool UnhookWindowsHookEx(IntPtr pHookHandle);

     

    /// <summary>

    /// 传递钩子(用于把拦截的消息继续传递下去,不然其他程序可能会得不到相应的消息)。

    /// </summary>

    [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]

    public static extern int CallNextHookEx(IntPtr pHookHandle, int nCode, IntPtr wParam, IntPtr lParam);

     

    /// <summary>

    /// 获取光标位置,以屏幕坐标表示。

    /// </summary>

    [DllImport("user32.dll", EntryPoint = "GetCursorPos")]

    public static extern bool GetCursorPos(ref Point point);

     

    /// <summary>

    /// 获得包含指定点的窗口的句柄。

    /// </summary>

    [DllImport("user32.dll", EntryPoint = "WindowFromPoint")]

    public static extern IntPtr WindowFromPoint(Point p);

     

    /// <summary>

    /// 将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。

    /// </summary>

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

    public static extern bool SendMessage(IntPtr hWnd, int msg, int wParam, [MarshalAs(UnmanagedType.LPTStr)]StringBuilder lParam);

     

    2)   调用代码

    /// <summary>

    /// 鼠标钩子测试。

    /// </summary>

    public void MouseHookTest()

    {

        IntPtr hookId = new IntPtr(14); //14代表鼠标钩子

        System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();

        //1. 安装钩子

        const int WM_RBUTTONUP = 0x205;     //右键释放(517)

        const int WM_GETTEXT = 0x000D;

        IntPtr hHook = IntPtr.Zero;

        hHook = SetWindowsHookEx(hookId, delegate(int nCode, IntPtr wParam, IntPtr lParam)

        {

            if ((int)wParam == WM_RBUTTONUP)

            {

                Point point = new Point();

                //获取光标位置

                GetCursorPos(ref point);

                //获取光标控件句柄

                IntPtr pointHwnd = WindowFromPoint(point);

                //获取光标控件Text属性值

                StringBuilder sbStr = new StringBuilder(256);

                SendMessage(pointHwnd, WM_GETTEXT, 100, sbStr);

                ShowMessageBox("获取光标句柄文本:{0}", sbStr);

            }

            return CallNextHookEx(hHook, nCode, wParam, lParam);    //将消息向下传递

        }, currentProcess.MainModule.BaseAddress, 0);

        //2. 卸载钩子

        if (hHook != IntPtr.Zero)

        {

            ShowMessageBox("钩子安装成功,60秒后将卸载钩子。");

            var timer = new System.Threading.Timer(o =>

            {

                if (UnhookWindowsHookEx(hHook))

                    ShowMessageBox("钩子卸载成功。");

                else

                    ShowMessageBox("钩子卸载失败!");

            }, null, 60000, 0);

        }

        else

            ShowMessageBox("钩子安装失败!");

    }

     

    3)   运行结果

    clip_image002[1]

  • 相关阅读:
    C# winform窗体自动停靠控件
    C# winform treeview checkbox 选中 循环 遍历
    解决WinForm(C#)中MDI子窗体最大化的问题
    tabcontrol的alignment属性设置成Left或Right时,tabPage的text内
    用伪随机数生成器Random生成随机数序列
    C#限制MDI子窗体重复打开——C#判断窗体是否已经打开 多种方法 20120626更新
    管理软件中融入“人、时间、流程”维度,提升软件社会价值
    如何让管理软件提升企业战略执行力
    2007年11月17日上午 ITIL与ITSM QQ群聊天记录: 欢迎加入QQ群:48132184
    Sharepoint 站点下应用程序虚拟路径下出现"不能进行输出缓存处理",错误ID 5787 解决方法
  • 原文地址:https://www.cnblogs.com/abeam/p/9996679.html
Copyright © 2020-2023  润新知