[C#.NET][VB.NET] 用 Win32 API 控制 外部應用程式選單

[C#.NET][VB.NET] 用 Win32 API 控制 外部應用程式選單

1.這並不是用SendKey所組成的,所以不管應用程式是否在最上層,都能控制的到。

2.匯入 System.Runtime.InteropServicesSystem.Threading 命名空間

3.選單控制主要由下列三隻API組成

        [DllImport("user32.dll", EntryPoint = "GetMenu")]

        public static extern int GetMenu(

            int hwnd

        );

        [DllImport("user32.dll", EntryPoint = "GetSubMenu")]

        public static extern int GetSubMenu(

            int hMenu,

            int nPos

        );

        [DllImport("user32.dll", EntryPoint="GetMenuItemID")]

        public static extern int GetMenuItemID(

            int hMenu,

            int nPos

        );

 

4.GetMenu所指的就是"主選單"工具列,如下圖所示。

快照-20097663059

而GetSubMenu指的就是"主選單"內的"子選單",由下圖可看到項目有五個"子選單",分別為:檔案(F)、編輯(E)、格式(O)、檢視(V)、說明(H)。

快照-2009766332

GetMenuItemID則是"子選單"中的"項目"

快照-20097663522

5.選單API的啟始值是0,GetSubMenu(gm, 0)表示第1個選單

快照-2009766332

GetSubMenu(gm, 1)表示第2個選單

快照-20097664922

 

6.GetMenuItemID用法同如上所示 ,int id = GetMenuItemID(gm, 3),表示第4個項目。

快照-20097663522

7.完整範例

C#

using System;

using System.Windows.Forms;

using System.Runtime.InteropServices;

using System.Diagnostics;

using System.Threading;

 

namespace CS_ControlMenu

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

        private const int WM_COMMAND = 0x111;

        [DllImport("user32.dll", EntryPoint = "FindWindow")]

        public static extern int FindWindow(

            string lpClassName,

            string lpWindowName

        );

        [DllImport("user32.dll", EntryPoint = "GetMenu")]

        public static extern int GetMenu(

            int hwnd

        );

        [DllImport("user32.dll", EntryPoint = "GetSubMenu")]

        public static extern int GetSubMenu(

            int hMenu,

            int nPos

        );

        [DllImport("user32.dll", EntryPoint="GetMenuItemID")]

        public static extern int GetMenuItemID(

            int hMenu,

            int nPos

        );

        [DllImport("user32.dll", EntryPoint = "PostMessage")]

        public static extern int PostMessage(

            int hwnd,

            int wMsg,

            int wParam,

            int lParam

        );

 

        private void button1_Click(object sender, EventArgs e)

        {

            //呼叫外部程式

            Process.Start(@"C:\windows\system32\notepad.exe");

            //等執行程式一下下

            Thread.Sleep(100);

            //取得外部程式的Handle

            int NotepadHwnd = FindWindow("notepad", null);

            //取得外部程式的選單Handle

            int gm = GetMenu(NotepadHwnd);

            //取得第一個子選單Handle

            gm = GetSubMenu(gm, 0); //選單的句柄 改變後面的0,就可以得到不同選單的句柄

            //取得子選單的ID

            int id = GetMenuItemID(gm, 3); //子選單"另存新檔"的ID

            //執行子選單

            PostMessage (NotepadHwnd, WM_COMMAND, id, 0);

 

        }

 

 

    }

}

VB

Imports System.Runtime.InteropServices

Imports System.Threading

 

Public Class Form1

    Private Const WM_COMMAND As Integer = &H111

    <DllImport("user32.dll", EntryPoint:="FindWindow")> _

    Public Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As Integer

    End Function

    <DllImport("user32.dll", EntryPoint:="GetMenu")> _

    Public Shared Function GetMenu(ByVal hwnd As Integer) As Integer

    End Function

    <DllImport("user32.dll", EntryPoint:="GetSubMenu")> _

    Public Shared Function GetSubMenu(ByVal hMenu As Integer, ByVal nPos As Integer) As Integer

    End Function

    <DllImport("user32.dll", EntryPoint:="GetMenuItemID")> _

    Public Shared Function GetMenuItemID(ByVal hMenu As Integer, ByVal nPos As Integer) As Integer

    End Function

    <DllImport("user32.dll", EntryPoint:="PostMessage")> _

    Public Shared Function PostMessage(ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    End Function

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        '呼叫外部程式

        Process.Start("C:\windows\system32\notepad.exe")

        '等執行程式一下下

        Thread.Sleep(100)

        '取得外部程式的Handle

        Dim NotepadHwnd As Integer = FindWindow("notepad", Nothing)

        '取得外部程式的選單Handle

        Dim gm As Integer = GetMenu(NotepadHwnd)

        '取得第一個子選單Handle

        gm = GetSubMenu(gm, 0) '選單的句柄 改變後面的0,就可以得到不同選單的句柄

        '取得子選單的ID

        Dim id As Integer = GetMenuItemID(gm, 3)'子選單"另存新檔"的ID

        '執行子選單

        PostMessage(NotepadHwnd, WM_COMMAND, id, 0)

    End Sub

End Class

範例下載:ControlMenu.rar

若有謬誤,煩請告知,新手發帖請多包涵


Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET

Image result for microsoft+mvp+logo