预期效果:使指定视图对应的UI失去对键盘和鼠标的响应,类似于给控件设置了Enabled属性
一、基本思路
1、找到视图关联的界面窗体handle
2、将handle设置为不可用
二、涉及Win32Api
1、获取窗体Text
private const string DllName = "user32.dll";
[DllImport(DllName)]
public static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount);
public static string GetWindowText(IntPtr hWnd)
{
StringBuilder builder = new StringBuilder(256);
GetWindowText(hWnd, builder, builder.Capacity);
return builder.ToString();
}
2、迭代遍历子窗体
public delegate bool WndEnumProc(IntPtr hWnd, IntPtr Iparam);
[DllImport(DllName)]
public static extern bool EnumChildWindows(IntPtr hWndParent, WndEnumProc IpEnumFunc, IntPtr Iparam);
3、封装方法,根据给定窗体text获取句柄
/// <summary>
/// 根据窗体名称寻找子窗体
/// </summary>
/// <param name="hwndP">父窗体句柄</param>
/// <param name="windowTitle">要查找窗体的title</param>
/// <returns></returns>
public static IntPtr FindChildWindowByTitle(IntPtr hwndP, string windowTitle)
{
IntPtr intPtR = IntPtr.Zero;
if(string.IsNullOrWhiteSpace(windowTitle))
{
return intPtR;
}
IntPtr lParam = Marshal.StringToHGlobalAnsi(windowTitle);
Queue<IntPtr> handles = new Queue<IntPtr>();
handles.Enqueue(hwndP);
//化递归为迭代
while(handles.Any())
{
if (intPtR != IntPtr.Zero)
break;
var useHwn = handles.Dequeue();
EnumChildWindows(useHwn, delegate (IntPtr hwndChild, IntPtr inputParam)
{
if (hwndChild == IntPtr.Zero)
{
//返回true继续遍历
return true;
}
//string value = Marshal.PtrToStringAnsi(ptrKey);
//var tempIntptr = Marshal.StringToHGlobalAnsi(text);
string text = GetWindowText(hwndChild);
if (!string.IsNullOrWhiteSpace(text) && text == windowTitle)
{
intPtR = hwndChild;
return false;
}
handles.Enqueue(hwndChild);
return true;
}, lParam);
}
return intPtR;
}
4、设置句柄为不可用
[PreserveSig, DllImport(DllName, CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool EnableWindow(IntPtr hWnd, bool enable);
三、具体实现
public override Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
var view = commandData.Application.ActiveUIDocument.Document.ActiveView;
string viewTitle =$"{view.Title} - {view.Document.Title}.rvt";
var handle=WinAPI.FindChildWindowByTitle(commandData.Application.MainWindowHandle, viewTitle);
WinAPI.EnableWindow(handle, false);
return Result.Succeeded;
}