Files
ShrlAlgoToolkit/ShrlAlgoToolkit.Revit/Assists/KeyIntPtrHelper.cs

681 lines
19 KiB
C#
Raw Normal View History

2024-09-22 11:05:41 +08:00
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Interop;
using Autodesk.Windows;
2025-04-24 20:56:44 +08:00
namespace ShrlAlgoToolkit.Revit.Assists;
2024-09-22 11:05:41 +08:00
public class KeyIntPtrHelper
{
public delegate bool CallBack(IntPtr hwnd, int lParam);
public delegate bool EnumWindowsProc(IntPtr hWnd, int lParam);
private static void CompleteMultiSelection()
{
var rvtwindow = ComponentManager.ApplicationWindow;
var list = new List<IntPtr>();
var flag = EnumChildWindows(
rvtwindow,
(hwnd, l) =>
{
var windowText = new StringBuilder(200);
_ = GetWindowText(hwnd, windowText, windowText.Capacity);
var className = new StringBuilder(200);
_ = GetClassName(hwnd, className, className.Capacity);
if (
(
windowText.ToString().Equals("完成", StringComparison.Ordinal)
|| windowText.ToString().Equals("Finish", StringComparison.Ordinal)
) && className.ToString().Contains("Button")
)
{
list.Add(hwnd);
return false;
}
return true;
},
new IntPtr(0)
);
var complete = list.FirstOrDefault();
_ = PostMessage(complete, 245, 0, 0);
}
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
private static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
private static extern bool DeleteObject(IntPtr hObject);
/// <summary>
/// 确定主窗口
/// </summary>
/// <param name="handles"></param>
/// <returns></returns>
private static IntPtr DetermineMainWindow(IReadOnlyList<IntPtr> handles)
{
IntPtr result;
if (handles == null || handles.Count <= 0)
{
result = IntPtr.Zero;
}
else
{
var intPtr = IntPtr.Zero;
if (handles.Count == 1)
{
intPtr = handles[0];
}
else
{
foreach (var intPtr2 in handles)
{
var windowTextLength = GetWindowTextLength(intPtr2);
if (windowTextLength != 0)
{
var stringBuilder = new StringBuilder(windowTextLength);
_ = GetWindowText(intPtr2, stringBuilder, windowTextLength + 1);
if (stringBuilder.ToString().ToLower().Contains("autodesk revit"))
{
intPtr = intPtr2;
break;
}
}
}
}
result = intPtr;
}
return result;
}
[DllImport("user32.dll", CharSet = CharSet.None, ExactSpelling = false)]
private static extern bool EnumChildWindows(IntPtr hwndParent, CallBack lpEnumFunc, IntPtr lParam);
[DllImport("user32.DLL")]
private static extern bool EnumWindows(EnumWindowsProc enumFunc, int lParam);
[DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Unicode)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern int GetCurrentThreadId();
[DllImport("user32.dll")]
private static extern int GetKeyboardState(byte[] lpKeyState);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetKeyNameText(int lParam, [Out] StringBuilder lpString, int nSize);
[DllImport("user32.dll")]
private static extern short GetKeyState(short nVirtKey);
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.DLL")]
private static extern IntPtr GetShellWindow();
[DllImport("user32.dll")]
private static extern IntPtr GetSystemMenu(IntPtr hWnd, int revert);
[DllImport("user32.dll")]
private static extern IntPtr GetWindow(IntPtr hWnd, int uCmd);
[DllImport("user32.dll")]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
private static extern IntPtr GetWindowLongPtr_1(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpText, int nCount);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
[DllImport("user32.dll")]
private static extern bool IsChild(IntPtr hWndParent, IntPtr hWnd);
[DllImport("user32.DLL")]
private static extern bool IsWindowVisible(IntPtr hWnd);
/// <summary>
/// 键盘事件
/// </summary>
/// <param name="bVk">虚拟键值查询虚拟键值表</param>
/// <param name="bScan">扫描不设置为0</param>
/// <param name="dwFlags">按键状态选项按下为0如果为松开 则设置成2KEYEVENT_KEYUP</param>
/// <param name="dwExtraInfo">,一般为0</param>
[DllImport("user32.dll")]
private static extern void keybdEvent(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
/// <summary>
/// 虚拟按钮
/// </summary>
/// <param name="uCode"></param>
/// <param name="uMapType"></param>
/// <returns></returns>
[DllImport("user32.dll")]
private static extern uint MapVirtualKey(uint uCode, uint uMapType);
[DllImport("user32.dll")]
private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
/// <summary>
///发送消息
/// </summary>
/// <param name="hWnd"></param>
/// <param name="msg"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <example>
/// <para>Press.PostMessage(_revit_window, (uint)Press.KEYBOARD_MSG.WM_KEYDOWN, (uint)System.Windows.Forms.Keys.Escape, 0);</para>
/// <para>Press.PostMessage(_revit_window, (uint)Press.KEYBOARD_MSG.WM_KEYDOWN, (uint)System.Windows.Forms.Keys.Escape, 0);</para></example>
/// <returns></returns>
[DllImport("user32.dll")]
private static extern bool PostMessage(IntPtr hWnd, uint msg, uint wParam, uint lParam);
[DllImport("user32.dll")]
private static extern IntPtr SetActiveWindow(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool SetWindowText(IntPtr hWnd, string lpString);
/// <summary>
/// 显示窗口
/// </summary>
/// <param name="hWnd"></param>
/// <param name="nCmdShow">0隐藏窗口1恢复窗口大小2最小化窗口3最大化窗口</param>
/// <returns></returns>
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
private static extern int ToUnicode(
int wVirtKey,
int wScanCode,
byte[] lpKeyState,
[MarshalAs(UnmanagedType.LPWStr)][Out] StringBuilder pwszBuff,
int cchBuff,
int wFlags
);
/// <summary>
/// 执行Esc两次退出Revit选择
/// </summary>
2024-12-22 10:26:12 +08:00
public static void RaiseEscTwice()
2024-09-22 11:05:41 +08:00
{
SetForegroundWindow(ComponentManager.ApplicationWindow);
keybdEvent(27, 0, 0, 0);
keybdEvent(27, 0, 2, 0);
2024-12-22 10:26:12 +08:00
//keybdEvent(0x1B, 0, 0, 0);
//keybdEvent(0x1B, 0, 0, 0);
2024-09-22 11:05:41 +08:00
}
/// <summary>
/// 查找内容
/// </summary>
/// <param name="hwndParent"></param>
/// <param name="hwndChildAfter"></param>
/// <param name="lpszClass"></param>
/// <param name="lpszWindow"></param>
/// <returns></returns>
[DllImport("user32.dll", EntryPoint = "FindWindowEx", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindowEx(
IntPtr hwndParent,
IntPtr hwndChildAfter,
string lpszClass,
string lpszWindow
);
public static IntPtr GetMainWindow(int pid)
{
var shellWindow = GetShellWindow();
var windowsForPid = new List<IntPtr>();
_ = EnumWindows(
(hWnd, _) =>
{
if (hWnd == shellWindow) { }
else
{
if (!IsWindowVisible(hWnd))
{
return true;
}
2024-12-22 10:26:12 +08:00
GetWindowThreadProcessId(hWnd, out var num);
2024-09-22 11:05:41 +08:00
if (num != (ulong)pid)
{
return true;
}
var parent = GetParent(hWnd);
if (parent == IntPtr.Zero)
{
windowsForPid.Add(hWnd);
}
}
return true;
},
0
);
return DetermineMainWindow(windowsForPid);
}
public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex)
{
return IntPtr.Size == 8 ? GetWindowLongPtr_1(hWnd, nIndex) : new IntPtr(GetWindowLong(hWnd, nIndex));
}
public static void HideWindow(string winName)
{
var parenthWndldsl = FindWindow(null, winName);
if (!parenthWndldsl.Equals(IntPtr.Zero))
{
_ = ShowWindow(parenthWndldsl, 0);
}
}
public static bool IsVisible(string winName)
{
var parenthWndldsl = FindWindow(null, winName);
return !parenthWndldsl.Equals(IntPtr.Zero);
}
/// <summary>
/// 提交一系列按钮
/// </summary>
/// <param name="revitHandle"></param>
/// <param name="command">快捷键命令</param>
public static void Keys(IntPtr revitHandle, string command)
{
//IntPtr revitHandle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
foreach (var letter in command)
{
OneKey(revitHandle, letter);
}
}
/// <summary>
/// 提交单个按键
/// </summary>
/// <param name="handle">窗口句柄</param>
/// <param name="letter"></param>
public static void OneKey(IntPtr handle, char letter)
{
var scanCode = MapVirtualKey(letter, (uint)MvkMapType.VkeyToScancode);
var keyDownCode = (uint)WhKeyboardLparam.Keydown | (scanCode << 16);
var keyUpCode = (uint)WhKeyboardLparam.Keyup | (scanCode << 16);
PostMessage(handle, (uint)KeyboardMsg.WmKeydown, letter, keyDownCode);
PostMessage(handle, (uint)KeyboardMsg.WmKeyup, letter, keyUpCode);
}
public static bool RestoreWindow(IntPtr hWnd)
{
return ShowWindow(hWnd, 1);
}
public static void SendKeys(IntPtr proc, byte bVk)
{
SetActiveWindow(proc);
SetForegroundWindow(proc);
//keybd_event(27, 0, 0, 0);
//keybd_event(27, 0, 2, 0);
keybdEvent(bVk, 0, 0, 0);
keybdEvent(bVk, 0, 2, 0);
keybdEvent(bVk, 0, 0, 0);
keybdEvent(bVk, 0, 2, 0);
}
public static void SetAsOwner(IntPtr mainHandler, Window childWindow)
{
new WindowInteropHelper(childWindow).Owner = mainHandler;
}
public static void ShowAndActive(string winname)
{
var parenthWndldsl = FindWindow(null, winname);
if (!parenthWndldsl.Equals(IntPtr.Zero))
{
ShowWindow(parenthWndldsl, 1);
SetActiveWindow(parenthWndldsl);
}
}
/// <summary>
/// 键盘消息
/// </summary>
public enum KeyboardMsg : uint
{
WmKeydown = 0x100,
WmKeyup = 0x101
}
private enum MvkMapType : uint
{
VkeyToScancode = 0,
ScancodeToVkey = 1,
VkeyToChar = 2,
ScancodeToLrVkey = 3
}
private enum WhKeyboardLparam : uint
{
Keydown = 0x00000001,
Keyup = 0xC0000001
}
#region Win32 API Hook
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
private const int VbWH_MOUSE_LL = 14;
private const int VbWM_LBUTTONDOWN = 0x0201;
private static IntPtr _hookID = IntPtr.Zero;
private static IntPtr SetHook(HookProc proc)
{
using var curProcess = Process.GetCurrentProcess();
using var curModule = curProcess.MainModule;
return SetWindowsHookEx(VbWH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private static IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)VbWM_LBUTTONDOWN)
{
MessageBox.Show("Left button down");
CompleteMultiSelection();
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
public static void MouseLeftButtonAction(Action action)
{
_hookID = SetHook(MouseHookCallback);
action();
UnhookWindowsHookEx(_hookID);
}
#endregion
#region Keys
public const byte VbKey0 = 48;
public const byte VbKey1 = 49;
public const byte VbKey2 = 50;
public const byte VbKey3 = 51;
public const byte VbKey4 = 52;
public const byte VbKey5 = 53;
public const byte VbKey6 = 54;
public const byte VbKey7 = 55;
public const byte VbKey8 = 56;
public const byte VbKey9 = 57;
public const byte VbKeyA = 65;
public const byte VbKeyAdd = 107;
public const byte VbKeyAlt = 18;
public const byte VbKeyB = 66;
public const byte VbKeyBack = 8;
public const byte VbKeyC = 67;
public const byte VbKeyCancel = 3;
public const byte VbKeyCapital = 20;
public const byte VbKeyClear = 12;
public const byte VbKeyControl = 17;
public const byte VbKeyD = 68;
public const byte VbKeyDecimal = 110;
public const byte VbKeyDelete = 46;
public const byte VbKeyDivide = 111;
public const byte VbKeyDown = 40;
public const byte VbKeyE = 69;
public const byte VbKeyEnd = 35;
public const byte VbKeyEscape = 27;
public const byte VbKeyExecute = 43;
public const byte VbKeyF = 70;
public const byte VbKeyF1 = 112;
public const byte VbKeyF10 = 121;
public const byte VbKeyF11 = 122;
public const byte VbKeyF12 = 123;
public const byte VbKeyF2 = 113;
public const byte VbKeyF3 = 114;
public const byte VbKeyF4 = 115;
public const byte VbKeyF5 = 116;
public const byte VbKeyF6 = 117;
public const byte VbKeyF7 = 118;
public const byte VbKeyF8 = 119;
public const byte VbKeyF9 = 120;
public const byte VbKeyG = 71;
public const byte VbKeyH = 72;
public const byte VbKeyHelp = 47;
public const byte VbKeyHome = 36;
public const byte VbKeyI = 73;
public const byte VbKeyJ = 74;
public const byte VbKeyK = 75;
public const byte VbKeyL = 76;
public const byte VbKeyLButton = 1;
public const byte VbKeyLeft = 37;
public const byte VbKeyM = 77;
public const byte VbKeyMButton = 4;
public const byte VbKeyMenu = 18;
public const byte VbKeyMultiply = 106;
public const byte VbKeyN = 78;
public const byte VbKeyNumlock = 144;
public const byte VbKeyNumpad0 = 96;
public const byte VbKeyNumpad1 = 97;
public const byte VbKeyNumpad2 = 98;
public const byte VbKeyNumpad3 = 99;
public const byte VbKeyNumpad4 = 100;
public const byte VbKeyNumpad5 = 101;
public const byte VbKeyNumpad6 = 102;
public const byte VbKeyNumpad7 = 103;
public const byte VbKeyNumpad8 = 104;
public const byte VbKeyNumpad9 = 105;
public const byte VbKeyO = 79;
public const byte VbKeyP = 80;
public const byte VbKeyPageUp = 33;
public const byte VbKeyPause = 19;
public const byte VbKeyPrint = 42;
public const byte VbKeyQ = 81;
public const byte VbKeyR = 82;
public const byte VbKeyRButton = 2;
public const byte VbKeyReturn = 13;
public const byte VbKeyRight = 39;
public const byte VbKeyS = 83;
public const byte VbKeySelect = 41;
public const byte VbKeySeparator = 108;
public const byte VbKeyShift = 16;
public const byte VbKeySnapshot = 44;
public const byte VbKeySpace = 32;
public const byte VbKeySubtract = 109;
public const byte VbKeyT = 84;
public const byte VbKeyTab = 9;
public const byte VbKeyU = 85;
public const byte VbKeyUp = 38;
public const byte VbKeyV = 86;
public const byte VbKeyW = 87;
public const byte VbKeyX = 88;
public const byte VbKeyY = 89;
public const byte VbKeyZ = 90;
public const int WmChar = 258;
public const int WmClick = 245;
public const int WmClose = 16;
public const int WmDeadchar = 259;
public const int WmKeydown = 256;
public const int WmKeyup = 257;
public const int WmLbuttondblclk = 515;
public const int WmLbuttondown = 513;
public const int WmLbuttonup = 514;
public const int WmMbuttondblclk = 521;
public const int WmMbuttondown = 519;
public const int WmMbuttonup = 520;
public const int WmMousehwheel = 526;
public const int WmMousemove = 512;
public const int WmMousewheel = 522;
public const int WmRbuttondblclk = 518;
public const int WmRbuttonup = 517;
public const int WmSyschar = 262;
public const int WmSysdeadchar = 263;
public const int WmSyskeydown = 260;
public const int WmSyskeyup = 261;
public const int WmXbuttondblclk = 525;
public const int WmXbuttondown = 523;
public const int WmXbuttonup = 524;
#endregion
}