Подтвердить что ты не робот

Прикрепите окно формы к другому окну в С#

Я хочу привязать форму к другому окну (другого процесса). Я пытаюсь сделать это, используя

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

setParentWindow(myWindowHwnd, newParentHwnd);

При этом моя форма присоединяется, но также невидима. Вопрос "Прикрепить окно.." разрешает эту проблему для окна WPF, в основном используя

HwndSourceParameters parameters = new HwndSourceParameters();
...
HwndSource src = new HwndSource(parameters);

Я попытался перенести это в свою форму, но я не могу этого сделать (например, как обрабатывать src.RootVisual = (Visual)window.Content;? → Полный источник).

Еще один комментарий говорит, мне нужно изменить стиль окна:

По соображениям совместимости SetParent не изменяет стили окна WS_CHILD или WS_POPUP окна, родительский элемент которого изменяется. Поэтому, если hWndNewParent равно NULL, вы также должны очистить бит WS_CHILD и установить стиль WS_POPUP после вызова SetParent. И наоборот, если hWndNewParent не является NULL, а окно ранее было дочерним элементом рабочего стола, вы должны очистить стиль WS_POPUP и установить стиль WS_CHILD перед вызовом SetParent.

Здесь я пропускаю соответствующий API для этого, могу ли я сделать это непосредственно с С# или мне снова использовать другой DllImport?

Хорошее или злое - API-интерфейс win32 API-интерфейса SetParent() между различными процессами рекомендует не устанавливать окна в разных процессах, но, по крайней мере, я хочу попробовать.

Вопрос:

Что мне нужно сделать, чтобы открыть окно формы? Если подход с WS_Child является правильным, как бы установить его? Или это WPF подход, но как бы применить его к форме Windows?

- Результаты (позже добавлены) -

Изменить стиль Windows другого приложения с помощью winAPI показывает, как изменить стиль из С#/PInvoke

Найти все стили windows здесь, синтаксис С# внизу.

- Выводы из-за обсуждения с Аланом -

Я запускал свою программу на Win XP для перекрестной проверки (см. ответ Алана ниже и комментарии). По крайней мере, я сейчас что-то вижу. Поскольку я добавил координаты как примеры Алана, мое окно теперь светится в блокноте, перемещаясь по другому окну возле левого верхнего угла. Вы все еще можете видеть текст, набранный в блокноте, как наложение. В Win 7 (32) я вообще ничего не вижу.

  • Теперь мне нужно выяснить, можно ли это написать стабильным образом, появляясь и на Win 7.
  • Тем не менее, я все еще не могу щелкнуть по кнопкам в моей форме, также нужно решить.

WinXP WinForm attached to notepad

4b9b3361

Ответ 1

Вот рабочий пример. Приложение для хостинга - это простое приложение WinForms с пустой формой (не включенной здесь), в то время как "гостевое приложение" имеет основную форму (код, приведенный ниже), с некоторыми элементами управления, включая тестовую кнопку для отображения сообщения после смены гостя родитель формы.

К этому относятся также обычные предостережения, связанные с вопросом OP.

public partial class GuestForm: Form
{
  [DllImport("user32.dll")]
  public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

  [DllImport("user32.dll")]
  public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

  [DllImport("user32.dll", SetLastError = true)]
  private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

  public static int GWL_STYLE = -16;
  public static int WS_CHILD = 0x40000000; 

  public GuestForm()
  {
    InitializeComponent();
  }

  private void button1_Click(object sender, EventArgs e)
  {
    MessageBox.Show("done");
  }

  private void button2_Click(object sender, EventArgs e)
  {
    Process hostProcess = Process.GetProcessesByName("HostFormApp").FirstOrDefault();
    if (hostProcess != null)
    {
      Hide();
      FormBorderStyle = FormBorderStyle.None;
      SetBounds(0, 0, 0, 0, BoundsSpecified.Location);

      IntPtr hostHandle = hostProcess.MainWindowHandle;
      IntPtr guestHandle = this.Handle;
      SetWindowLong(guestHandle, GWL_STYLE, GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD);
      SetParent(guestHandle, hostHandle);

      Show();
    }
  }
}

Ответ 2

@Horst Walter Привет, парень, я не уверен, исправили ли вы проблему, но я нашел решение для этого.

Для меня проблема заключалась в прозрачности основной формы, которую вы хотите в другой форме.

Просто отключите прозрачность, и она должна работать.