c #, WinApi: невозможно выбрать элемент в выпадающем списке или добавить элемент в список, используя WM_SETTEXT и другие сообщения - PullRequest
0 голосов
/ 08 декабря 2018

некоторая предыстория: есть приложение с небольшим списком:

Image of the Listbox

Элементы добавляются через кнопку «+»

Image of the added row

На этом этапе вы можете напрямую изменить текст в элементе или нажать кнопку «*», чтобы появилось и отредактировало другое диалоговое окно:

Image of the second dialog

Вот как Listview (основной элемент управления SysListView и первые 3 поля в ListView подчеркнуты на изображении, хотят отметить, что первый файл, поданный в этом ListViewэто Combobox ), который выглядит в Spy ++:

Image of the Listbox in Spy++

Так выглядит второй диалог (Изображение 2) (управление Combobox иего окно «Правка» подчеркнуто на изображении), глядя в Spy ++:

Image of the Dialog in Spy++

Что я могу сделать: Найдите все необходимые ручки, нажмите обаКнопки «+» и «*», заполните оба текстовых поля в диалоговом окне (3).

Проблема в том, что я не могу выбрать элемент в Комбоксе oв диалоговом окне (3) или добавьте элемент непосредственно в ListView без использования диалогового окна (3).

Для выбора элемента в комбинированном ящике я использовал WM_SETTEXT с маршалингом lpsz ... и с помощью этого метода текст задается в выпадающем списке, но после нажатия кнопки «ОК» в диалоговом окне этот текст не сохраняется и не добавляется в ListView.Я также использовал SETCURSEL и снова - текст, заданный в выпадающем списке без сохранения и добавления в lsitbox.Хотя я решил проблему, подражая человеческому поведению - публикуя событие KEYDOWN / KEYUP , оно меня не удовлетворяет, потому что я уверен, что есть более продвинутый метод, а также мне любопытно, почему этот метод работает, а другие терпят неудачу.

Для добавления элемента непосредственно в ListView я пробовал то же самое, но на этот раз безуспешно.

ТАК, резюмируя мои вопросы:

1) Как можно добавить элемент в представление списка.

* 2) Почему SETTEXT / SETCURSEL не работают в Combobox, хотя текст добавляется. *

Например:

StringBuilder sb = new StringBuilder("Test");
SendMessage(Combobox_Handle, WM_SETTEXT, IntPtr.Zero, sb);

Это добавит «тест» в комбинированный список, но после нажатия OK надиалог текст не сохранит.Но эмуляция поведения человека и использование WM_KEYUP работает.

* 3) Не затрагивал эту проблему, но почему WM_SETTEXT не работает с замаскированными текстовыми полями, мне пришлось циклически проходить по моей строке ипоместите каждый символ с WM_CHAR . *

Например:

Текстовое поле выглядит так: «- -», если я использую

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]);
}

Это отлично работает, но я хочу спросить, хорош ли этот метод, иесли есть какие-либо другие способы сделать это.

Невозможно предоставить какой-либо код, потому что проект находится в работе.Я работаю над этим около 2 недель и безуспешно искал дерьмо в интернете.

1 Ответ

0 голосов
/ 09 декабря 2018

Используйте 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
  • Выделить память для LVITEM с помощью VirtualAllocEx
  • Использовать WriteProcessMemory для записи LVITEM
  • Отправка LVM_INSERTITEM сообщения

Пример:

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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...