C#或者MFC 通过SendMessage 修改 外部程序界面combox,edit checkbox,子界面上的控件 并使其生效

近一段时间刚刚接触C#,需要做一个修改外部程序界面上面的值 然后自动点击确认即可

修改界面如下 通过C#程序修改 仅做记录,以免以后忘记

C#或者MFC 通过SendMessage 修改 外部程序界面combox,edit checkbox,子界面上的控件 并使其生效_第1张图片

 

我写一个C# 控制台程序

首先要用spy++来获取每个固定控件的ID

spy++ 地址 链接: https://pan.baidu.com/s/1gwuHMf2Umg_wtxVGFoRoDQ 提取码: mggv

简单介绍一下spy++的使用方法吧我也是刚接触

spy++打开界面如下

C#或者MFC 通过SendMessage 修改 外部程序界面combox,edit checkbox,子界面上的控件 并使其生效_第2张图片

 

 

 

按下CTRL+F 搜索 或者手动点击界面上面一个望远镜的图标

 

C#或者MFC 通过SendMessage 修改 外部程序界面combox,edit checkbox,子界面上的控件 并使其生效_第3张图片

 

 

点击Find Window 界面中的Finder Tool后面的 鼠标左键不松手 ,然后放到控件上面

放好之后,点击Find Windows下面OK按钮

C#或者MFC 通过SendMessage 修改 外部程序界面combox,edit checkbox,子界面上的控件 并使其生效_第4张图片

 

其中Control ID 就是该控件的ID 该ID是唯一的,句柄是00350A30 这个是每次打开都会变掉的

 

环境:VS2015+win10 64位 台式机

 

下面开始放代码吧  仅供参考  

 

using System;
using System.Runtime.InteropServices;
using System.Text;
using NS_INI;
using NS_TRACELOG;
using System.Diagnostics;

/*
 * ModifyX265 -CModifyX265 主要用于配置H265软件安装出来的界面的配置
 */
namespace ModifyX265
{

    public class CModifyX265
    {

        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        public extern static IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("User32.dll", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hHandleParent, IntPtr hHandleChildAfter, string lpClassName, string lpWindowName);

        [DllImport("User32.dll", EntryPoint = "FindEx")]
        public static extern IntPtr FindEx(IntPtr hHandle, IntPtr hHandleChild, string lpClassName, string lpWindowName);

        //[DllImport("user32.dll", EntryPoint = "GetWindowText")]
        //public static extern int GetWindowText(int hHandle, string lpString, int cch);


        //用于一般控件发送事件
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(IntPtr hHandle, int Msg, IntPtr wParam, StringBuilder lParam);


        //用于  edit 发送事件
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessageString(IntPtr hHandle, int Msg, IntPtr wParam, string lParam);


        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage_A(IntPtr hHandle, int Msg, int wParam, int lParam);

        [DllImport("user32.dll ", EntryPoint = "GetDlgItem")]
        public static extern IntPtr GetDlgItem(IntPtr hParent, int nIDParentItem);

        [DllImport("user32.dll", EntryPoint = "GetWindowText")]
        public static extern int GetWindowText(IntPtr hHandle, StringBuilder lpString, int cch);

        [DllImport("user32.dll", EntryPoint = "GetDlgItemTextA")]
        private static extern int GetDlgItemText(IntPtr hDlg, int nIDDlgItem, [Out]StringBuilder lpString, int nMaxCount);


