首页 > 代码库 > 获得其他程序弹出菜单的内容(一个困扰许久的问题o(╯□╰)o)

获得其他程序弹出菜单的内容(一个困扰许久的问题o(╯□╰)o)

刚开始到现在公司的时候接到一个任务:开发一个activex控件,自动操作本地exe程序,当时遇到弹出菜单无法获取的问题,还好不影响,最近又遇到这个问题,绕不过去了,于是昨天花了一个上午百度了个遍,总算解决了。。。网上也有人遇到类似的问题,但是都没人给出一个完整解决方案来,所以记录下来,以备后用。

 

技术分享

核心代码:windows系统其实只有一个弹出菜单,类型为#32768,但是FindWindow获取的是窗口句柄,需要发送MN_GETHMENU 0x01E1消息转换成菜单句柄,然后通过菜单的API进行其他操作,这里是获取的菜单的文字内容

            var hand = WindowsAPI.FindWindow("Notepad", "无标题 - 记事本");            WindowsAPI.SetForegroundWindow(hand);            var cwnd = WindowsAPI.FindWindowEx(hand, IntPtr.Zero, "Edit", null);            {                System.Threading.Thread.Sleep(100);                WindowsAPI.PostMessage(cwnd, (int)WindowsAPI.WndMsg.WM_RBUTTONDOWN, (int)WindowsAPI.WndMsg.MK_RBUTTON, WindowsAPI.MAKELONG(100, 100));                WindowsAPI.PostMessage(cwnd, (int)WindowsAPI.WndMsg.WM_RBUTTONUP, (int)WindowsAPI.WndMsg.MK_RBUTTON, WindowsAPI.MAKELONG(100, 100));            }            System.Threading.Thread.Sleep(100);            hand = WindowsAPI.FindWindow("#32768", null);            IntPtr hMenu = WindowsAPI.SendMessage(hand, 0x01E1, 0, 0);            int n = WindowsAPI.GetMenuItemCount(hMenu);            var meg = new StringBuilder(100);            n = WindowsAPI.GetMenuString(hMenu, (uint)WindowsAPI.GetMenuItemID(hMenu, 0), meg, 100, (uint)0);            MessageBox.Show(meg.ToString());

API封装

        //查找指定窗体        [DllImport("User32.dll", EntryPoint = "FindWindow")]        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);        //发送窗口消息        [DllImport("user32.dll", EntryPoint = "SendMessage")]        public static extern IntPtr SendMessage(IntPtr hwnd, int wMsg, int wParam, uint lParam);        public enum WndMsg        {            WM_CLICK = 0x00F5,            WM_LBUTTONDOWN = 0x0201,            WM_LBUTTONUP = 0x202,            WM_RBUTTONDOWN = 0x0204,            WM_RBUTTONUP = 0x205,            MK_LBUTTON = 0x0001,            MK_RBUTTON = 0x0002,            WM_SETTEXT = 0x000C,            BM_CLICK = 0xF5        }        [DllImport("USER32.dll", EntryPoint = "GetMenuItemCount", CharSet = CharSet.Unicode)]        public static extern int GetMenuItemCount(IntPtr hMenu);        [DllImport("User32.dll")]        public static extern IntPtr GetSystemMenu(IntPtr hWnd, Int32 bRevert);        [DllImport("User32.dll")]        public static extern int GetMenuString(IntPtr hMenu, uint uIDItem, StringBuilder lpString, int nMaxCount, uint uFlag);                [DllImport("User32.dll")]        public static extern int GetMenuItemID(IntPtr hMenu, int nPos);

 其他一些常用API封装

        //读写ini文件        [DllImport("kernel32")]        public static extern bool WritePrivateProfileString(string section, string key, string val, string filePath);        [DllImport("kernel32")]        public static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retStr, int size, string filePath);        private delegate bool WNDENUMPROC(IntPtr hWnd, int lParam);        [DllImport("user32.dll", ExactSpelling = true)]        private static extern bool EnumChildWindows(IntPtr hwndParent, WNDENUMPROC lpEnumFunc, int lParam);        [DllImport("user32.dll")]        private static extern bool EnumWindows(WNDENUMPROC lpEnumFunc, int lParam);        //[DllImport("user32.dll")]         //private static extern IntPtr FindWindowW(string lpClassName, string lpWindowName);         [DllImport("user32.dll")]        private static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);        [DllImport("user32.dll")]        private static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);        public struct WindowInfo        {            public IntPtr hWnd;            public string szWindowName;            public string szClassName;        }        //遍历窗口子窗口控件        public static List<WindowInfo> GetAllChildWindows(IntPtr handle)        {            List<WindowInfo> wndList = new List<WindowInfo>();            EnumChildWindows(handle, delegate(IntPtr hWnd, int lParam)            {                WindowInfo wnd = new WindowInfo();                StringBuilder sb = new StringBuilder(256);                //get hwnd                 wnd.hWnd = hWnd;                //get window name                 GetWindowTextW(hWnd, sb, sb.Capacity);                wnd.szWindowName = sb.ToString();                //get window class                 GetClassNameW(hWnd, sb, sb.Capacity);                wnd.szClassName = sb.ToString();                //add it into list                 wndList.Add(wnd);                return true;            }, 0);            return wndList;        }        public static List<WindowInfo> GetAllDesktopWindows()        {            List<WindowInfo> wndList = new List<WindowInfo>();            //enum all desktop windows             EnumWindows(delegate(IntPtr hWnd, int lParam)            {                WindowInfo wnd = new WindowInfo();                StringBuilder sb = new StringBuilder(256);                //get hwnd                 wnd.hWnd = hWnd;                //get window name                 GetWindowTextW(hWnd, sb, sb.Capacity);                wnd.szWindowName = sb.ToString();                //get window class                 GetClassNameW(hWnd, sb, sb.Capacity);                wnd.szClassName = sb.ToString();                //add it into list                 wndList.Add(wnd);                return true;            }, 0);            return wndList;        }

 

源码就懒得发了,就这么几句,但是为了这几句代码,折腾的够呛,虽然以前用过VC++但是这么底层的API还真是没用过。。。

获得其他程序弹出菜单的内容(一个困扰许久的问题o(╯□╰)o)