当前位置:编程学习 > C#/ASP.NET >>

请帅哥解答,sendinput操作鼠标;可以再多加分!

请帅哥解答,sendinput操作鼠标;可以再多加分! --------------------编程问答--------------------
引用 楼主 u013038077 的回复:
请帅哥解答,sendinput操作鼠标;可以再多加分!



SendInput可以将指定的鼠标键盘消息插入到系统消息队列,从而实现对鼠标键盘的模拟。有很多程序对SendInput进行了屏蔽,但不是所有的。所以这里介绍一下SendInput的使用。我已经将主要的模拟功能写在了一个单元文件中:SIMouseKeyboard.pas,调用该单元文件中的相关函数就可以实现鼠标键盘的模拟。该单元文件的下载见本楼末尾。SendInput的参数其实很简单,在Windows.pas就有函数的声明如下:

function SendInput(cInputs: UINT; var pInputs: TInput; cbSize: Integer): UINT; stdcall;

  cInputs:定义pInputs中记录数组的元素数目。pInputs:TInput类型记录数组的第1个元素。每个元素代表插人到系统消息队列的键盘或鼠标事件。cbSize:定义TInput的大小,一般为SizeOf(TInput)。函数返回成功插入系统消息队列中事件的数目,失败返回0。调用SendInput关键的就是要搞清楚它的几个记录结构的意思,在Windows.pas中对TInput的声明如下:

  tagINPUT = packed record
    Itype: DWORD;
    case Integer of
      0: (mi: TMouseInput);
      1: (ki: TKeybdInput);
      2: (hi: THardwareInput);
  end;
  TInput = tagINPUT;

  其中mi、ki、hi是3个共用型的记录结构,Itype指出记录结构中所使用的类型,它有3个值。INPUT_MOUSE:表示使用mi记录结构,忽略ki和hi;INPUT_KEYBOARD:表示使用ki记录结构,忽略mi和hi

--------------------编程问答--------------------

鼠标模拟

  TMouseInput记录结构的声明如下:

  tagMOUSEINPUT = packed record
    dx: Longint;
    dy: Longint;
    mouseData: DWORD;
    dwFlags: DWORD;
    time: DWORD;
    dwExtraInfo: DWORD;
  end;
  TMouseInput = tagMOUSEINPUT;

  其中dx、dy是鼠标移动时的坐标差(不是象素单位),在鼠标移动时有效。mouseData是鼠标滚轮滚动值,在滚动鼠标滚轮时有效。当mouseData小于0时向下滚动,当mouseData大于0时向上滚动,mouseData的绝对值一般设为120。dwFlags指定鼠标所进行的操作,例如,MOUSEEVENTF_MOVE表示移动鼠标,MOUSEEVENTF_LEFTDOWN表示按下鼠标左键,MOUSEEVENTF_LEFTUP表示放开鼠标左键。time是时间戳,可以使用API函数GetTickCount的返回值。dwExtraInfo是扩展信息,可以使用API函数GetMessageExtraInfo的返回值。例如单击鼠标左键的程序如下:

procedure MouseClick;
var
    Inputs : array [0..1] of TInput;
begin
    Inputs[0].Itype:=INPUT_MOUSE;
    with Inputs[0].mi do
    begin
        dx:=0;
        dy:=0;
        mouseData:=0;
        dwFlags:=MOUSEEVENTF_LEFTDOWN;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    Inputs[1].Itype:=INPUT_MOUSE;
    with Inputs[1].mi do
    begin
        dx:=0;
        dy:=0;
        mouseData:=0;
        dwFlags:=MOUSEEVENTF_LEFTUP;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    SendInput(2,Inputs[0],SizeOf(TInput));
end;

  鼠标的移动总是很麻烦,上面的dx、dy不是以象素为单位的,而是以鼠标设备移动量为单位的,它们之间的比值受鼠标移动速度设置的影响。具体的解决方法我已经在《Delphi下利用WinIo模拟鼠标键盘详解》一文中进行了讨论,这里不再重复。dwFlags可以设置一个MOUSEEVENTF_ABSOLUTE标志,这使得可以用另外一种方法移动鼠标。当dwFlags设置了MOUSEEVENTF_ABSOLUTE标志,dx、dy为屏幕坐标值,表示将鼠标移动到dx,dy的位置。但是这个坐标值也不是以象素为单位的。这个值的范围是0到65535($FFFF),当dx等于0、dy等于0时表示屏幕的最左上角,当dx等于65535、dy等于65535时表示屏幕的最右下角,相当于将屏幕的宽和高分别65536等分。API函数GetSystemMetrics(SM_CXSCREEN)可以返回屏幕的宽度,函数GetSystemMetrics(SM_CYSCREEN)可以返回屏幕的高度,利用屏幕的宽度和高度就可以将象素坐标换算成相应的dx、dy。注意:这种换算最多会出现1象素的误差。例如:将鼠标指针移动到屏幕150,120坐标处的程序如下:

procedure MouseMove;
var
    Input : TInput;
