獲得其他程序彈出菜單的內容(一個困擾許久的問題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還真是沒用過。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM