2013-08-30 3 views
0

У меня есть приложение, которое захватывает сообщения Windows, посланные в форму, и запускает метод, если обновление производится в буфере обмена системы:обработки окна сообщений, объекты резьб COM

protected override void WndProc(ref Message m) 
{ 
    switch (m.Msg) 
    { 
     case WM_CLIPBOARDUPDATE: 

      if (IsClipboardListenerOn) 
       OnClipboardChanged(); 

      break; 
    } 

    base.WndProc(ref m); 
} 

В некоторых случаях я не» t хочу мой метод, OnClipboardChanged(), для запуска. Моим решением было установить статическую глобальную переменную IsClipboardListenerOn и переключить ее по мере необходимости. Это не получить работу, так как сообщение Windows, не был обработан до после моей функции, сделавшей переключение вернулся, так что это всегда было правдой:

private void some_event(object sender, EventArgs e) 
{ 
    MainForm.IsClipboardListenerOn = false; 

    // some code that makes the clipboard changed message fire 

    MainForm.IsClipboardListenerOn = true; 

    // when this returns the WM_CLIPBOARDUPDATE message gets caught 
} 

Следующая идея была запустить код, вызвало сообщение о событии на нитку и ждать, пока поток, чтобы вернуться, чтобы гарантировать ее казнены в то время как глобальный флаг выключена:

Thread thread1 = new Thread(() => clipboard_stuff()); 
    thread1.SetApartmentState(ApartmentState.STA); 

    MainForm.IsClipboardListenerOn = false; 

    thread1.Start();   

    thread1.Join(); 
    MainForm.IsClipboardListenerOn = true; 

Но это не сработало, либо. Фактически, иногда он будет выполнять мой метод OnClipboardChanged() дважды. Я знаю, что для системы Clipboard требуется отдельная квартира с резьбой; Является ли эта часть моей проблемы? Я собираюсь сделать это неправильно? Есть ли какая-то другая техника, которую я могу использовать?

ответ

2

Правильно, это не сработает. Windows ждет, когда вы снова начнете накачивать сообщения. Обходной путь заключается в том, чтобы отложить установку флага обратно в значение true до тех пор, пока не будут отправлены все ожидающие сообщения. Это можно сделать элегантно, используя метод Control.BeginInvoke(). Например:

private void some_event(object sender, EventArgs e) 
{ 
    MainForm.IsClipboardListenerOn = false; 
    // some code that makes the clipboard changed message fire 
    //... 
    this.BeginInvoke(new Action(() => MainForm.IsClipboardListenerOn = true)); 
} 

С предположением, что some_event() является членом формы. Я бы предположил, что MainForm.BeginInvoke() будет работать.

+0

Throwing исключение NullReferenceException. some_event является делегатом для события кликов ToolStripMenuItem. Мой глобальный флаг определяется как: static public bool IsClipboardListenerOn = true; –

+0

Я не могу сказать, как выглядят ваши ссылки на объекты. Выберите что-то не null :) –

+0

Прошу прощения, я просто не знаком с кодом на основе LINQ. Там ничего не должно быть. Вы вызываете новый объект Action и создаете его с анонимным делегатом? Не возражаете ли вы прописать это немного больше, что на самом деле делает ваш код? –

0

Похоже, должно быть более чистое решение, чем то, что я собираюсь предложить, но вы знаете, что они говорят ... если это глупо, и это работает, это не глупо.

Если вы уверены, что вы собираетесь вызвать сообщение из буфера обмена, который вы хотите игнорировать, установить флаг и пусть WndProc закрыть его:

private void some_event(object sender, EventArgs e) 
{ 
    MainForm.SkipNextClipboardMessage = true; 
    // some code that makes the clipboard changed message fire 
} 

protected override void WndProc(ref Message m) 
{ 
    switch (m.Msg) 
    { 
     case WM_CLIPBOARDUPDATE: 
      if (SkipNextClipboardMessage) 
       SkipNextClipboardMessage = false; 
      else      
       OnClipboardChanged(); 
      break; 
    } 
    base.WndProc(ref m); 
} 

Еще одна страшная мысль, что это связанный с получить некоторые stinkeyes от читателей - это сделать так, как вы делали в своей первой версии кода, и добавить звонок в Application.DoEvents() после того, как вы вызвали метод изменения буфера обмена, чтобы заставить сообщения обрабатываться.

Да, да, это зло, и я пойду в ад, я знаю.

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