        #region 这里是根据spy++ 拿到H265配置界面上面的控件ID,根据控件ID即可操控控件的方法和属性
        const int m_nPreSetHandle = 0x3F1;                           //preset句柄值
        const int m_nTuningHandle = 0x3F2;                           //Tuning句柄值
        const int m_nPrrofileHandle = 0x3F3;                         //Profile句柄值
        const int m_nLevelHandle = 0x3F4;                            //Level句柄值
        const int m_nFastDecodeHandle = 0x3F5;                       //FastDecode句柄值
        const int m_nFastDecodeColorSpaceHandle = 0x415;          //FastDecode后面要转换的句柄值
        const int m_nZeroLatencyHandle = 0x3F6;                      //ZeroLatency句柄值
        const int m_nRateControlHandle = 0x3F7;                      //RateControl句柄值
        const int m_nRateControlTextHandle = 0x3F9;                  //RateControl设置后 Ratefactor或者Target bitrate句柄值
        const int m_nCreateStatusFileHandle = 0x3FD;                 //CreateStatusFile句柄值
        const int m_nOutputModeHandle = 0x401;                       //OutputMode句柄值
        const int m_nVFWFourCCHandle = 0x402;                        //VFWFourCC句柄值
        const int m_nVirtualDubHackHandle = 0x403;                   //VirtualDubHack句柄值
        const int m_nSARWidthHandle = 0x407;                         //SAR Width句柄值
        const int m_nSARHeightHandle = 0x408;                        //SAR Height句柄值
        const int m_nLogLevelHandle = 0x409;                         //Log Level句柄值
        const int m_nDisableAllCpuOptimizationsHandle = 0x40C;       //Disable All Cpu Optimizations句柄值
        const int m_nDisableDecoderSWHWHandle = 0x40D;               //Disable Decoder SW/HW句柄值
        const int m_nEnableHwDecoderHandle = 0x40E;                  //Enable Hw Decoder句柄值
        const int m_nBtnOkHandle = 0x01; //确定按钮
        const int m_nBtnCancelHandle = 0x02; //取消按钮
        #endregion


        #region  这里是windows消息映射对应需要对控件做相应操作
        const int WM_SETTEXT = 0x0C;  //设置框里面的值
        const int WM_GETTEXT = 0x0D;  //获取文本框里面的值
        const int LB_SETCURSEL = 0x0186;
        const int BM_SETCHECK = 0x00F1;  //设置是否选中
        const int BM_GETCHECK = 0x00F0;  //获取是否选中
        const int BM_CLICK = 0x00F5; //按钮单机
        const int MB_OK = 0x00000000; //确认按钮
        const int WM_SETFOCUS = 0x07; //获取焦点
        const int WM_LBUTTONDOWN = 0x0201;
        const int WM_LBUTTONUP = 0x0202;
        const int WM_KEYDOWN = 0x0100;
        const int WM_KEYUP = 0x0101;
        const int WM_COMMAND = 0x0111;
        const int CB_SELECTSTRING = 0x014D;
        const int CB_SHOWDROPDOWN = 0x014F; //展开ComboBox列表框
        const int CB_SETCURSEL = 0x014E;//修改下拉框 默认选中那一项 相当于MFC中的SetCurlSel
        const int BST_UNCHECKED = 0x0000; //checkbox没有选中
        const int BST_CHECKED = 0x0001; //check box 设置选中
        #endregion


        #region 这里是windows消息 键盘键位
        const int VK_RETURN = 0x0D;
        const int VK_SPACE = 0x20;
        #endregion


        //这里是主窗口句柄H265
        public static IntPtr m_MainHandle;


        //这里是每个具体控件对应的命名 主要用于读取配置文件和其他操作
        public static int m_nPreset;
        public static int m_nTuning;
        public static int m_nProfile;
        public static int m_nLevel;
        public static int m_nFastDecode;
        public static int m_nFastDecodeColorSpace;
        public static int m_nZeroLatency;
        public static int m_nRateControl;
        public static int m_nRatefactorOrAveragebrtrate;
        public static int m_nCreateStatusFile;
        public static int m_nOutputMode;
        public static int m_nVfwFourCC;
        public static int m_nVirtualDubHack;
        public static int m_nSarWidth;
        public static int m_nSarHeight;
        public static int m_nLogLevel;
        public static int m_nDisableAllCpuOptimizations;
        public static int m_nDisableDecoderSwHw;
        public static int m_nEnableHwDecoder;
        public static int m_nBtnOk;
        public static int m_nBtnCancel;


