|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#16
|
|||
|
|||
Я вернулась чуть раньше =)
И пример притащила... Всё оказывается несколько сложнее, чем я изначально полагала! Так вот просто забрать содержимое ListView из чужого окна путем посылки ему сообщения LVM_GETITEMTEXT не получится. Нужно свершать дополнительные манипуляции по выделению памяти под текстовый буфер в чужом процессе. Сразу говорю, что я воспользовалась этим примером (и авторство себе не присваиваю). Но я заточила тот пример под наши конкретные нужды и написала процедуру, считывающую всё содержимое ListView в объект StringGrid, который передается процедуре как параметр по ссылке. Это может быть как реально существующий на форме StringGrid, так и динамически создаваемый (runtime) с помощью конструктора Create. Просто, думаю, со StringGrid очень удобно работать в дальнейшем, анализируя содержимое. Вот как выглядит процедура: Код:
procedure TForm1.GetListViewData(LVHandle: HWND; ColumnCount: Integer; var DataGrid: TStringGrid); var hProcess: THandle; dwProcessID: DWORD; dwBytesWriten: DWORD; nItemCount: Integer; i, j, nTextLength: Integer; plviRemoteLVItem: PLVItem; lviRemoteLVItem: LV_ITEM; pszText: PChar; svText: ShortString; begin if LVHandle = 0 then Exit; dwProcessID := 0; nItemCount := ListView_GetItemCount(LVHandle); GetWindowThreadProcessId(LVHandle, @dwProcessID); if dwProcessID = 0 then Exit; hProcess := OpenProcess(PROCESS_ALL_ACCESS, True, dwProcessID); if hProcess = 0 then Exit; pszText := VirtualAllocEx(hProcess, nil, 255, MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE); if GetLastError <> 0 then Exit; plviRemoteLVItem := VirtualAllocEx(hProcess, nil, SizeOf(LV_ITEM), MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE); if GetLastError <> 0 then Exit; { единицу прибавляю в том предположении, что есть фиксированные строка и столбец } DataGrid.RowCount := nItemCount + 1; DataGrid.ColCount := ColumnCount + 1; ZeroMemory(@lviRemoteLVItem, SizeOf(LV_ITEM)); lviRemoteLVItem.mask := LVIF_TEXT; lviRemoteLVItem.pszText := pszText; lviRemoteLVItem.cchTextMax := 255; for i := 0 to nItemCount - 1 do begin lviRemoteLVItem.iSubItem := 0; if not WriteProcessMemory(hProcess, plviRemoteLVItem, @lviRemoteLVItem, SizeOf(LV_ITEM), dwBytesWriten) then Exit; nTextLength := SendMessage(LVHandle, LVM_GETITEMTEXT, i, Integer(plviRemoteLVItem)); ZeroMemory(@svText, 255); ReadProcessMemory(hProcess, lviRemoteLVItem.pszText, @svText[1], nTextLength, dwBytesWriten); DataGrid.Cells[1, i + 1] := StrPas(PChar(@svText[1])); for j := 1 to ColumnCount - 1 do begin lviRemoteLVItem.iSubItem := j; if not WriteProcessMemory(hProcess, plviRemoteLVItem, @lviRemoteLVItem, SizeOf(LV_ITEM), dwBytesWriten) then Exit; nTextLength := SendMessage(LVHandle, LVM_GETITEMTEXT, i, Integer(plviRemoteLVItem)); ZeroMemory(@svText, 255); ReadProcessMemory(hProcess, lviRemoteLVItem.pszText, @svText[1], nTextLength, dwBytesWriten); DataGrid.Cells[j + 1, i + 1] := StrPas(PChar(@svText[1])); end; end; VirtualFreeEx(hProcess, pszText, 0, MEM_RELEASE); VirtualFreeEx(hProcess, plviRemoteLVItem, 0, MEM_RELEASE); CloseHandle(hProcess); end;
Код:
procedure TForm1.Button1Click(Sender: TObject); var StrGrid: TStringGrid; begin StrGrid := TStringGrid.Create(Self); try GetListViewData(ListViewHandle, 4, StrGrid); { теперь таблица StrGrid содержит всё, что было в ListView. Тут можно выполнять какие-то манипуляции с данными, обращаясь к ним, например, так: StrGrid.Cells[3, 5] } // Анализ и обработка... finally StrGrid.Free; end; end; |
#17
|
|||
|
|||
К сожалению ни чего не получилось(
Через Trace into посмотрел программа еще вот здесь: Код:
... hProcess := OpenProcess(PROCESS_ALL_ACCESS, True, dwProcessID); if hProcess = 0 then Exit; pszText := VirtualAllocEx(hProcess, nil, 255, MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE); if GetLastError <> 0 then Exit; ... В чем дело господа знатоки? |
#18
|
|||
|
|||
Ну что-то аж не знаю! Проверяю на всех окнах класса SysListView32, какие только есть у Windows, и всё работает... Уже получаю и список процессов в Диспетчере задач, и список файлов в Explorer'е, и всё, что есть в консоли mmc, — всё вытаскивается. Не понятно, почему у вас не работает.
Вы тоже проверьте при возможности на других объектах ListView, хотя бы из тех, что я перечислила... И попробуйте еще для ясности убрать из процедуры GetListViewData вот эти строчки: Код:
DataGrid.RowCount := nItemCount + 1; DataGrid.ColCount := ColumnCount + 1; P.S. Да, и еще. Раз уж вы делаете трассировку, посмотрите заодно, как программа проходится по тем циклам for, что в процедуре GetListViewData. Уж не вылетает ли она вот на этих Exit: Код:
if not WriteProcessMemory(hProcess, plviRemoteLVItem, @lviRemoteLVItem, SizeOf(LV_ITEM), dwBytesWriten) then Exit; Последний раз редактировалось Nyctos Kasignete, 24.04.2009 в 21:51. |
#19
|
|||
|
|||
Странно но с диспетчером задач действительно работает)
Но с моей прогой - нет. в циклах ни где не выкидывает - проходит до конца. |
#20
|
|||
|
|||
Эх. =(
Возможно, для полноты картины стоит проверить еще, что возвращает функция ReadProcessMemory. Если чтение памяти завершается неудачей, функция возвращает False. То есть, можно попробовать в циклах заменить строчку Код:
ReadProcessMemory(hProcess, lviRemoteLVItem.pszText, @svText[1], nTextLength, dwBytesWriten); Код:
if not ReadProcessMemory(hProcess, lviRemoteLVItem.pszText, @svText[1], nTextLength, dwBytesWriten) then Exit; И ведь мне проверять-то не на чем! O_o |
#21
|
|||
|
|||
Если у вас есть возможность 5 метров скачать вот здесь лежит та прога:
http://www.alpari.ru/files/mt4setup.exe в меню Вид нажать на терминал и вот как раз из появившегося окна мне надо вытянуть данные. Ну все равно большое спасибо, вы мне очень помогли. |
#22
|
|||
|
|||
О! Получилось, только не до конца...
Почему-то в стринггрид не записываются фиксированные ячейки(там только перавя строка) а еще внизу стринггрида есть закрашенная строка(внизу же не может быть фиксированной строки) вот так выглядит: http://www.delphisources.ru/forum/at...1&d=1240722716 ее тоже не выводит. И при трассировке иногда вообще ни чего не выводит, появляется ошибка, а иногда в ст выводит но при навелении на переменную psztext выглядит пустой. Почему? строки DataGrid.RowCount := nItemCount + 1; DataGrid.ColCount := ColumnCount + 1; убирал - не помогло. |
#23
|
||||
|
||||
Цитата:
Цитата:
Цитата:
Цитата:
|
#24
|
||||
|
||||
Цитата:
Жизнь такова какова она есть и больше никакова. Помогаю за спасибо. |
#25
|
|||
|
|||
Цитата:
|
#26
|
|||
|
|||
Ладно, закрашенная строка внизу мне пока не нужна.
Цитата:
Теперь коли скачали мт4 тогда не подскажете ли: как мне передать в эту программу нажатие клавишы F9 и в появившемся окне в некоторых окнах что-то выбрать из списка, а что-то ввести, и нажать чекбокс внизу? И как все это сделать чтоб при передачи этих сообщений в программу она не разворачивалась? |
#27
|
|||
|
|||
Подождите, а что делает F9? Нажимаю-нажимаю, и ничего не происходит...
Тааак. Раскопала в справке к программе, что F9 вызывает команду Новый ордер. Соответствующая кнопка у меня неактивна, поэтому ничего не происходит. Короче, разбираться с этой программой не хочу. Скажу в общем. Нажатие клавиши F9 можно послать окну, если известен его handle. Искать дескриптор вы умеете. Отослать F9 можно так: Код:
PostMessage(wndHandle, WM_KEYDOWN, VK_F9, 0) Ввести текст в какой-нибудь Edit: Код:
SendMessage(editHandle, WM_SETTEXT, 0, Integer(PChar('новый текст здесь'))); Нажать на CheckBox: Код:
PostMessage(CheckBoxHandle, BM_CLICK, 0, 0); Последний раз редактировалось Nyctos Kasignete, 26.04.2009 в 16:40. |
#28
|
|||
|
|||
а как проверить чему равен checked у checkbox?
и скажите где и как вы всю эту информацию ищите, чтоб я вас больше не доставал) Такой вот еще вопрос: можно же как-то имея адрес ехе файла узнать запущен ли он и если запущен получить дескриптор процесса, нити, и.. что там еще надо для вывода в мемо дескрипторов всех дочерних окон? А еще как выбрать в комбобокс один из элементов, и как прочесть тексто того который сейчас показан? и как узнать чему равен enabled и visible разных элементов, в частности лабел и едит? И эмитирование нажатия F9 происходит только если терминал развернут, можно ли как нибудь это обойти? Может ему сначала следует пеердать фокус без разворачивания? И можно нажать на кнопку новый ордер, она находится возле меню(у вас затемненная), как на нее нажать? Я так понимаю она расположена на каком-то меню быстрых кнопок которе по моему имеет класс ToolbarWindows32. Последний раз редактировалось одинадцатый, 26.04.2009 в 20:26. |
#29
|
||||||
|
||||||
Ааааааа!! Сколько вопросов! У меня сейчас взорвется голова!
Но поехали потихоньку... Цитата:
Код:
case SendMessage(CheckBoxHandle, BM_GETCHECK, 0, 0) of BST_CHECKED: ShowMessage('Флажок стоит'); BST_UNCHECKED: ShowMessage('Флажок снят'); else ShowMessage('Флажок затенен'); end; Цитата:
Цитата:
Цитата:
Код:
var CurTxt: PChar; CurSel: Integer; ElementToSelect: string; begin ElementToSelect := 'qwerty'; // Впишите здесь текст элемента, который должен быть выбран GetMem(CurTxt, 255); try CurSel := SendMessage(ComboBoxHandle, CB_GETCURSEL, 0, 0); // индекс текущего элемента SendMessage(ComboBoxHandle, CB_GETLBTEXT, CurSel, Integer(CurTxt)); ShowMessage('Текущий элемент: ' + StrPas(CurTxt)); SendMessage(ComboBoxHandle, CB_SELECTSTRING, -1, Integer(@ElementToSelect[1])); finally FreeMem(CurTxt, 255); end; end; Цитата:
Про остальное подумаю тоже потом. Устала =) И еще не очень поняла, про развернутость окна... Это что значит — если окно развернуто на весь экран, то сообщение WM_KEYDOWN принимается, а если не развернуто, то нет? Цитата:
Код:
if GetWindow(HandleOfToolbar, GW_CHILD) <> 0 then ShowMessage('Есть дети') else ShowMessage('Нет детей'); Если "дети" есть, то добраться до их дескрипторов можно с помощью функции EnumChildWindows. Хотя, вполне возможно, в Win32 API есть и специальные функции для работы с такими Toolbar. Всё, не могу больше тыкать по кнопкам. Спокойной ночи. Последний раз редактировалось Nyctos Kasignete, 26.04.2009 в 22:52. |
#30
|
|||
|
|||
Цитата:
Такая еще проблема: когда я жму кнопку методом PostMessage(handle, BM_CLICK, 0, 0); программа выдает ошибку не верные параметры для сделки, а если жму на эту кнопку явно, мышкой - все нормально, почему так? Может стоит сделать не BM_CLICK, а что то типа BM_MOUSEDOWN а потом BM_MOUSEUP? А можно как-нибудь выбрать элимент из комбобокс не по тексту, а по индексу? А главная проблемма в том что не смотря на имеющиеся поля(открытые позиции) в таблице на вкладке Торговля, на окне Терминал, в мой стринггрид эта информация все равно не выводиться.(((((((((((((( Все остальное не имеет значения если этих данных нет. Умоляю помогите. Чтоб у вас появилась эта вкладка, и загорелась кнопка Новый ордер вам надо зарегестрировать демо счет. ПРЕДУПРЕЖДАЮ: ВАС ЭТО НИ К ЧЕМУ НЕ ОБЯЗЫВАЕТ! Регистрируется так: меню Файл->Открыть счет, там от фонаря вводите данные и жмете везде далее. Чтоб в стринггриде на вкладке торговля появились данные надо открыть позиции(ОПЯТЬ ЖЕ ПРЕДУПРЕЖДАЮ - ВИРТУАЛЬНО, вы ни каких денег ни кому должны не будете) Открываются так: F9 или новый ордер, и там сразу нажать на Buy или Sell. Все, данные появились, и они почему то не выводятся. Может это от того что эта вкладка не видна во время запуска программы и записывается в память куда то в другое место? А можно с вами как-нибудь в другом месте связаться? Сильно доставать не буду) Мое мыло: D-work@list.ru. Последний раз редактировалось одинадцатый, 27.04.2009 в 19:27. |