用C#调用API的“USER32.DLL”,控制开始菜单的弹出。也就是模拟用户单击键盘上的WINDOWS键。
我找了好久了,百度上出了一大堆。就是下面这段程序。。也找不到原作者是,写的不是很清楚。看不懂。大致看懂了有以下几点:
User32是他写的一个类。类里有几个结构和方法。
还有几点不明白。
1:第三行 new EnumProc(Enum),这个是什么,请高人解释一下。
2:程序流程也不太清楚。
3:还有API。也不是很清楚。 基本思路为,寻找开始菜单按钮窗口,并模拟用户单击
void pop()
{
User32.EnumWindows(new EnumProc(Enum), 0);
}
private bool Enum(IntPtr hWnd, uint param)
{
User32.STRINGBUFFER buffer=new User32.STRINGBUFFER();
User32.GetClassName(hWnd, ref buffer, 256);
if (buffer.szText == "Shell_TrayWnd")
{
User32.EnumChildWindows(hWnd, new EnumProc(Enum2), 0);
return false;
}
else return true;
}
IntPtr lastForeGroundWindow;
private bool Enum2(IntPtr hWnd, uint param)
{
User32.STRINGBUFFER buffer = new User32.STRINGBUFFER();
User32.GetClassName(hWnd, ref buffer, 256);
if (buffer.szText == "Button")
{
if (User32.SendMessage(hWnd, WndMsg.BM_GETSTATE, 0, 0) ==
User32.BST_PUSHED)
{
User32.SetForegroundWindow(lastForeGroundWindow);
}
else
{
lastForeGroundWindow = User32.GetForegroundWindow();
User32.SetForegroundWindow(hWnd);
User32.PostMessage(hWnd, WndMsg.BM_CLICK, 0, 0);
}
return true;
}
else
return false;
}using System; using System.Runtime.InteropServices; public delegate bool CallBack(int hwnd, int lParam); public class EnumWindowsApp { [DllImport("user32")] public static extern int EnumWindows(CallBack x, int y); public static void Main() { CallBack myCallBack = new CallBack(EnumWindowsApp.Report); EnumWindows(myCallBack, 0); } public static bool Report(int hwnd, int lParam) { Console.Write("Window handle is :"); Console.WriteLine(hwnd); return true; } }
我找了好久了,百度上出了一大堆。就是下面这段程序。。也找不到原作者是,写的不是很清楚。看不懂。大致看懂了有以下几点:
User32是他写的一个类。类里有几个结构和方法。
还有几点不明白。
1:第三行 new EnumProc(Enum),这个是什么,请高人解释一下。
2:程序流程也不太清楚。
3:还有API。也不是很清楚。 基本思路为,寻找开始菜单按钮窗口,并模拟用户单击
void pop()
{
User32.EnumWindows(new EnumProc(Enum), 0);
}
private bool Enum(IntPtr hWnd, uint param)
{
User32.STRINGBUFFER buffer=new User32.STRINGBUFFER();
User32.GetClassName(hWnd, ref buffer, 256);
if (buffer.szText == "Shell_TrayWnd")
{
User32.EnumChildWindows(hWnd, new EnumProc(Enum2), 0);
return false;
}
else return true;
}
IntPtr lastForeGroundWindow;
private bool Enum2(IntPtr hWnd, uint param)
{
User32.STRINGBUFFER buffer = new User32.STRINGBUFFER();
User32.GetClassName(hWnd, ref buffer, 256);
if (buffer.szText == "Button")
{
if (User32.SendMessage(hWnd, WndMsg.BM_GETSTATE, 0, 0) ==
User32.BST_PUSHED)
{
User32.SetForegroundWindow(lastForeGroundWindow);
}
else
{
lastForeGroundWindow = User32.GetForegroundWindow();
User32.SetForegroundWindow(hWnd);
User32.PostMessage(hWnd, WndMsg.BM_CLICK, 0, 0);
}
return true;
}
else
return false;
}using System; using System.Runtime.InteropServices; public delegate bool CallBack(int hwnd, int lParam); public class EnumWindowsApp { [DllImport("user32")] public static extern int EnumWindows(CallBack x, int y); public static void Main() { CallBack myCallBack = new CallBack(EnumWindowsApp.Report); EnumWindows(myCallBack, 0); } public static bool Report(int hwnd, int lParam) { Console.Write("Window handle is :"); Console.WriteLine(hwnd); return true; } }
回调函数
public partial class Form1 : Form
{
[StructLayout(LayoutKind.Sequential)]
//定义一个表示上下左右的结构
struct NativeRECT
{
public int left;
public int top;
public int right;
public int bottom;
} [Flags]
//定义鼠标动作
enum MouseEventFlag : uint
{
Move = 0x0001,
LeftDown = 0x0002,
LeftUp = 0x0004,
RightDown = 0x0008,
RightUp = 0x0010,
MiddleDown = 0x0020,
MiddleUp = 0x0040,
XDown = 0x0080,
XUp = 0x0100,
Wheel = 0x0800,
VirtualDesk = 0x4000,
Absolute = 0x8000
}
#region 定义需要用到的Windows API
[DllImport("user32.dll")]
static extern bool SetCursorPos(int X, int Y); [DllImport("user32.dll")]
static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, UIntPtr extraInfo); [DllImport("user32.dll")]
static extern IntPtr FindWindow(string strClass, string strWindow); [DllImport("user32.dll")]
static extern IntPtr FindWindowEx(HandleRef hwndParent, HandleRef hwndChildAfter, string strClass, string strWindow); [DllImport("user32.dll")]
static extern bool GetWindowRect(HandleRef hwnd, out NativeRECT rect);
#endregion private Point endPosition; public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
NativeRECT rect;
//找到任务栏
IntPtr ptrTaskbar = FindWindow("Shell_TrayWnd", null);
if (ptrTaskbar == IntPtr.Zero)
{
MessageBox.Show("No taskbar found.");
return;
} //找到任务栏上的开始菜单按钮
IntPtr ptrStartBtn = FindWindowEx(new HandleRef(this, ptrTaskbar), new HandleRef(this, IntPtr.Zero), "Button", null);
if (ptrStartBtn == IntPtr.Zero)
{
MessageBox.Show("No start button found.");
return;
} //获取开始菜单按钮的上下左右坐标点
GetWindowRect(new HandleRef(this, ptrStartBtn), out rect); //计算出开始菜单按钮的中央位置坐标
endPosition.X = (rect.left + rect.right) / 2;
endPosition.Y = (rect.top + rect.bottom) / 2; //将鼠标定位到开始菜单按钮的中央位置
SetCursorPos(endPosition.X, endPosition.Y);
//模拟鼠标左键按下动作
mouse_event(MouseEventFlag.LeftDown, 0, 0, 0, UIntPtr.Zero);
mouse_event(MouseEventFlag.LeftUp, 0, 0, 0, UIntPtr.Zero);
}
}
using System.Runtime.InteropServices;
void pop()
{
//调用EnumWindows api枚举窗口,EnumWindows 的用法参见msdn。大体上就是每找到一个窗口就调用callback函数。
User32.EnumWindows(new EnumProc(Enum), 0);
} private bool Enum(IntPtr hWnd, uint param)
{
User32.STRINGBUFFER buffer=new User32.STRINGBUFFER();
//当找到一个ClassName叫Shell_TrayWnd的时候再枚举这个窗口的子窗口,Shell_TrayWnd应该就是任务栏。
User32.GetClassName(hWnd, ref buffer, 256);
if (buffer.szText == "Shell_TrayWnd")
{
User32.EnumChildWindows(hWnd, new EnumProc(Enum2), 0);
return false;
}
else return true;
}
IntPtr lastForeGroundWindow;
private bool Enum2(IntPtr hWnd, uint param)
{
User32.STRINGBUFFER buffer = new User32.STRINGBUFFER();
//再在子窗口找ClassName是button的窗口
User32.GetClassName(hWnd, ref buffer, 256);
if (buffer.szText == "Button")
{
if (User32.SendMessage(hWnd, WndMsg.BM_GETSTATE, 0, 0) ==
User32.BST_PUSHED)
{
//如果这个窗口的State是BST_PUSHED,就调用SetForegroundWindow把前一个前景窗口设置成当前的前景窗口。
User32.SetForegroundWindow(lastForeGroundWindow);
}
else
{
//否则给这个button发送click消息
lastForeGroundWindow = User32.GetForegroundWindow();
User32.SetForegroundWindow(hWnd);
User32.PostMessage(hWnd, WndMsg.BM_CLICK, 0, 0);
}
return true;
}
else
return false;
}
ms-help://MS.MSDNQTR.v90.en/dv_fxinterop/html/eca7606e-ebfb-4f47-b8d9-289903fdc045.htm
你可以Ctrl+Esc弹出开始菜单