发送消息,修改其他程序的下拉框的选择

发送消息,修改其他程序的下拉框的选择。

先说结论

public void SelectItem(int index)

{

COMBOBOXINFO cbi = new COMBOBOXINFO();

cbi.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(cbi);

if (User32.GetComboBoxInfo(Wnd, ref cbi))

{

User32.SendMessage(Wnd, ComboBoxMsg.CB_SETCURSEL, index, 0);

int cbId = User32.GetDlgCtrlID(cbi.hwndList);

int wParam = WordHelper.GetWord(ComboBoxMsg.CBN_SELCHANGE, cbId);

User32.SendMessage(Wnd, Constant_WM.WM_COMMAND, wParam, (int)cbi.hwndList);

}

}

User32是一个封装了User32.dll里面的API函数的静态类,嘛,学习这方面的人都会有吧。

摸索的过程费了点时间,希望“后来人”搜索的时候可以找到这里,记录一下过程。

我以前就简单的学过一点MFC编程,现在用的是c#。估计对于原本知道的人来说这些(像是GetComboBoxInfo)都是理所当然的,没必要特别写出来的吧。

1. 先是百度一下,很快找到信息

Windows消息之ComboBox

发假消息让下拉列表菜单选中, 但是只有第一句的时候不能激发select change,很多业务逻辑耦合在这个上面

所以还要人为的做出select change的消息

PostMessage(comboBoxHWND, CB_SETCURSEL, selectItem, 0);

PostMessage(targetHWND,WM_COMMAND, MAKEWPARAM(GetWindowLong(comboBoxHWND, GWL_ID), CBN_SELCHANGE), (LPARAM)comboBoxHWND);

c#通过SendMessage发送消息,改变其他程序的下拉框控件(ComboBox)的值

IntPtr mwh = (IntPtr)Convert.ToInt32(handle);                         //ComboBox的句柄

int result = SendMessage(mwh, 0x014D, -1, selectStr);            //改变ComboBox的值,selectStr为预期的下拉框选项

int mwh_p = GetWindowLong(mwh, -8);                                   //获取ComboBox所属窗口的句柄

IntPtr mwh2 = (IntPtr)Convert.ToInt32(mwh_p);                      //转换ComboBox所属窗口的句柄

string cbn_selchange;

int cb_id = GetWindowLong(mwh, -12);                                    //获取ComboBox的控件ID

cbn_selchange = "0001" + string.Format("{0:X4}", cb_id);

IntPtr s1 = (IntPtr)Convert.ToInt32(Tools.ToD(cbn_selchange, 16));

SendMessage(mwh2, 0x0111, s1, mwh);                    //给ComboBox所属窗口发送WM_COMMAND命令,第3个参数wParam是(CBN_SELCHANGE(高位) + 控件ID(低位))

SendMessage(mwh2, 0x0111, s1, mwh);可以参考SPY++捕捉的消息日志

GetWindowLong的参数可以参考:

http://blog.csdn.net/hnhyhongmingjiang/archive/2008/03/06/2154410.aspx

SendMessage的参数可以参考:

http://topic.csdn.net/t/20050713/18/4142641.html

我按照自己的程序进行了一下修改

ntPtr mwh = Wnd;

User32.SendMessage(mwh, ComboBoxMsg.CB_SETCURSEL, index, 0);

int mwh_p = User32.GetWindowLong(mwh, GetWindowLongFlag.GWL_HWNDPARENT);

IntPtr mwh2 = (IntPtr)Convert.ToInt32(mwh_p);

string cbn_selchange;

nt cb_id = User32.GetWindowLong(mwh, GetWindowLongFlag.GWL_ID);

int s1 = WordHelper.GetWord(ComboBoxMsg.CBN_SELCHANGE, cb_id);

User32.SendMessage(mwh2, Constant_WM.WM_COMMAND, s1, (int)mwh);

结果失败,最后一个消息没有效果。

第一个CB_SETCURSEL消息只是修改了下拉框的显示,并没有触发SelectChange事件,程序没有实质上的变化。

第二个消息就是要触发事件。

2. 用Spy++查看消息,发现

<00377> 000C0BFA S WM_COMMAND wNotifyCode:0001 wID:1000 hwndCtl:001B08E4

发现修改成

User32.SendMessage(mwh, Constant_WM.WM_COMMAND, 1000, 110734);

一种110734是001B08E4的十进制数

有效果!

说明前面说的SendMessage第一个参数错了,应该是ComboBox本身的句柄而不是父窗体,在之前查找ToolBar发送消息点击按钮时也碰到过。

3. 然后在Spy++中001B08E4是一个ComboLBox的类,其父是桌面。

寻找ComboLBox的信息,得到:

ComboLBox :The class for the list box contained in a combo box.

In Windows(, before a new type of window is created, it must register a special class name to the system. Every window has its own class name, which could be used to tell the window‘s type. In the case of combo box, its edit box‘s class name is "Edit" and its list box‘s class name is "ComboLBox". Please note that this class name has nothing to do with MFC classes. It is used by the operating system to identify the window types rather than a programming implementation.

如何从ComboBox的到ComboLBox的句柄就卡住了,查询ComboLBox得不到有用的信息,不过有个地方提到它的句柄和ListBox的句柄一样。

用中文“获取Combo里面的Listbox的句柄”不行,用“获取ComboBox的Listbox的句柄”也不行。

4. 用“get listbox in combobox”找到了!(google连不上,翻墙不知道现在方便不,就用必应搜索了)

Win32: How do I get the listbox for a combobox

I‘m writing some code and I need to get the window handle of the listbox associated with a combo box. When looking in spy++, it looks like the parent of the listbox is the desktop, not the combo box. How can I programmatically find the listbox window handle?

Answer

Send CB_GETCOMBOBOXINFO to the combo box, and it fills in a COMBOBOXINFO structure, which contains the window handles to the edit control and the list box control.

接下来搜索CB_GETCOMBOBOXINFO 和COMBOBOXINFO,找到了发送消息和调用User32函数GetComboBoxInfo两种方法,发送消息没具体研究,我使用的是GetComboBoxInfo。

[DllImport("user32.dll")]

public static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);