        /*
         * strSession读取ini的session strKeyini的key IniType ini的类型 如int-0或者string-1
         */
        public static  string ReadIni(string strSession,string  strKey,int IniType)
        {
            string strOut = "";
            try
            {
                CIni.MstrFileName = Environment.CurrentDirectory + "\\config_x265.ini";
                if (IniType == 1)
                {//读取string类型的节点返回string值
                    strOut = CIni.IniReadString(strSession, strKey, "");
                }else 
                if (IniType == 0)
                {//读取string类型的节点返回int值
                    strOut = ( CIni.IniReadInt(strSession, strKey,-1) ).ToString();
                }
            }
            catch(Exception e)
            {
                CTraceLog.TraceLog("读取ini异常,Session=" + strSession+ "Key="+ strKey);
                strOut = "";
            }


            return strOut;

        }


        /*nType 类型combox textbox等 , edit - 1 ,combox- 2 ,checkbox - 3
         * nTypeHandle 类型的句柄 
         * strData 从配置文件中读取的值 strMsg描述*/
        public static void SetAllH265Item(int nType,int nTypeHandle,int nData,string strMsg)
        {
            StringBuilder buffer = new StringBuilder(1024);
            IntPtr TypeHandle = GetDlgItem(m_MainHandle, nTypeHandle);

            switch (nType)
            {
                case 1:
                    System.Threading.Thread.Sleep(10);
                    SendMessageString(TypeHandle, WM_SETTEXT, (IntPtr)nData, nData.ToString());
                    SendMessage(TypeHandle, WM_GETTEXT, (IntPtr)buffer.Capacity, buffer);
                    break;
                case 2:
                    SendMessage_A(TypeHandle, CB_SHOWDROPDOWN, 1, 0); //展开ComboBox列表框
                    SendMessage_A(TypeHandle, CB_SETCURSEL, nData, 0); //指向需要写入的下标
                    SendMessage_A(TypeHandle, WM_SETFOCUS, 0, 0); //设置焦点
                    System.Threading.Thread.Sleep(10);
                    SendMessage_A(TypeHandle, WM_KEYDOWN, VK_RETURN, 0); //模拟鼠标按下 
                    System.Threading.Thread.Sleep(10);
                    SendMessage_A(TypeHandle, WM_KEYUP, VK_RETURN, 0);//模拟鼠标放开

                    SendMessage(TypeHandle, WM_GETTEXT, (IntPtr)buffer.Capacity, buffer);//获取combox的值
                    break;
                case 3:
                    if (nData == 1)
                    {   //配置文件按钮状态为选中
                        if (SendMessage_A(TypeHandle, BM_GETCHECK, 0, 0) != BST_CHECKED)
                        { //如果没有选中 设置选中状态
                            System.Threading.Thread.Sleep(5);
                            SendMessage_A(TypeHandle, WM_KEYDOWN, VK_SPACE, 0); //模拟鼠标按下 
                            System.Threading.Thread.Sleep(5);
                            SendMessage_A(TypeHandle, WM_KEYUP, VK_SPACE, 0);//模拟鼠标放开
                        }

                    }else
                    {   //配置文件中按钮状态为未选中
                        if (SendMessage_A(TypeHandle, BM_GETCHECK, 0, 0) == BST_CHECKED)
                        { //如果按钮是选中的 那么再选一次 就变成了未选中状态
                            System.Threading.Thread.Sleep(5);
                            SendMessage_A(TypeHandle, WM_KEYDOWN, VK_SPACE, 0); //模拟鼠标按下 
                            System.Threading.Thread.Sleep(5);
                            SendMessage_A(TypeHandle, WM_KEYUP, VK_SPACE, 0);//模拟鼠标放开
                        }
                    }
                    
                    if (SendMessage_A(TypeHandle, BM_GETCHECK, 0, 0) == BST_CHECKED) //输出按钮选中状态
                    {
                        CTraceLog.TraceLog(strMsg + "是选中状态");

                    }
                    else
                    {
                        CTraceLog.TraceLog(strMsg + "不是选中状态");
                    }


                    break;
                default:
                    break;
            }

            if (nType != 3)
            {  //输出 combox 和edit 中获取到的值
                CTraceLog.TraceLog(strMsg + "取到的值为=" + buffer.ToString());
            }
            
            buffer.Clear();

        }


