获得其他程序弹出菜单的内容(一个困扰许久的问题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还真是没用过。。。

原文地址:https://www.cnblogs.com/HelliX/p/5898857.html