Прикрепите окно формы к другому окну в С#
Я хочу привязать форму к другому окну (другого процесса). Я пытаюсь сделать это, используя
[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]()
Ответы
Ответ 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 Привет, парень, я не уверен, исправили ли вы проблему, но я нашел решение для этого.
Для меня проблема заключалась в прозрачности основной формы, которую вы хотите в другой форме.
Просто отключите прозрачность, и она должна работать.