        public static void SetH265Form()
        {
            try
            {
                int n_Time = Convert.ToInt32(ReadIni("SOFTWAIT", "TIME", 0)); //从配置文件中读取H265界面打开扫描时间,预防H265界面没有打开
                int nWriteTime = n_Time;
                //主要是为了检测H265配置界面是否打开
                while (n_Time >= 0)
                {
                    m_MainHandle = FindWindow(null, "x265vfw configuration"); //获得H265界面句柄 
                    if (m_MainHandle != (IntPtr)0)
                    {
                        break;
                    }else
                    {
                        System.Threading.Thread.Sleep(1000);
                        n_Time --;
                    }
                }

                if (m_MainHandle != IntPtr.Zero)
                {

                    //开始设置 Preset 下拉框默认选中第几行   
                    m_nPreset = Convert.ToInt32( ReadIni("Preset", "INDEX",0 ));
                    SetAllH265Item(2, m_nPreSetHandle, m_nPreset, "Preset");


                    //开始设置 Tuning 下拉框默认选中第几行  
                    m_nTuning = Convert.ToInt32(ReadIni("Tuning", "INDEX", 0));
                    SetAllH265Item(2, m_nTuningHandle, m_nTuning, "Tuning");

                    //开始设置 Profile 下拉框默认选中第几行  
                    m_nProfile = Convert.ToInt32(ReadIni("Profile", "INDEX", 0));
                    SetAllH265Item(2, m_nPrrofileHandle, m_nProfile, "Profile");

                    //开始设置 Level 下拉框默认选中第几行  
                    m_nLevel = Convert.ToInt32(ReadIni("Level", "INDEX", 0));
                    SetAllH265Item(2, m_nLevelHandle, m_nLevel, "Level");

                    //开始设置 Fast Decode checkbox 是否选中   
                    m_nFastDecode = Convert.ToInt32(ReadIni("FastDecode", "ISCHECK", 0));
                    SetAllH265Item(3, m_nFastDecodeHandle, m_nFastDecode, "Fast Decode");

                    //开始设置 Fast Decode 后面colorspace 下拉框默认选中第几行
                    m_nFastDecodeColorSpace = Convert.ToInt32(ReadIni("Colorspace", "INDEX", 0));
                    SetAllH265Item(2, m_nFastDecodeColorSpaceHandle, m_nFastDecodeColorSpace, "Fast Decode ColorSpace");

                    //设置 Zero Latency checkbox是否选中 是否选中
                    m_nZeroLatency = Convert.ToInt32(ReadIni("ZeroLatency", "ISCHECK", 0));
                    SetAllH265Item(3, m_nZeroLatencyHandle, m_nZeroLatency, "Zero Latency");

                    //开始设置 RateControl CRF ABR 下拉框默认选中第几行
                    m_nRateControl = Convert.ToInt32(ReadIni("Ratecontrol", "INDEX", 0));
                    SetAllH265Item(2, m_nRateControlHandle, m_nRateControl, "RateControl CRF");

                    //开始设置 RateControl CRF ABR  后面的质量或者平均比特率  textbox 文本框
                    m_nRatefactorOrAveragebrtrate = Convert.ToInt32(ReadIni("Ratecontrol_CRF", "MINMAX", 0));
                    SetAllH265Item(1, m_nRateControlTextHandle, m_nRatefactorOrAveragebrtrate, " RateControl CRF ABR  后面的质量或者平均比特率");

                    //开始设置CreateStatusFile checkbox是否选中
                    m_nCreateStatusFile = Convert.ToInt32(ReadIni("CreateStatusFile", "ISCHECK", 0));
                    SetAllH265Item(3, m_nCreateStatusFileHandle, m_nCreateStatusFile, "Create Status File ");

                    //开始设置Output mode 下拉框默认选中第几行
                    m_nOutputMode = Convert.ToInt32(ReadIni("OutPutMode", "INDEX", 0));
                    SetAllH265Item(2, m_nOutputModeHandle, m_nOutputMode, "Output mode");

                    //开始设置 VFW FourCC 下拉框默认选中第几行
                    m_nVfwFourCC = Convert.ToInt32(ReadIni("VFWFourCC", "INDEX", 0));
                    SetAllH265Item(2, m_nVFWFourCCHandle, m_nVfwFourCC, "VFW FourCC");

                    //开始设置 VirtualDub Hack checkbox选中状态
                    m_nVirtualDubHack = Convert.ToInt32(ReadIni("VirtualDubHack", "ISCHECK", 0));
                    SetAllH265Item(3, m_nVirtualDubHackHandle, m_nVirtualDubHack, "VirtualDub Hack ");

                    //开始设置 SAR Width textbox
                    m_nSarWidth = Convert.ToInt32(ReadIni("SARWIDTH", "WIDTH", 0));
                    SetAllH265Item(1, m_nSARWidthHandle, m_nSarWidth, "SAR Width ");

                    //开始设置 SAR Height textbox
                    m_nSarHeight = Convert.ToInt32(ReadIni("SARHeight", "HEIGHT", 0));
                    SetAllH265Item(1, m_nSARHeightHandle, m_nSarHeight, "SAR Height ");

                    //开始设置 Log Level 
                    m_nLogLevel = Convert.ToInt32(ReadIni("LogLevel", "INDEX", 0));
                    SetAllH265Item(2, m_nLogLevelHandle, m_nLogLevel, "Log Level ");

                    //开始设置 Disable all cpu optimizations 
                    m_nDisableAllCpuOptimizations = Convert.ToInt32(ReadIni("DisableAllCpuOptimizations", "ISCHECK", 0));
                    SetAllH265Item(3, m_nDisableAllCpuOptimizationsHandle, m_nDisableAllCpuOptimizations, "DisableAllCpuOptimizations ");

                    //开始设置Disable Decoder Sw/hw
                    m_nDisableDecoderSwHw = Convert.ToInt32(ReadIni("DisableDecoderSWHW", "ISCHECK", 0));
                    SetAllH265Item(3, m_nDisableDecoderSWHWHandle, m_nDisableDecoderSwHw, "Disable Decoder Sw/hw ");

                    //开始设置 Enable Hw(DXVI) decoder
                    m_nEnableHwDecoder = Convert.ToInt32(ReadIni("DisableDecoderSWHW", "ISCHECK", 0));
                    SetAllH265Item(3, m_nEnableHwDecoderHandle, m_nEnableHwDecoder, "Enable Hw(DXVI) decoder");

                    System.Threading.Thread.Sleep(100);
                    //OK 确定按钮
                    IntPtr TypeHandle = GetDlgItem(m_MainHandle, m_nBtnOkHandle);
                    SendMessage_A(m_MainHandle, WM_COMMAND, m_nBtnOkHandle, m_nBtnOkHandle);
                    System.Threading.Thread.Sleep(100);
                    //SendMessageMain(TypeHandle, BM_CLICK, 0, 0);


                }
                else
                {
                    CTraceLog.TraceLog("从配置文件中读取到配置" + nWriteTime.ToString() + "秒后还是未检测到窗口,关闭本程序");
                }
            }
            catch (Exception e)
            {
                CTraceLog.TraceLog("配置出现异常: " + e.ToString());
            }
        }