begin
    Input.Itype:=INPUT_MOUSE;
    with Input.mi do
    begin
        dx:=($FFFF div (GetSystemMetrics(SM_CXSCREEN)-1)) * 150;
        dy:=($FFFF div (GetSystemMetrics(SM_CYSCREEN)-1)) * 120;
        mouseData:=0;
        dwFlags:=MOUSEEVENTF_MOVE or MOUSEEVENTF_ABSOLUTE;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    SendInput(1,Input,SizeOf(TInput));
end;

--------------------编程问答-------------------- 帅哥,上面的好像不是C#的;小妹只会C# --------------------编程问答--------------------
引用 2 楼 u010192842 的回复:

鼠标模拟

  TMouseInput记录结构的声明如下:

  tagMOUSEINPUT = packed record
    dx: Longint;
    dy: Longint;
    mouseData: DWORD;
    dwFlags: DWORD;
    time: DWORD;
    dwExtraInfo: DWORD;
  end;
  TMouseInput = tagMOUSEINPUT;

  其中dx、dy是鼠标移动时的坐标差(不是象素单位),在鼠标移动时有效。mouseData是鼠标滚轮滚动值,在滚动鼠标滚轮时有效。当mouseData小于0时向下滚动,当mouseData大于0时向上滚动,mouseData的绝对值一般设为120。dwFlags指定鼠标所进行的操作,例如,MOUSEEVENTF_MOVE表示移动鼠标,MOUSEEVENTF_LEFTDOWN表示按下鼠标左键,MOUSEEVENTF_LEFTUP表示放开鼠标左键。time是时间戳,可以使用API函数GetTickCount的返回值。dwExtraInfo是扩展信息,可以使用API函数GetMessageExtraInfo的返回值。例如单击鼠标左键的程序如下:

procedure MouseClick;
var
    Inputs : array [0..1] of TInput;
begin
    Inputs[0].Itype:=INPUT_MOUSE;
    with Inputs[0].mi do
    begin
        dx:=0;
        dy:=0;
        mouseData:=0;
        dwFlags:=MOUSEEVENTF_LEFTDOWN;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    Inputs[1].Itype:=INPUT_MOUSE;
    with Inputs[1].mi do
    begin
        dx:=0;
        dy:=0;
        mouseData:=0;
        dwFlags:=MOUSEEVENTF_LEFTUP;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    SendInput(2,Inputs[0],SizeOf(TInput));
end;

  鼠标的移动总是很麻烦,上面的dx、dy不是以象素为单位的,而是以鼠标设备移动量为单位的,它们之间的比值受鼠标移动速度设置的影响。具体的解决方法我已经在《Delphi下利用WinIo模拟鼠标键盘详解》一文中进行了讨论,这里不再重复。dwFlags可以设置一个MOUSEEVENTF_ABSOLUTE标志,这使得可以用另外一种方法移动鼠标。当dwFlags设置了MOUSEEVENTF_ABSOLUTE标志,dx、dy为屏幕坐标值,表示将鼠标移动到dx,dy的位置。但是这个坐标值也不是以象素为单位的。这个值的范围是0到65535($FFFF),当dx等于0、dy等于0时表示屏幕的最左上角,当dx等于65535、dy等于65535时表示屏幕的最右下角,相当于将屏幕的宽和高分别65536等分。API函数GetSystemMetrics(SM_CXSCREEN)可以返回屏幕的宽度,函数GetSystemMetrics(SM_CYSCREEN)可以返回屏幕的高度,利用屏幕的宽度和高度就可以将象素坐标换算成相应的dx、dy。注意:这种换算最多会出现1象素的误差。例如:将鼠标指针移动到屏幕150,120坐标处的程序如下:

procedure MouseMove;
var
    Input : TInput;
begin
    Input.Itype:=INPUT_MOUSE;
    with Input.mi do
    begin
        dx:=($FFFF div (GetSystemMetrics(SM_CXSCREEN)-1)) * 150;
        dy:=($FFFF div (GetSystemMetrics(SM_CYSCREEN)-1)) * 120;
        mouseData:=0;
        dwFlags:=MOUSEEVENTF_MOVE or MOUSEEVENTF_ABSOLUTE;
        time:=GetTickCount;
        dwExtraInfo:=GetMessageExtraInfo;
    end;
    SendInput(1,Input,SizeOf(TInput));
end;



能改成C#的吗,谢谢;多多加分!!!!! --------------------编程问答--------------------

