/// <summary> /// Processes Windows messages. /// </summary> /// <param name="m">The Windows Message to process. </param> protected override void WndProc(ref Message m) { switch (m.Msg) { case PI.WM_.NCLBUTTONDOWN: { // Perform a hit test to determine which area the mouse press is over at the moment uint result = PI.SendMessage(Handle, PI.WM_.NCHITTEST, IntPtr.Zero, m.LParam); // Only want to override the behaviour of moving the window via the caption bar if (result == PI.HT.CAPTION) { // Extract screen position of the mouse from the message LPARAM Point screenPos = new Point(PI.LOWORD(m.LParam), PI.HIWORD(m.LParam)); // Find the mouse offset relative to the top left of the window Point offset = new Point(screenPos.X - Location.X, screenPos.Y - Location.Y); // Do not intercept message if inside the max/close buttons if (!HitTestMaxButton(offset) && !HitTestCloseButton(offset)) { // Capture the mouse until the mouse us is received and gain focus so we look active Capture = true; Activate(); // Use event to notify the request to drag the window OnWindowCaptionDragging(new ScreenAndOffsetEventArgs(screenPos, offset)); // Eat the message! return; } } } break; case PI.WM_.KEYDOWN: base.WndProc(ref m); FloatingMessages?.OnKEYDOWN(ref m); return; case PI.WM_.MOUSEMOVE: base.WndProc(ref m); FloatingMessages?.OnMOUSEMOVE(); return; case PI.WM_.LBUTTONUP: base.WndProc(ref m); FloatingMessages?.OnLBUTTONUP(); return; } base.WndProc(ref m); }
/// <summary> /// Показать скрытое окно /// </summary> /// <param name="process">Процесс</param> /// <param name="windowHandle">Дескриптор окна</param> /// <param name="windowWmCommand">Команда для открытия окна</param> public static void ShowHiddenWindow(Process process, IntPtr windowHandle, int windowWmCommand) { if (PI.IsWindowVisible(windowHandle) == false) { PI.SendMessage(process.MainWindowHandle, (uint)PI.WM.COMMAND, windowWmCommand, 0); return; } }
/// <summary> /// A few keyboard messages need to be forwarded to the inner textbox of the /// KryptonNumericUpDown control so that the first character pressed appears in it. /// </summary> protected override bool ProcessKeyEventArgs(ref Message m) { TextBox textBox = Controls[0] as TextBox; if (textBox != null) { PI.SendMessage(textBox.Handle, m.Msg, m.WParam, m.LParam); return(true); } return(base.ProcessKeyEventArgs(ref m)); }
/// <summary> /// Поиск дескриптора окна /// </summary> /// <param name="currentProcess">Текущий процесс</param> /// <param name="windowName">Имя окна</param> /// <param name="wndWmCommand">WM-команда окна</param> /// <param name="dialogHandle">handle диалога</param> /// <param name="wndVisiblePtr">Дескриптор найденного окна</param> /// <returns>True - успешно, False - с ошибкой</returns> /// <param name="isSecondUse">Второй ли запуск функции (рекурсивный) /// </param> public static bool SearchWindowDescriptor(Process currentProcess, string windowName, int wndWmCommand, ref IntPtr dialogHandle, ref IntPtr wndVisiblePtr, bool isSecondUse = false) { // Поиск плавающего представления окна через функцию IntPtr res = PI.FindWindowByCaption(IntPtr.Zero, windowName); if (res != IntPtr.Zero) { var resList = PI.GetChildWindows(res); if (resList.Count > 0) { dialogHandle = resList[0]; wndVisiblePtr = dialogHandle; } } else { const int bufferSize = 200; var stringBuffer = new StringBuilder(bufferSize); // Поиск плавающего представления окна по всем окнам системы SearchFloatWindow(stringBuffer, windowName, ref dialogHandle, ref wndVisiblePtr); if (dialogHandle == IntPtr.Zero) { // Поиск закрепленного представления окна SearchStaticWindow(currentProcess, stringBuffer, windowName, ref dialogHandle, ref wndVisiblePtr); } if (dialogHandle == IntPtr.Zero) { PI.SendMessage(currentProcess.MainWindowHandle, (uint)PI.WM.COMMAND, wndWmCommand, 0); if (isSecondUse == true && dialogHandle == IntPtr.Zero) { MessageBox.Show("Не удалось найти окно!"); return(false); } // Повторный поиск SearchWindowDescriptor(currentProcess, windowName, wndWmCommand, ref dialogHandle, ref wndVisiblePtr, true); } } return(true); }
public static bool modeIsShown = false; // Показано ли окно. /// <summary> /// Инициализация формы данными для редактирования. /// /// Так как данная форма отображается как внутреннее окно, то алгоритм /// следующий: /// 1 Поиск окна "Основные данные изделия" (меню Сервисные программы -> /// Изделие -> Навигатор основных данных изделий). /// 1.1 Поиск плавающего представления: через FindWindowByCaption, /// потом для поиска панели и диалога DlgItemId (0xE81F - базовая панель, /// 0x32С8 - диалог). Если окно найдено, то переходим к 4, иначе к 1.1.1. /// 1.1.1 Поиск плавающего представления: иногда не отображается заголовок /// из-за чего невозможно сразу определить окно, тогда проверяются потомки окон, /// которые могут содержать заголовок родительского окна. Если не найдены заголовки, /// то переходим к 1.2 (значит плавающего представления нет). /// 1.2 Поиск закрепленного представления: через GetDlgItem для всех дочерних /// окон (GetChildWindows) приложения Eplan по DlgItemId (0x32C8 - диалог). /// Если окно найдено, то переходим к 4, иначе к 2. /// 2 Симулируем нажатие пункта меню (Сервисные программы -> /// Изделие -> Навигатор основных данных изделий - 35357) /// для его отображения. /// 3 Повторяем поиск окна (1.1, 1.1.1 и 1.2). Если окно не найдено выводим /// сообщение об ошибке, завершаем редактирование, иначе к 4. /// 4 Скрываем панель с элементами управления Eplan'а /// (GetDlgItem, 0x3E6 - родительская панель, ShowWindow). /// 5. Переносим на найденное окно свои элементы (SetParent) и подгоняем /// из размеры и позицию. /// 6. Устанавливаем свой хук для найденного окна (для изменения размеров /// своих элементов, сохранения изменений при закрытии и отключения хука). /// </summary> public void ShowDlg() { System.Diagnostics.Process oCurrent = System.Diagnostics.Process.GetCurrentProcess(); const int wndWmCommand = 35093; // Идентификатор команды вызова окна "Штекеры" if (modeIsShown == true) { if (PI.IsWindowVisible(wndModeVisibilePtr) == false) { PI.SendMessage(oCurrent.MainWindowHandle, (uint)PI.WM.COMMAND, wndWmCommand, 0); return; } return; } string windowName = "Штекеры"; IntPtr res = PI.FindWindowByCaption( IntPtr.Zero, windowName); //1.1 if (res != IntPtr.Zero) { var resList = PI.GetChildWindows(res); if (resList.Count > 0) { wndHandle = PI.GetParent(resList[0]); dialogHandle = resList[0]; wndModeVisibilePtr = dialogHandle; // Сохраняем дескриптор окна. } } else { StringBuilder stringBuffer = new StringBuilder(200); //1.1.1 List <IntPtr> mainWindowChilds = PI.GetChildWindows(PI.GetDesktopWindow()); foreach (IntPtr mainWindowChild in mainWindowChilds) { PI.GetWindowText(mainWindowChild, stringBuffer, stringBuffer.Capacity); if (stringBuffer.ToString().Contains(windowName) == false && stringBuffer.ToString().Contains("EPLAN") == false) { List <IntPtr> windowChilds = PI.GetChildWindows(mainWindowChild); foreach (IntPtr windowChild in windowChilds) { PI.GetWindowText(windowChild, stringBuffer, stringBuffer.Capacity); if (stringBuffer.ToString().Contains(windowName) == true) { if (PI.IsWindowVisible(windowChild) == true) { // Если нашел в потомке название, беру родительское окно и работаю с ним var resList = PI.GetChildWindows(mainWindowChild); if (resList.Count > 0) { dialogHandle = resList[0]; res = dialogHandle; wndModeVisibilePtr = dialogHandle; // Сохраняем дескриптор окна. break; } } } } } } List <IntPtr> resW = PI.GetChildWindows(oCurrent.MainWindowHandle); //1.2 foreach (IntPtr panel in resW) { PI.GetWindowText(panel, stringBuffer, stringBuffer.Capacity); if (stringBuffer.ToString().Contains(windowName) == true) { if (PI.IsWindowVisible(panel) == true) { var resList = PI.GetChildWindows(panel); if (resList.Count > 0) { dialogHandle = resList[0]; res = dialogHandle; wndModeVisibilePtr = dialogHandle; // Сохраняем дескриптор окна. break; } } } } if (res == IntPtr.Zero) { PI.SendMessage(oCurrent.MainWindowHandle, (uint)PI.WM.COMMAND, wndWmCommand, 0); //2 res = PI.FindWindowByCaption( IntPtr.Zero, windowName); //3 if (res != IntPtr.Zero) { var resList = PI.GetChildWindows(res); if (resList.Count > 0) { dialogHandle = resList[0]; wndHandle = PI.GetParent(resList[0]); wndModeVisibilePtr = dialogHandle; // Сохраняем дескриптор окна. } } else { mainWindowChilds = PI.GetChildWindows(PI.GetDesktopWindow()); foreach (IntPtr mainWindowChild in mainWindowChilds) { PI.GetWindowText(mainWindowChild, stringBuffer, stringBuffer.Capacity); if (stringBuffer.ToString().Contains(windowName) == false && stringBuffer.ToString().Contains("EPLAN") == false) { List <IntPtr> windowChilds = PI.GetChildWindows(mainWindowChild); foreach (IntPtr windowChild in windowChilds) { PI.GetWindowText(windowChild, stringBuffer, stringBuffer.Capacity); if (stringBuffer.ToString().Contains(windowName) == true) { // Если нашел в потомке название, беру родительское окно и работаю с ним var resList = PI.GetChildWindows(mainWindowChild); if (resList.Count > 0) { dialogHandle = resList[0]; wndModeVisibilePtr = dialogHandle; // Сохраняем дескриптор окна. break; } } } } } resW = PI.GetChildWindows(oCurrent.MainWindowHandle); foreach (IntPtr panel in resW) { PI.GetWindowText(panel, stringBuffer, stringBuffer.Capacity); if (stringBuffer.ToString().Contains(windowName) == true) { var resList = PI.GetChildWindows(panel); if (resList.Count > 0) { dialogHandle = resList[0]; wndModeVisibilePtr = dialogHandle; // Сохраняем дескриптор окна. break; } } } if (dialogHandle == IntPtr.Zero) { MessageBox.Show("Не удалось найти окно!"); return; } } } } var panelList = PI.GetChildWindows(dialogHandle); //4 if (panelList.Count > 0) { panelPtr = panelList[0]; } if (panelPtr == IntPtr.Zero) { MessageBox.Show("Не удалось скрыть окно!"); return; } PI.ShowWindow(panelPtr, 0); this.Controls.Clear(); modesTreeViewAdv.Show(); PI.SetParent(modesTreeViewAdv.Handle, dialogHandle); //5 PI.SetParent(toolStrip.Handle, dialogHandle); IntPtr dialogPtr = PI.GetParent(modesTreeViewAdv.Handle); PI.RECT rctDialog; PI.RECT rctPanel; PI.GetWindowRect(dialogPtr, out rctDialog); PI.GetWindowRect(panelPtr, out rctPanel); int w = rctDialog.Right - rctDialog.Left; int h = rctDialog.Bottom - rctDialog.Top; toolStrip.Location = new Point(0, 0); modesTreeViewAdv.Location = new Point(0, 0 + toolStrip.Height); toolStrip.Width = w; modesTreeViewAdv.Width = w; modesTreeViewAdv.Height = h - toolStrip.Height; uint pid = PI.GetWindowThreadProcessId(dialogHandle, IntPtr.Zero); //6 dialogHookPtr = PI.SetWindowsHookEx(PI.HookType.WH_CALLWNDPROC, dialogCallbackDelegate, IntPtr.Zero, pid); PI.SetWindowText(dialogHandle, caption); PI.SetWindowText(wndHandle, caption); modeIsShown = true; }
/// <summary> /// Discover the preferred size of the element. /// </summary> /// <param name="context">Layout context.</param> public override Size GetPreferredSize(ViewLayoutContext context) { Size preferredSize = Size.Empty; // We need an owning form to perform calculations if (CompOwnerForm != null) { // We only have size if custom chrome is being used with composition if (CompOwnerForm.ApplyCustomChrome && CompOwnerForm.ApplyComposition) { try { // Create structure that will be populated by call to WM_GETTITLEBARINFOEX PI.TITLEBARINFOEX tbi = new PI.TITLEBARINFOEX(); tbi.cbSize = (uint)Marshal.SizeOf(tbi); // Ask the window for the title bar information PI.SendMessage(CompOwnerForm.Handle, PI.WM_.GETTITLEBARINFOEX, IntPtr.Zero, ref tbi); // Find width of the button rectangle int closeWidth = tbi.rcCloseButton.right - tbi.rcCloseButton.left; int helpWidth = tbi.rcHelpButton.right - tbi.rcHelpButton.left; int minWidth = tbi.rcMinimizeButton.right - tbi.rcMinimizeButton.left; int maxWidth = tbi.rcMaximizeButton.right - tbi.rcMaximizeButton.left; int clientWidth = CompOwnerForm.ClientSize.Width; int clientScreenRight = CompOwnerForm.RectangleToScreen(CompOwnerForm.ClientRectangle).Right; int leftMost = clientScreenRight; // Find the left most button edge (start with right side of client area) if ((closeWidth > 0) && (closeWidth < clientWidth)) { leftMost = Math.Min(leftMost, tbi.rcCloseButton.left); } if ((helpWidth > 0) && (helpWidth < clientWidth)) { leftMost = Math.Min(leftMost, tbi.rcHelpButton.left); } if ((minWidth > 0) && (minWidth < clientWidth)) { leftMost = Math.Min(leftMost, tbi.rcMinimizeButton.left); } if ((maxWidth > 0) && (maxWidth < clientWidth)) { leftMost = Math.Min(leftMost, tbi.rcMaximizeButton.left); } // Our width is the distance between the left most button edge and the right // side of the client area (this space the buttons are taking up). Plus a small // extra gap between the first button and the caption elements to its left. _width = (clientScreenRight - leftMost) + SPACING_GAP; preferredSize.Width = _width; } catch (ObjectDisposedException) { // Asking for the WM_GETTITLEBARINFOEX can cause exception if the form level // Icon has already been disposed. This happens in rare circumstances. } } } return(preferredSize); }