        //H265会报错 RunDLL
        public static void CloseRunDll()
        {
            try
            {
                CTraceLog.TraceLog("开始关闭 RUN DLL窗口");
                IntPtr rulGandle = FindWindow(null, "RunDLL"); //获得RunDLL界面句柄 
                //SendMessage_A(rulGandle, WM_KEYDOWN, VK_RETURN, 0);
            }catch(Exception e)
            {
                CTraceLog.TraceLog("关闭RUN DLL异常=" + e.ToString());
            }
        }
        private static IntPtr MAKEWPARAM(int m_nPreSetHandle, object cBN_SELCHANGE)
        {
            throw new NotImplementedException();
        }

        private static void SendMessage(IntPtr intPtr1, int m_nRatefactorOrAveragebrtrate, IntPtr intPtr2, string v)
        {
            throw new NotImplementedException();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //设置日志文件名称 日志位于当前exe同级目录下面的log 
          
            CTraceLog.SetTraceLogFilePath("SetH265");


            CTraceLog.TraceLog("配置H265界面开始");

            //开始调用具体设置方法
            CModifyX265.SetH265Form();

            CModifyX265.CloseRunDll();
            CTraceLog.TraceLog("配置H265界面结束\r\n");

        }
    }
}
 

总结一下吧

获取具体控件句柄的值

