using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; using System.Windows; using System.Windows.Interop; using Autodesk.Windows; namespace ShrlAlgoToolkit.Revit.Assists; public class KeyIntPtrHelper { public delegate bool CallBack(IntPtr hwnd, int lParam); public delegate bool EnumWindowsProc(IntPtr hWnd, int lParam); private static void CompleteMultiSelection() { var window = ComponentManager.ApplicationWindow; var list = new List(); var flag = EnumChildWindows( window, (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); /// /// 确定主窗口 /// /// /// private static IntPtr DetermineMainWindow(IReadOnlyList 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) continue; 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); /// /// 键盘事件 /// /// 虚拟键值查询虚拟键值表 /// 扫描不设置为0 /// 按键状态选项按下为0,如果为松开 则设置成2,KEYEVENT_KEYUP /// ,一般为0 [DllImport("user32.dll", EntryPoint = "keybd_event")] private static extern void keybdEvent(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo); /// /// 虚拟按钮 /// /// /// /// [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); /// ///发送消息 /// /// /// /// /// /// /// Press.PostMessage(_revit_window, (uint)Press.KEYBOARD_MSG.WM_KEYDOWN, (uint)System.Windows.Forms.Keys.Escape, 0); /// Press.PostMessage(_revit_window, (uint)Press.KEYBOARD_MSG.WM_KEYDOWN, (uint)System.Windows.Forms.Keys.Escape, 0); /// [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); /// /// 显示窗口 /// /// /// 0隐藏窗口,1恢复(原)窗口大小,2最小化窗口,3最大化窗口 /// [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 ); /// /// 查找内容 /// /// /// /// /// /// [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(); _ = EnumWindows( (hWnd, _) => { if (hWnd == shellWindow) { } else { if (!IsWindowVisible(hWnd)) { return true; } GetWindowThreadProcessId(hWnd, out var num); 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); } /// /// 提交一系列按钮 /// /// /// 快捷键命令 public static void Keys(IntPtr revitHandle, string command) { //IntPtr revitHandle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle; foreach (var letter in command) { OneKey(revitHandle, letter); } } /// /// 提交单个按键 /// /// 窗口句柄 /// 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); } /// /// 执行Esc两次,退出Revit选择 /// public static void RaiseEscTwice() { SetForegroundWindow(ComponentManager.ApplicationWindow); keybdEvent(27, 0, 0, 0); keybdEvent(27, 0, 2, 0); //keybdEvent(0x1B, 0, 0, 0); //keybdEvent(0x1B, 0, 0, 0); } /// /// 执行Esc两次,退出Revit命令(常用) /// public static void PostEscTwice() { SetForegroundWindow(ComponentManager.ApplicationWindow); PostMessage(ComponentManager.ApplicationWindow, (uint)KEYBOARD_MSG.WM_KEYDOWN, (uint)27, 0); PostMessage(ComponentManager.ApplicationWindow, (uint)KEYBOARD_MSG.WM_KEYDOWN, (uint)27, 0); //keybdEvent(0x1B, 0, 0, 0); //keybdEvent(0x1B, 0, 0, 0); } 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; } [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool SetWindowText(IntPtr hWnd, string lpString); public static void ShowAndActive(string winname) { var parenthWndldsl = FindWindow(null, winname); if (!parenthWndldsl.Equals(IntPtr.Zero)) { ShowWindow(parenthWndldsl, 1); SetActiveWindow(parenthWndldsl); } } private enum WH_KEYBOARD_LPARAM : uint { KEYDOWN = 0x00000001, KEYUP = 0xC0000001 } public enum KEYBOARD_MSG : uint { WM_KEYDOWN = 0x100, WM_KEYUP = 0x101 } private enum MVK_MAP_TYPE : uint { VKEY_TO_SCANCODE = 0, SCANCODE_TO_VKEY = 1, VKEY_TO_CHAR = 2, SCANCODE_TO_LR_VKEY = 3 } /// /// 键盘消息 /// 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 }