[StructLayout(LayoutKind.Sequential)]

public struct COMBOBOXINFO {

public Int32 cbSize;

public RECT rcItem;

public RECT rcButton;

public ComboBoxButtonState buttonState;

public IntPtr hwndCombo;

public IntPtr hwndEdit;

public IntPtr hwndList;

}

public enum ComboBoxButtonState {

STATE_SYSTEM_NONE = 0,

STATE_SYSTEM_INVISIBLE = 0x00008000,

STATE_SYSTEM_PRESSED = 0x00000008

}

COMBOBOXINFO cbi = new COMBOBOXINFO();

cbi.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(cbi);

if(GetComboBoxInfo(comboBox1.Handle, ref cbi)) {

if(cbi.hwndEdit == IntPtr.Zero) {

throw new Exception("ComboBox must have the DropDown style!");

}

}

上面是从pinvoke上找的,pinvoke真是方便,好想有个脱机版本!(工作的电脑无法上网!)

最终我测试成功的代码就是开头的代码。

时间: 2024-10-11 04:06:29

发送消息,修改其他程序的下拉框的选择的相关文章

JS年月日三级联动下拉框日期选择代码

原博客网址: http://www.cnblogs.com/gdcgy/p/5467742.html 由于工作中涉及到生日编辑资料编辑,年月日用上面网址案例:bug提示: 编辑生日栏的[年]或者[月],之前保存的具体的[日]就不显示啦,产品说不管编辑哪个数据,其他数据不变: 然后自己改了一下代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xh

jquery 下拉框左右选择

html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>下拉框左右选择</title> <link rel="stylesheet" href="css/test.css" /> <script type="text/javascript" src="

robotframework+Selenium2Library 特殊下拉框的选择

4 特殊下拉框的选择   对于这种下拉框,一拉啥没有. 代码中也没有任何可操作的select option标签等.如何是好. 既然下拉框,那就总可以选择.我们输入一个名“王XX”,下拉框自动出现这样. 但是怎么选择上?代码实在没有相应的元素来操作啊. 不过,我们操作键盘,向下键,enter键,即可成功选择. 那问题就变成如何在robotframework+selenium2library中操作键盘.api给的很简单,press key  xxxx. 查了向下键的ascii为40,enter键的为

Robotframework下拉框的选择

Robotframework下拉框的选择用到的关键字为:1.Select form List其意思是从列表中选择需要的值.例如:从该Options中选择一个时间其带的参数为:Arguments:[ locator | items]locator为该下拉框的定位,items为选择时间的值2.Select from List By Index通过索引值来选择下来框中对应的值,从0开始索引其带的参数为:Arguments:[ locator | *indexes ]locator为该下拉框的定位,in

android-theme中修改actionmode中more下拉框的背景颜色

今天在做图库修改是,需要修改图库的actionbar某个按钮弹出来的下拉框的背景颜色,在网上找了个方法尝试下,没有打到自己的要求,不过阴差阳错的却修改了more下拉框的背景,再次记录下,也许以后能用的到. 代码 <style name="Theme.FunuiGallery" parent="android:Theme.Funui"> <item name="listPreferredItemHeightSmall">48

微信小程序select下拉框实现

小程序中是没有h5中的下拉 标签的 所以要实现下拉功能就必须自己动手写拉,这里为了更清楚的显示小程序层级 就把源码直接复制过来了 <view class='list-msg'> <view class='list-msg1'> <text>商品金额</text> <text>¥99.00</text> </view> <!--下拉框 --> <view class='list-msg2' bindtap=

Java Swing应用程序 JComboBox下拉框联动查询

在web项目中,通过下拉框.JQuery和ajax可以实现下拉框联动查询. 譬如说,当你查询某个地方时,页面上有:省份:<下拉框省份> 市区:<下拉框市区> 县乡:<下拉框县乡> 街道:<街道下拉框> 查询 譬如说,你选择了省:江苏省,那么在市区中只会显示江苏省的市区 譬如:(网上的图) 具体详细实现可以参考,写得挺好的:http://blog.csdn.net/sinat_24491773/article/details/50810471 那么在swing

下拉框&quot;--请选择--&quot; 浏览器渲染不同造成页面初始化不一致

问题: 页面下拉框初始化时,展示"--请选择--" : 在Google.Firefox浏览器渲染正常,但在IE(低版本)浏览器下不展示. 修复: (1) 修改对应的*.js文件: 如: please_select: "--请选择--", //产品运输方式判断 var flag = false; $("#productDictionary option").each(function() { if($(this).val()===data.data

bootstrap select 下拉框没选择

情况:根据取得的值去选定select下拉框的选项.但不知为何每次根据select的id传递值过去了,也能取得对应的值,但是页面上的select依然是下拉框第一个选项,但点击下拉框时,会在对应的值有特殊css(选中标志),即改变了值,却没改变现实的值.原因:设置select的选中的option,并没有修改对应的span的值跟title.<span class="select2-selection__rendered" id="select2-字段ID-container&