C# c、 WinApi:无法使用WM_SETTEXT和其他消息选择组合框中的项或列表视图中的附加项

C# c、 WinApi:无法使用WM_SETTEXT和其他消息选择组合框中的项或列表视图中的附加项,c#,winapi,C#,Winapi,一些背景故事:有一个小列表框的应用程序: 通过+按钮添加项目 此时,您可以直接更改项目中的文本,或按*按钮以显示另一个对话框并在其中进行编辑: 这是Listview主SysListView控件和Listview中的前3个字段在图像上加下划线的方式,希望确定此Listview中的第一个字段是Spy++中的组合框: 这是第二个对话框Image 2 Combobox控件及其“Edit”窗口在Spy++中的图像上加下划线的方式: 我能做的是:找到所有需要的句柄,单击+和*按钮,在对话框3中填充两个文本框

一些背景故事:有一个小列表框的应用程序:

通过+按钮添加项目

此时,您可以直接更改项目中的文本,或按*按钮以显示另一个对话框并在其中进行编辑:

这是Listview主SysListView控件和Listview中的前3个字段在图像上加下划线的方式,希望确定此Listview中的第一个字段是Spy++中的组合框:

这是第二个对话框Image 2 Combobox控件及其“Edit”窗口在Spy++中的图像上加下划线的方式:

我能做的是:找到所有需要的句柄,单击+和*按钮,在对话框3中填充两个文本框

问题是:我不能在对话框3的组合框中选择一个项目,也不能在不使用对话框3的情况下将项目直接添加到ListView

为了在组合框中选择项,我使用WM_SETTEXT和封送lpsz…并使用此方法在组合框中设置文本,但在对话框中单击“确定”后,不会保存此文本并将其添加到ListView。我还使用了SETCURSEL,并再次使用-文本在组合框中设置,而不保存并添加到lsitbox。 虽然我通过模拟人类行为解决了这个问题——发布KEYDOWN/KEYUP事件,但我并不满意,因为我确信有一种更高级的方法,而且我有点好奇为什么这种方法有效,而其他方法却失败了

为了将项目直接添加到ListView中,我尝试了相同的方法,但这次没有成功

因此,总结我的问题:

1如何将项目添加到Listview

*2为什么SETTEXT/SETCURSEL在添加文本时不使用Combobox*

例如:

StringBuilder sb = new StringBuilder("Test");
SendMessage(Combobox_Handle, WM_SETTEXT, IntPtr.Zero, sb);
这会将测试添加到组合框中,但单击对话框上的“确定”后,文本将不会保存。但是,模仿人类行为和使用WM_-KEYUP是可行的

*3没有解决这个问题,但是为什么WM_SETTEXT不能在屏蔽文本框上工作,我必须循环我的字符串并用WM_CHAR放置每个字符*

例如:

StringBuilder sb = new StringBuilder("Test");
SendMessage(Combobox_Handle, WM_SETTEXT, IntPtr.Zero, sb);
文本框看起来像:--,如果我使用

SendMessage(Combobox_Handle, WM_SETTEXT, IntPtr.Zero, "000-000-000000") 
文本将被设置,但单击文本框后它将消失,因此我必须这样做:

string s = "005006012567";
foreach (char c in s)
{
    PostMessage(TextBox_Handle, WM_CHAR, wParam_Dictionary[c],lParam_Dictionary[c]);
}
这个方法非常有效,但我想问一下这个方法是否有用,是否还有其他方法可以做到这一点

无法提供任何代码,因为项目正在工作。我在这方面工作了大约两周,从互联网上搜索垃圾却没有成功。

使用CB_ADDSTRING将项目添加到组合框中,如下所示:

IntPtr hwnd_external = FindWindow(IntPtr.Zero, "some window");
IntPtr hcombo = FindWindowEx(hwnd_external, IntPtr.Zero, "ComboBox", IntPtr.Zero);
int sel = SendMessage(hcombo, CB_ADDSTRING, IntPtr.Zero, "Test1");
SendMessage(hcombo, CB_SETCURSEL, sel, IntPtr.Zero);
假设它是一个标准的组合框控件,这应该可以与另一个进程一起使用,但它可能无法与某些控件一起使用,例如某些所有者绘制控件

IntPtr hlist = FindWindowEx(hwnd_external, IntPtr.Zero, "SysListView32", IntPtr.Zero);
向ListView控件添加项比较困难,因为您需要在另一个进程中访问内存

从窗口获取进程句柄 调用OpenProcess 使用VirtualAllocEx为LVITEM分配内存 使用WriteProcessMemory写入LVITEM 发送LVM_插入项消息 例如:

DWORD process_id;
HWND hlist = FindWindowEx(hwnd_external, 0, L"SysListView32", 0);
GetWindowThreadProcessId(hlist, &process_id);

HANDLE hprocess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ |
    PROCESS_VM_WRITE, FALSE, process_id);
if(!hprocess)
    return 0;

wchar_t text[] = L"new item";
void* pbuf = VirtualAllocEx(hprocess, NULL, sizeof(text), MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hprocess, pbuf, text, sizeof(text), NULL);

void* pitem = VirtualAllocEx(hprocess, NULL, sizeof(LVITEM), MEM_COMMIT, PAGE_READWRITE);
LVITEM lvItem = { 0 };
lvItem.mask = LVIF_TEXT | LVIF_STATE;
lvItem.cchTextMax = wcslen(text);
lvItem.pszText = (wchar_t*)pbuf;
WriteProcessMemory(hprocess, pitem, &lvItem, sizeof(LVITEM), NULL);

SendMessage(hlist, LVM_INSERTITEM, 0, (LPARAM)(const LV_ITEM*)(pitem));

VirtualFreeEx(hprocess, pitem, 0, MEM_RELEASE);
VirtualFreeEx(hprocess, pbuf, 0, MEM_RELEASE);
CloseHandle(hprocess);

您需要提供代码。A please.ListBox和A是两个不同的东西。我不完全理解这个问题,但看起来你需要与另一个程序进行交互。ListView需要LVM_INSERTITEM来插入项,托管代码可能会让人头疼。@David Heffernan,我明天会提供它。@Barmak Shemirani,我的坏ofc这是一个ListView。我将尝试LVM_INSERTITEM。我将阅读有关UI自动化的内容,谢谢。@David Heffernan在我文章末尾的“问题”区域添加了一些代码。非常感谢@Barmak Shemirani,我明天会尝试!顺便问一下,你对我用WM_键在组合框中选择一个项目的方法有什么看法?坏吗?