2008-10-17 2 views
6

Мое приложение является исполняемым vb6, но некоторые новые формы в системе написаны на C#. Я хотел бы иметь возможность установить свойство владельца формы C# с помощью дескриптора в основное окно приложения, так что диалоги остаются сверху, когда вы перемещаетесь между моим приложением и другими приложениями.Могу ли я получить поведение установки владельца формы WinForms с помощью hwnd/NativeWindow?

Я могу получить hwnd основного окна приложения. Я не уверен, что я могу сделать оттуда?


UPDATE 20 Окт '08 в 17:06:

Скотт,

Спасибо за ответ. Я упустил из виду, что параметр метода Show/ShowDialog не был типа Form - я искал только свойство Owner.

Я немного изменил код, который я использую из вышеперечисленного, - у нас есть компонент, который в основном загружает наши формы и вызывает ShowDialog. Мой код выглядит следующим образом:

Form launchTarget = FormFactory.GetForm(xxx); // psuedo-code for generic form loader 
launchTarget.StartPosition = FormStartPosition.CenterParent; 
IWin32Window parentWindow = GetWindowFromHwnd(hwnd); 

launchTarget.ShowDialog(parentWindow); 

GetWindowFromHwnd является метод обернутой версии коды:

private IWin32Window GetWindowFromHost(int hwnd) 
{ 
    IWin32Window window = null; 
    IntPtr handle = new IntPtr(hwnd); 

    try 
    { 
     NativeWindow nativeWindow = new NativeWindow(); 
     nativeWindow.AssignHandle(handle); 
     window = nativeWindow; 
    } 
    finally 
    { 
     handle = IntPtr.Zero; 
    } 

    return window; 
} 

К сожалению, это не делает то, что я надеялся. Форма отображается модально, но она не отображается в правильном положении и не остается на вершине, когда я убираюсь и возвращаюсь в родительское окно. Наши модалы не отображают задачи на панели задач, поэтому окно, казалось бы, «исчезает» (хотя оно все еще присутствует в списке окон Alt-Tab). Это означает, что у меня может не быть подходящего hwnd. Если у вас есть другие предложения, ответьте пожалуйста. Еще раз спасибо.


UPDATE 10 Нояб '08 в 16:25

One следить за замечание - Если вы фактор его в вызове метода в Try /, наконец, как во 2-й пост Скотта, призыв в блоке, наконец, должно быть:

parentWindow.ReleaseHandle(); 
+0

Скотт - извините за долгую задержку, получил тягу к другим вещам. Ваш оригинальный представленный ответ отлично работает. Мне просто нужно было передать NativeWindow через ShowDialog вместо установки Form.Owner. Моя другая проблема заключалась в том, что код вызова не передавал правильный hWnd в первую очередь. Спасибо – mcw0933 2008-10-30 20:55:38

ответ

9

Так вы вызываете класс Form C# Windows из VB6, который означает, что вы, вероятно, используют либо Show() или ShowDialog(), правильно? Оба этих метода также принимают параметр IWin32Window, который просто определяет объект, который возвращает свойство IntPtr с именем Handle.

Итак, вам нужно добавить перегруженный конструктор (или метод ShowDialog) для ваших классов Windows Forms, которые принимают параметр long в качестве параметра, чтобы вы могли передать hbdb VB6 в форму. После внутри кода C# вам нужно создать IntPtr из hwnd и назначить его объекту NativeWindow, а затем передать это как владельцу.

Что-то вроде этого должны работы, хотя это непроверенные:

public DialogResult ShowDialog(long hwnd) 
{ 
    IntPtr handle = new IntPtr(hwnd); 
    try 
    { 
     NativeWindow nativeWindow = new NativeWindow(); 

     nativeWindow.AssignHandle(handle); 
     return this.ShowDialog(nativeWindow); 
    } 
    finally 
    { 
     handle = IntPtr.Zero; 
    } 
} 
2

Это слишком долго, чтобы получить возможность отправлять как комментарий ...

Я думаю, что проблема, которую вы используете, чтобы это вы завернули код, который я представил в перегрузке ShowDialog.Если вы следите за тем, что делает ваш код GetWindowFromHost, он выполняет следующие шаги:

  1. Создает новый IntPtr из предоставленного hwnd.
  2. Создает новый объект NativeWindow и назначает его дескриптором IntPtr.
  3. Устанавливает IntPtr (в блоке finally) как IntPtr.Zero.

Я думаю, что это последний блок, который вызывает у вас проблемы. В моем коде блок finally будет работать после завершения вызова this.ShowDialog(nativeWindow). В этот момент ручка (IntPtr) больше не использовалась. В вашем коде вы возвращаете IWin32Window, который все равно должен содержать ссылку на этот IntPtr, который в то время, когда вы вызываете launchTarget.ShowDialog(parentWindow), является IntPtr.Zero.

Попробуйте изменить свой код, чтобы выглядеть следующим образом:

private NativeWindow GetWindowFromHost(int hwnd) 
{ 
    IntPtr handle = new IntPtr(hwnd); 
    NativeWindow nativeWindow = new NativeWindow(); 
    nativeWindow.AssignHandle(handle); 
    return window; 
} 

А затем изменить код вызова выглядеть следующим образом:

Form launchTarget = FormFactory.GetForm(xxx); // psuedo-code for generic form 
loaderlaunchTarget.StartPosition = FormStartPosition.CenterParent; 
NativeWindow parentWindow = GetWindowFromHwnd(hwnd); 

try 
{ 
    launchTarget.ShowDialog(parentWindow); 
} 
finally 
{ 
    parentWindow.DestroyHandle(); 
} 

Эти изменения должны работать, но опять-таки это не тестировалась.

Смежные вопросы