//定义鼠标的flag值:

    const int MouseEvent_Absolute = 0x8000;

    const int MouserEvent_Hwheel = 0x01000;

    const int MouseEvent_Move = 0x0001;

    const int MouseEvent_Move_noCoalesce = 0x2000;

    const int MouseEvent_LeftDown = 0x0002;

    const int MouseEvent_LeftUp = 0x0004;

    const int MouseEvent_MiddleDown = 0x0020;

    const int MouseEvent_MiddleUp = 0x0040;

    const int MouseEvent_RightDown = 0x0008;

    const int MouseEvent_RightUp = 0x0010;

    const int MouseEvent_Wheel = 0x0800;

    const int MousseEvent_XUp = 0x0100;

    const int MousseEvent_XDown = 0x0080;

   // c#中模拟鼠标操作的代码:

    for (i = X; i <= X+width; i += 450)

    //X为Flash窗口的左上角的x轴绝对坐标值.屏幕左上角坐标是(0,0).width是Flash窗口宽度.

    {

    for (j = Y; j <= Y +height; j+=150) //Y为Flash窗口的左上角的y轴绝对坐标值.height是Flash窗口高度.

    {

    MouseInput myMinput = new MouseInput();

    myMinput.dx = i;

    myMinput.dy = j;

    myMinput.Mousedata = 0;

    myMinput.dwFlag = MouseEvent_Absolute | MouseEvent_Move | MouseEvent_LeftDown | MouseEvent_LeftUp;

    myMinput.time = 0;

    Input[] myInput = new Input[1];

    myInput[0] = new Input();

    myInput[0].type = 0;

    myInput[0].mi = myMinput;

    UInt32 result = SendInput((uint)myInput.Length, myInput, Marshal.SizeOf(myInput[0].GetType()));

    if (result == 0)

    {

    MessageBox.Show(“fail”);

    }

    }

    }

   /* 知识点:将像素坐标转化为绝对坐标:

    API中MouseInput结构中的dx,dy含义是绝对坐标,是相对屏幕的而言的,屏幕左上角的坐标为(0,0),右下角的坐标为(65535,65535).而我们在C#中获得的对象(Frame,button,flash等)的坐标都是像素坐标,是跟你当前屏幕的分辨率相关的.假如你的显示器分辨率是1024*768,那么屏幕左上角的像素坐标是(0,0),右下角坐标为(1024,768).转换函数如下:
*/

    dx = x * (65335/ScreenWidth) //x,y为像素坐标.

    dy = y * (65335/ScreenHeight)//ScreenWidth和ScreenHeight,其实是当前显示器的分辨率,获得方法是

ScreenWidth=Screen.PrimaryScreen.WorkingArea.Width;
ScreenHeight=Screen.PrimaryScreen.WorkingArea.Height;

--------------------编程问答-------------------- 那两个FOR循环是实现具体什么功能? --------------------编程问答--------------------
引用 5 楼 u010192842 的回复:

//定义鼠标的flag值:

    const int MouseEvent_Absolute = 0x8000;

    const int MouserEvent_Hwheel = 0x01000;

    const int MouseEvent_Move = 0x0001;

    const int MouseEvent_Move_noCoalesce = 0x2000;

    const int MouseEvent_LeftDown = 0x0002;

    const int MouseEvent_LeftUp = 0x0004;

    const int MouseEvent_MiddleDown = 0x0020;

    const int MouseEvent_MiddleUp = 0x0040;

    const int MouseEvent_RightDown = 0x0008;

    const int MouseEvent_RightUp = 0x0010;

    const int MouseEvent_Wheel = 0x0800;

    const int MousseEvent_XUp = 0x0100;

    const int MousseEvent_XDown = 0x0080;

   // c#中模拟鼠标操作的代码:

    for (i = X; i <= X+width; i += 450)

    //X为Flash窗口的左上角的x轴绝对坐标值.屏幕左上角坐标是(0,0).width是Flash窗口宽度.

    {

    for (j = Y; j <= Y +height; j+=150) //Y为Flash窗口的左上角的y轴绝对坐标值.height是Flash窗口高度.

    {

    MouseInput myMinput = new MouseInput();

    myMinput.dx = i;

    myMinput.dy = j;

    myMinput.Mousedata = 0;

    myMinput.dwFlag = MouseEvent_Absolute | MouseEvent_Move | MouseEvent_LeftDown | MouseEvent_LeftUp;

    myMinput.time = 0;

    Input[] myInput = new Input[1];

    myInput[0] = new Input();

    myInput[0].type = 0;

    myInput[0].mi = myMinput;

    UInt32 result = SendInput((uint)myInput.Length, myInput, Marshal.SizeOf(myInput[0].GetType()));

    if (result == 0)

    {

    MessageBox.Show(“fail”);

    }

    }

    }

   /* 知识点:将像素坐标转化为绝对坐标:

    API中MouseInput结构中的dx,dy含义是绝对坐标,是相对屏幕的而言的,屏幕左上角的坐标为(0,0),右下角的坐标为(65535,65535).而我们在C#中获得的对象(Frame,button,flash等)的坐标都是像素坐标,是跟你当前屏幕的分辨率相关的.假如你的显示器分辨率是1024*768,那么屏幕左上角的像素坐标是(0,0),右下角坐标为(1024,768).转换函数如下:
*/

    dx = x * (65335/ScreenWidth) //x,y为像素坐标.

    dy = y * (65335/ScreenHeight)//ScreenWidth和ScreenHeight,其实是当前显示器的分辨率,获得方法是

ScreenWidth=Screen.PrimaryScreen.WorkingArea.Width;
ScreenHeight=Screen.PrimaryScreen.WorkingArea.Height;



那两个FOR循环是实现具体什么功能?  FOR循环要怎么调用,我稀里糊涂
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,