界面的句柄 = FindWindow(null, "需要查找界面的名称“); //获得H265界面句柄

具体控件的句柄=GetDlgItem(界面的句柄, 具体控件的ID); //具体控件ID可以根据SPY++获取到

修改COMBOX的值

                    SendMessage_A(COMBOX具体控件的句柄, CB_SHOWDROPDOWN, 1, 0); //展开ComboBox列表框
                    SendMessage_A(COMBOX具体控件的句柄, CB_SETCURSEL, nData, 0); //指向需要写入的下标
                    SendMessage_A(COMBOX具体控件的句柄, WM_SETFOCUS, 0, 0); //设置焦点
                    SendMessage_A(COMBOX具体控件的句柄, WM_KEYDOWN, VK_RETURN, 0); //模拟鼠标按下 
                    SendMessage_A(COMBOX具体控件的句柄, WM_KEYUP, VK_RETURN, 0);//模拟鼠标放开                                                          SendMessage(COMBOX具体控件的句柄, WM_GETTEXT, (IntPtr)buffer.Capacity, buffer);//获取combox的值

修改edit里面的值

        SendMessageString(EDIT具体控件的句柄, WM_SETTEXT, (IntPtr)nData, nData.ToString());
获取EDIT里面的值

SendMessage(EDIT具体控件的句柄, WM_GETTEXT, (IntPtr)buffer.Capacity, buffer);

设置CHECK选中或者未选中 先根据BM_GETCHECK获取选中状态 然后在执行下面的2句 即可设置是否选中

通过SendMessage_A(CHECKBOX的句柄, BM_GETCHECK, 0, 0) != BST_CHECKED

如果为BST_CHECKED那么是选中执行下面2句为未选中状态

如果不为BST_CHECKED 那么是不选中执行下面2句为选中状态

                            SendMessage_A(CHECKBOX具体控件的句柄, WM_KEYDOWN, VK_SPACE, 0); //模拟鼠标按下 
                            SendMessage_A(CHECKBOX具体控件的句柄, WM_KEYUP, VK_SPACE, 0);//模拟鼠标放开

一个界面中打开另一个子界面 修改子界面上面控件的值 步骤

界面的句柄 = FindWindow(null, "需要查找界面的名称“); 

子界面的句柄 = ::GetWindow(界面的句柄 , GW_CHILD);

具体控件的句柄=GetDlgItem(子界面的句柄, 具体控件的ID); //具体控件ID可以根据SPY++获取到

MFC步骤和C#步骤类似 应该说更简单一点 因为C#需要导入user32.dll而MFC不需要

其他说明点:

对于自己来说中间遇到过用SPY++获取不到控件值的问题,过程是点击SPY++的按钮拖动到界面上 比如一个panle里面放了一个TEXT 只能获取到panle的值 而用SPY++获取不到TEXT的ID,这种情况用SPY++和SPYLITE两种工具每个都试下,我自己测试过程后,还没有说这两种工具都试不出来的情况

如果有朋友不懂 或者指正  在下面留言 我看到会回复的

你可能感兴趣的:(C#,C++,MFC,修改ComBox下标)