Узнать Handle окна по имени файла |
Прежде чем задать вопрос, смотрите FAQ.
Рекомендуем загрузить DRKB.
Узнать Handle окна по имени файла |
Unconnected |
29.05.2010 17:34
Сообщение
#1
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Привет всем.
Мне нужно узнать хэндл окна. Допустим, запускаю я cmd через ShellExecute, и нужно мне получить её хэндл. Через FindWindow нельзя, т.к. заголовок cmd может быть разный - у некоторых в начале приписывается "Администратор" (видимо, сидят под администратором). Я думаю, можно перебирать все окна и искать по слову cmd в заголовке. Попробовал ф-ю EnumWindows, вот так:
, и нифига, getmodulename не хочет возвращать имя файла по хэндлу. Помогите, а то меня скоро в гугле как ддос-бота забанят)) -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
volvo |
29.05.2010 18:20
Сообщение
#2
|
Гость |
Кто тебе сказал, что имя модуля - это заголовок? Заголовок получается через GetWindowText...
var |
Unconnected |
29.05.2010 23:39
Сообщение
#3
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Спасибо, это работает. Ещё вопрос, как можно сменить раскладку в чужом окне? Дело в том, что если эмулировать нажатия клавиатуры, то в другом окне они будут отображаться в соответствии с тамошней раскладкой, т.е. передаю ord('F') - появляется 'а'. На одном форуме я нашёл такую функцию:
(передаю хэндл нужного окна) , но она была под изменение на русскую раскладку, а мне нужна английская. Там я в SetKeyboardLayout изменил код раскладки на английский и в предпоследней строке вместо RUSSIAN_CHARSET вписал DEFAULT_CHARSET (в модуле windows.pas константы поглядел), только вот не работает. Кажется, там не DEFAULT_CHARSET, но вот по логике вещей ENGLISH_CHARSET тоже нет.. Кое-где пишут, что вообще хук нужен. -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
volvo |
30.05.2010 1:44
Сообщение
#4
|
Гость |
Цитата только вот не работает В чем неработоспособность проявляется? Я вот сделал так:procedure TForm1.Button12Click(Sender: TObject); , запустил Блокнот, поменял в нем раскладку на русскую, а потом нажал эту кнопку... раскладка блокнота тут же поменялась на английскую. Значит, работает? То, что Rouse_ выкладывает, всегда работает... |
Unconnected |
30.05.2010 2:02
Сообщение
#5
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
раскладка блокнота тут же поменялась на английскую. Это с оригинальной функцией function ChangeRemoteWndKeyboardLayoutToRussian(? Если да, то вообще из названия я понял, что она исключительно на русскую меняет раскладку. У меня первый язык русский, я делал так:
, в t - хэндл cmd. Передаётся буква а, русская и маленькая. По умолчанию у меня во вновь открытых приложениях русский язык. Так вот, ни с оригинальной, ни с моей правленной функциями раскладка не поменялась (я под Seven, если что). Сообщение отредактировано: Unconnected - 30.05.2010 2:04 -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
volvo |
30.05.2010 2:39
Сообщение
#6
|
Гость |
А... Ну, так ты бы и говорил, что хочешь работать с той самой консолью, которую искал в первом посте... Отсюда и проблемы. С консолью - только через хук WH_SHELL (консоли - это вообще темные лошадки). Ну, или (если консоль активная, в фокусе ввода, в смысле) - то пошли ей комбинацию клавиш, переключающих раскладку.
Но это будет частное решение, на одной машине, чтоб переключиться Ru -> En понадобится одна посылка, на другой - может понадобиться больше, зависит от порядка и количества доступных раскладок... Да и получить раскладку для чужого консольного окна не так просто, так что отсылать Alt+Shift и проверять, не стала ли она английской - не получится... А если другая комбинация клавиш выбрана для переключения раскладки? Вопросом много, ответов - нет... |
Unconnected |
30.05.2010 9:36
Сообщение
#7
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Ого, ну и заморочки. Я сейчас попробовал работать с ней через буфер обмена, т.е. вставлять туда строку, а в cmd эмулировать Ctrl+V - так нет же, даже вручную ни Ctrl-V, ни Shift-Ins не работают. Спасибо за инфу, почитаю про WH_Shell.
Сообщение отредактировано: Unconnected - 30.05.2010 9:42 -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
volvo |
30.05.2010 10:23
Сообщение
#8
|
Гость |
У тебя будет гораздо больше проблем, чем ты думаешь сейчас, если ты еще и с хуками заморочишься. Начиная с того, что на WinNT хуки не работают с консольными приложениями ( это является небезопасным, вот что говорит MS по этому поводу: http://support.microsoft.com/kb/108232 ).
Теперь - вопрос на засыпку: а зачем тебе что-то печатать в консоли, да еще созданной через ShellExecute? Если тебе просто нужна консоль, скажем, для вывода, то есть AllocConsole + GetStdHandle, и пиши сколько хочешь в STD_OUTPUT_HANDLE... О том, как запустить процесс и перехватить его вывод написано в DRKB. Так зачем консоль понадобилась? Кстати, еще одно: есть более интересный способ получить хендл консоли, чем приведенный тобой: создавать процесс через CreateProcess, а потом делать вот так |
Unconnected |
30.05.2010 21:47
Сообщение
#9
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Цитата Теперь - вопрос на засыпку: а зачем тебе что-то печатать в консоли, да еще созданной через ShellExecute? Если тебе просто нужна консоль, скажем, для вывода, то есть AllocConsole + GetStdHandle, и пиши сколько хочешь в STD_OUTPUT_HANDLE... О том, как запустить процесс и перехватить его вывод написано в DRKB. Так зачем консоль понадобилась? Ну, мне надо исполнить cmd-команду, но как будто от имени пользователя, через bat-файл не вариант. Короче, я отказался от cmd в пользу окошка Выполнить. Делаю так: var t,editt,but:hwnd; Окошко находится, ComboBox в нём - тоже, даже получается записать туда строку, а вот кнопка что-то не хочет. Вообще, FindWindowEx ищет на всех дочерних "компонентах" окнА, чей хэндл был передан, или только на основной форме? Просто на Win7 кнопки на какой-то белой полосе, типа TBevel или TPanel, что-то такое. Можно, конечно, сделать EnumChildWindows, чтобы посмотреть все контролы, но может и так можно? Цитата создавать процесс через CreateProcess, а потом делать вот так Ага, мне говорили про такой способ, но я испугался множества входных параметров этой функции Сообщение отредактировано: Unconnected - 30.05.2010 21:50 -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
volvo |
30.05.2010 23:23
Сообщение
#10
|
Гость |
Эт чего было? Ты что, серьезно вызываешь окно Run именно так, имитируя всю последовательность действий? Я бы так не делал, есть специализированные методы, которые поддерживаются и будут поддерживаться всеми версиями Windows, независимо от того, как изменится интерфейс. Я про Shell...
Да, и еще:
Исходя из вышесказанного, я бы сделал так: var Только разберись, как оно работает, не копируй код в проект без этого, ибо: Читать здесь |
Unconnected |
31.05.2010 16:13
Сообщение
#11
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Разобрался, узнал много нового ) Только вот этот код у меня, в консольном приложении (видимо, вся соль именно в этом), не отрабатывал и выбивал ошибку, мол, не вызвано CoInitialize. Я добавил строчку CoInitialize(nil) в самом начале процедуры и CoUninintialize в конце, работать стало, но всё равно выдавало AV в конце программы, пришлось убрать CoUninitialize (это, наверное, и неправильно, но и мне ошибки не нужны)).
Кстати, там при передаче сообщения Эдиту использовалась SendMessage, а при передаче кнопке - Post. Это типа чтобы текст эдиту присвоился, информация об этом вернулась и только потом нажалась бы кнопка? //проникся блогом, оказалось, я истинный CodeMonkey, прямо по всем признакам Сообщение отредактировано: Unconnected - 31.05.2010 16:14 -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
volvo |
31.05.2010 18:28
Сообщение
#12
|
Гость |
Цитата Я добавил строчку CoInitialize(nil) в самом начале процедуры и CoUninintialize в конце Как ни пытался - не получилось у меня, чтоб AV вылетел. Может ты несколько раз вызываешь эту процедуру? Тогда пара Co/CoUn должна быть в начале/конце программы, а не подпрограммы.Просто убирать CoUninitialize нельзя: Цитата To close the COM library gracefully, each successful call to CoInitialize or CoInitializeEx, including those that return S_FALSE, must be balanced by a corresponding call to CoUninitialize Цитата Это типа чтобы текст эдиту присвоился, информация об этом вернулась и только потом нажалась бы кнопка? Это привычка, отсылать текст через SetMessage, чтобы не дать повода для ошибки. Если здесь сделать PostMessage... Хотя, чего я-то? У Paul DiLascia в блоге все написано, читай перевод |
Unconnected |
1.06.2010 18:11
Сообщение
#13
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Ага, поставил именно в начале и конце программы - помогло, я твой код просто в процедуру оборачивал. А вот
Цитата ShellApplication := CreateOleObject('Shell.Application'); , это ж мы в переменной плавающего типа создаём объект, да? А где можно почитать про методы и свойства класса OleObject (конструктор которого был вызван именно с таким параметром)? Я искал по msdn.com, но там чего-то всё относительно Visual Studio Tools for Office. -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
volvo |
1.06.2010 18:17
Сообщение
#14
|
Гость |
Ты про Shell.Application? Вот тут: MSDN -> Shell Object
|
Unconnected |
1.06.2010 23:35
Сообщение
#15
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Спасибо, в итоге добился, чего хотел
-------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
Unconnected |
2.06.2010 23:13
Сообщение
#16
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Volvo, а вот, чисто теоретически, можешь предположить, почему твой код из 10-го поста может не сработать? Вариант со слабой машиной и как следствие маленькой задержкой отметается. Просто человек один говорит, что у него просто открывается Выполнить, там висит команда и ничего не происходит, типа, кнопка не нажалась. Или же вообще, что кнопка Ок неактивна, и становится активна только после нажатия кнопки какой-нибудь в поле ввода. У меня и на основной и на виртуальной машинах всё работает.. Пользуюсь этим, убрал проверку:
//added: может, stdcall надо было написать возле заголовка процедуры? Там же апи, как-никак.. Сообщение отредактировано: Unconnected - 2.06.2010 23:27 -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
volvo |
2.06.2010 23:41
Сообщение
#17
|
Гость |
Теоретически - могу, такое будет, когда программа запускается из-под IDE. У меня у самого так было, пока не запустил из-под Эксплорера... Причем GUI-приложение отрабатывает прекрасно и из-под IDE тоже, а вот консольное - не хочет. Все-таки, консоль - это необычное окно... Зря ты с ней затеялся. Другой причины - не вижу пока.
Цитата может, stdcall надо было написать возле заголовка процедуры? В данном случае это ни на что не влияет. Модель вызова важна в Callback-функциях. У тебя никакого КоллБэка нет. На всякий случай, присоедини сюда или в Личку проект полностью, может у тебя там еще чего заморочено?Добавлено через 2 мин. Цитата //здесь я пробовал дополнительно //ввести пробел, чтобы кнопка активировалась Не поможет, я тоже пробовал, когда запускал из-под IDE. Пока окно не потеряет фокус, и потом его снова не получит - ничего не помогало. Но снимать с Run-диалога фокус, а потом снова активизировать его - это по-моему уже лишнее... |
Unconnected |
3.06.2010 16:13
Сообщение
#18
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Цитата а вот консольное - не хочет. Все-таки, консоль - это необычное окно... Странно, ведь апи-команды, вызываемые из консоли, вроде как ничем не отличаются от тех, которые вызываются из GUI-приложения. У меня, кстати, из консольного всё заработало, с тем добавлением пробела. Странно это. -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
volvo |
3.06.2010 16:29
Сообщение
#19
|
Гость |
Цитата ведь апи-команды, вызываемые из консоли, вроде как ничем не отличаются от тех, которые вызываются из GUI-приложения. Зато поведение консольного окна отличается от того, как ведет себя окно графическое. Возьмет и переключится на консоль в тот момент, когда ты собираешься занести строку в Run-диалог. На долю секунды, не важно, насколько. Но в момент посылки строки Run-диалог будет неактивен. И все... Кнопка "Ok" останется за-disable-нной, несмотря на то, что потом фокус опять перешел назад на диалог.Учитывай, что хозяином консоли является системный процесс csrss. Что так ему в голову придет - ты знаешь? Я - нет... Вопрос на засыпку: а что ты, собственно, выиграл от того, что сделал консольную программу? Думаешь, размер ее будет меньше, чем у оконного приложения? Вряд ли, напиши на чистом API (если тебе от программы больше ничего не надо, кроме как запускать что-то через через Start -> Run, то в 50 строк точно уложишься) - размер будет еще меньше, чем размер консольного приложения... Зато работать будет стабильно... |
Unconnected |
3.06.2010 20:45
Сообщение
#20
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Даа, апи сила) Почитал, переделал (коряво, кажется, но работает)). Размер, правда, остался примерно таким же - вместе с модулями variants,comobj,activex (которые нужны для того кода) и нужным мне Sysutils. Зато - стабильно. Ведь действительно, ну не мог я объяснить, почему у меня 10 раз кряду всё отрабатывает, а у другого - ровно через 3 раза))
Спасибо за советы Сообщение отредактировано: Unconnected - 3.06.2010 20:46 -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
Текстовая версия | 23.09.2024 11:16 |