2012-06-15 2 views
2

Я бы хотел, чтобы имитировать щелчок мышью на приложении Cocoa, не нажимая на мышь, и * не нужно определять, какое представление должно отвечать на щелчок, учитывая текущее местоположение мыши.Имитировать щелчок мышью в NSWindow

Я хотел бы, чтобы структура Cocoa обрабатывала определение того, какой вид должен отвечать, поэтому я не думаю, что вызов метода для объекта NSView является тем, что я ищу. То есть, я думаю, мне нужен вызов метода, который в конечном итоге вызовет этот метод.

В настоящее время я работаю, щелкая мышью в определенном глобальном местоположении, используя CGEventCreateMouseEvent и CGEventPost. Однако этот метод фактически нажимает на мышь. Так что это работает, но я не совсем доволен поведением. Например, если я удерживаю клавишу на клавиатуре во время вызова CGEventPost, этот ключ завершается в событие. Кроме того, если я перемещаю окно другого процесса над окном, которое я хотел бы имитировать щелчком, тогда метод CGEventPost будет щелкнуть мышью в этом окне. То есть, он действует глобально, через процессы. Мне нужна техника, которая работает в одном окне. Что-то вроде объекта NSWindow?

Я прочитал, что «События мыши отправляются объектом NSWindow объекту NSView, по которому произошло событие» в документации Cocoa.

OK. Поэтому я хотел бы знать метод, который призван выполнять диспетчеризацию. Вызовите этот метод в окне, а затем дайте инфраструктуре выяснить, какой NSView будет вызывать, учитывая текущее местоположение мыши.

Любая помощь была бы принята с благодарностью. Я только начинаю изучать структуру Cocoa, поэтому я приношу свои извинения, если какая-либо из терминологии/веры здесь не совсем правильная.

+2

['- [NSApplication sendEvent:]'] (http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html) по существу является точка входа для входных событий; оттуда он (вообще) попадает в окно. Тем не менее, различие, которое вы пытаетесь провести между «имитацией» и «фактически» щелчком мыши, неясно. Каковы особенности процедуры «CGEvent», которую вы пытаетесь избежать? (Например, в физическом устройстве мыши нет сервопривода, который перемещает кнопку, и это то, что я бы назвал «фактически» нажатием.) –

+0

Отредактировано. Thx для ваших комментариев. –

+0

@JoshCaswell Это похоже на хороший подход, но я не могу заставить его работать. Я бы опубликовал код, но он написан в Clozure с использованием моста Objective C, так что это может быть немного налогообложения для синтаксического анализа. Я не смог найти примеры онлайн-имитационных щелчков мыши, используя sendEvent. Можете ли вы, случайно? –

ответ

4

Трудно точно узнать, сколько верности вы ищете, что происходит для фактического щелчка. Например, хотите ли вы активировать приложение? Вы хотите, чтобы щелчок отображал окно вверху? Сделать это ключевым или основным? Если местоположение находится в строке заголовка, вы хотите, чтобы он потенциально закрывал, сворачивал, увеличивал масштаб или перемещал окно?

Как отметил Джон Касуэлл, если вы передадите соответствующим образом сконструированный NSEvent на номер -[NSApplication sendEvent:], который будет симулировать обработку реального события. В большинстве случаев NSApplication отправит событие в окно события и его метод -[NSWindow sendEvent:]. Если вы хотите избежать каких-либо шансов NSApplication делать что-то еще, вы можете отправить его прямо в окно -sendEvent:. Но это может победить какое-то желательное поведение, в зависимости от того, что вы хотите.

Что произойдет, если ответ щелкнутого окна или представления будет состоять из внутреннего цикла отслеживания событий? Это будет синхронно; то есть код, который вызывает -sendEvent:, не получит контроля до тех пор, пока этот цикл не завершится, и он может не завершиться, если вы не сможете доставить последующие события. Фактически, такой цикл будет искать последующие события через -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:], поэтому, если ваши синтетические события не находятся в очереди, они не будут видны. Таким образом, даже лучшее симуляция обработки реальных событий, вероятно, потребует, чтобы вы отправляли события (мышь, мышь, мышью) в очередь, используя -[NSApplication postEvent:atStart:].

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

Что касается материалов CGEvent..., вы можете отправить мероприятие в конкретный процесс с помощью CGEventPostToPSN() и не нажимать на окна другого приложения, даже если они находятся перед целевым окном. Тем не менее, он все равно может нажать на другое окно в целевом приложении.

1

Вы можете имитировать щелчок мыши, вызвав mouseDown: так:

[self mouseDown: nil]; 

И получить расположение мыши в окне:

-(void)mouseDown:(NSEvent *)theEvent { 

    NSPoint mouseLocation = [NSEvent mouseLocation]; 

    NSLog(@"x: %f", mouseLocation.x); 
    NSLog(@"y: %f", mouseLocation.y); 
} 
+0

Для этого требуется уже знание правильной цели события мыши. –

+0

@JoshCaswell Что вы имеете в виду, зная правильную цель события мыши? –

+0

Это похоже на правильное направление, но я думаю, что мне нужно создать подходящий объект NSEvent для щелчка мыши. И этот код должен иметь местоположение мыши в нем, да? –

2

OK. Поэтому я хотел бы знать метод, который призван выполнять диспетчеризацию. Вызовите этот метод в окне, а затем дайте инфраструктуре выяснить, какой NSView будет вызывать, учитывая текущее местоположение мыши.

NSView *target = [[theWindow contentView] hitTest:thePoint]; 

Я не совсем ясно, на вашей проблеме, так что я не знаю, если все, что вам нужно сделать, это то называют MouseDown: на цель. Но если бы вы это сделали, это было бы почти то же самое, что и при реальном щелчке мыши.

Это сообщение, используемое при доставке живых кликов. Он просматривает иерархию представлений, автоматически обрабатывая перекрытие, скрытые сообщения и т. Д., И позволяет каждому шагу в цепочке представлений вмешиваться, если захочет. Если в представлении требуется, чтобы дочерние представления не получали клики, это делает это путем использования hitTest :, что означает, что это повлияет на ваш код точно так же, как на реальный клик. Если будет доставлен, этот метод всегда сообщает вам , где будет доставлен.

Однако он не обязательно обрабатывает все причины, по которым не может быть доставлен клик (acceptsFirstMouse, модальные диалоги и т. Д.). Кроме того, вы должны знать окно и точку (в соответствующей системе координат), но, похоже, это то, с чего вы начинаете.

+0

Спасибо abarnert. Это похоже на простой подход. Будет проверяться в ближайшее время и опубликовать результаты. –

Смежные вопросы