2011-10-10 4 views
2

Я хотел бы использовать цикл в то время как левая MouseButton нажата:C# цикл, пока кнопка нажата MouseDown

private void Loop_MouseDown(object sender, MouseEventArgs e) 
     { 
      while (e.Button==MouseButtons.Left) 
      { 
      //Loop 
      } 
     } 

Я не могу использовать решение из этой темы:
C# how to loop while mouse button is held down , потому что я представляемого через RS232 данные и использование таймера с собственным интервалом не работают. Также любое решение из этой темы не работает для меня. Он не может работать один, как здесь:

if (e.Button == MouseButtons.Left) 
    { 
     //loop 
    } 

Это решение также не работает:

bool isLooping = false; 

//on mouse down 
private void myControl_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { 
    isLooping = true; 
    runLoop(); 
} 

//on mouse up event 
private void myControl_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { 
    isLooping = false; 
} 

//This is the main loop you care about. Put this in your application 
//This should go in its own thread 
void runLoop() { 
    while (isLooping) { 
     //do stuff 
    } 
} 

, потому что вызов runLoop будет блокировать поток, и поэтому событие MouseUp никогда не будет огня.

Итак, как заставить его работать правильно?

+0

Зачем вам это нужно? – TJHeuvel

+0

Почему таймер не работает? – SLaks

+0

Рассматривали ли вы использование API для получения текущего состояния кнопки мыши? –

ответ

2

Используйте BackgroundWorker. Идеально подходит для вашей проблемы.

Поместите функцию цикла в рабочий и запустите/остановите рабочего на события мыши.

+0

Когда вы говорите «остановка», вы имеете в виду «[отменить] (http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.cancelasync.aspx)»? – svick

+0

sry означает RunWorkerAsync & CancelAsync – jrb

+0

Простое и приятное решение. Tnx;) – Elfoc

0

Если таймер не работает, вам нужно будет отправить данные в другой поток и передать этот поток из обработчика MouseUp.

0

Правильный способ сделать это будет поместить функцию отправки rs-232 в отдельный поток, чтобы пользовательский интерфейс оставался отзывчивым, после чего вы можете запускать и останавливать его при изменении событий мыши.

Эта страница может быть полезно:

http://www.yoda.arachsys.com/csharp/threads/winforms.shtml

0

Эти сценарии очень сложны для реализации - см. Ваши обработчики и логические переменные для хранения состояния.

Я предлагаю использовать Reactive Extensions.

Edit:

Это, вероятно, будет немного избыточны (я не знаю, если это единственный сценарий Elfoc хочет реализовать). В Rx вы можете создать наблюдаемую последовательность событий

var mouseDown = Observable.FromEvent<MouseButtonEventArgs>(source, "MouseDown"); 
var mouseUp = Observable.FromEvent<MouseButtonEventArgs>(image, "MouseUp"); 
var mouseMove = from evt in Observable.FromEvent<MouseEventArgs>(image, "MouseMove") 
    select evt.EventArgs.GetPosition(this); 

использование LINQ к Rx для запросов и фильтровать события

var leftMouseDown = from evt in mouseDown 
    where evt.LeftButton == MouseButtonState.Pressed 
    select evt; 

и слагающих его с помощью операторов Rx - до любой мыши вверх событие не поднимается взять все позиции в то время как левая кнопка мыши нажата

var q = from position in leftMouseDown 
    from pos in mouseMove.Until(mouseUp) 
    select new { X = pos.X - imageOffset.X, Y = pos.Y - imageOffset.Y }; 

Наконец, подписаться на наблюдаемую последовательность позиций и сделать свой материал

q.Subsribe(value => { ... }); 

Немного изменено с кодом here.

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