从@DotNetHitMan 的答案谷歌搜索,我终于找到了PeekMessage,它让我在离开 matlab 代码时从 windows 队列中删除不需要的消息,所以很容易:
private void onBtnClick(object sender, EventArgs e)
{
// Call matlab
matlabComponent.ShowModalDlg();
// Remove unwanted messages from the queue
NativeMessage msg;
while (PeekMessage(out msg, new HandleRef(this, this.Handle), WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)); // Remove mouse messages
while (PeekMessage(out msg, new HandleRef(this, this.Handle), WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)); // Remove keyboard messages
}
注意:PeekMessage 和 NativeMessage 互操作的语法可以从 here 读取。
编辑
这是将事物重构为using 语句的代码:
using System;
using System.Drawing;
using System.Runtime.InteropServices;
/// <summary>Allows discarding keyboard and mouse events while thread is blocked in executing some code while its windows message queue is continuing to accumulate events.</summary>
///<example>If you don't disable events while showing matlab modal dialog, events will continue to accumulate in message queue and will be processed after modal dialog is closed (i.e. not the behaviour one expects for a modal dialog).</example>
public class DiscardUiEvents : IDisposable
{
/// <summary>Create new discard object.</summary>
/// <param name="hr">Reference to the control that need to block its events.</param>
/// <remarks>
/// Must be used like this:
///
/// using(new DiscardUiEvent(new HandleRef(myControl, myControl.Handle)))
/// {
/// matlabCompiledCode.ShowSomeModalFigure();
/// }
/// </remarks>
public DiscardUiEvents(HandleRef hr)
{
this.hr = hr;
}
/// <summary>Dispose discard object.</summary>
public void Dispose()
{
if (disposed) { return; }
NativeMessage msg;
while (PeekMessage(out msg, hr, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) { /* Remove all mouse messages */ }
while (PeekMessage(out msg, hr, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) { /* Remove all keyboard messages */ }
}
private readonly HandleRef hr;
private bool disposed = false;
private const UInt32 PM_REMOVE = 0x0001;
private const UInt32 WM_MOUSEFIRST = 0x0200;
private const UInt32 WM_MOUSELAST = 0x020D;
private const UInt32 WM_KEYFIRST = 0x0100;
private const UInt32 WM_KEYLAST = 0x0108;
// ReSharper disable MemberCanBePrivate.Local
[StructLayout(LayoutKind.Sequential)]
private struct NativeMessage
{
public IntPtr handle;
public UInt32 msg;
public IntPtr wParam;
public IntPtr lParam;
public UInt32 time;
public Point p;
}
// ReSharper restore MemberCanBePrivate.Local
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool PeekMessage(out NativeMessage lpMsg, HandleRef hWnd, uint wMsgFilterMin, uint wMsgFilterMax, uint wRemoveMsg);
}
可以这样使用:
using(new DiscardUiEvent(new HandleRef(myControl, myControl.Handle)))
{
matlabCompiledCode.ShowSomeModalFigure();
}