2008-10-17 37 views
6

我的應用程序是VB6的可執行文件,但系統中的一些較新的形式寫在C#。我希望能夠使用主應用程序窗口的句柄來設置C#窗體的Owner屬性,以便在我的應用程序和其他應用程序之間來回切換時,對話框保持最前端。我可以使用hwnd/NativeWindow獲取設置WinForms窗體所有者的行爲嗎?

我能得到應用程序主窗口的HWND。我不確定我能從那裏做什麼?


UPDATE年10月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; 
} 

不幸的是,這是不是在做什麼我所希望的。表單不會以模態方式顯示,但它不會顯示在正確的位置,當我退回到父窗口時,它也不會顯示在最前面。我們的模態不會在任務欄中顯示任務,因此該窗口似乎「消失」(儘管它仍存在於替代選項卡窗口列表中)。對我來說這表明我可能沒有正確的hwnd。如果您還有其他建議,請回復。再次感謝。


UPDATE 11月10日08時16:25

一個跟進的話 - 如果您因素出來到一個try /終於,在斯科特的第二後,調用一個方法調用在finally塊應該是:

parentWindow.ReleaseHandle(); 
+0

斯科特 - 抱歉拖延了很長時間,被拉到其他東西。您提交的原始答案效果很好。我只需要通過ShowDialog傳入NativeWindow,而不是設置Form.Owner。我的另一個問題是調用代碼首先不能傳遞正確的hWnd。謝謝 – mcw0933 2008-10-30 20:55:38

回答

9

所以,你在呼喚從VB6一個C#Windows窗體類,您可能正在使用或者Show()ShowDialog()這意味着,正確嗎?這兩種方法都使用IWin32Window參數,該參數只是定義一個返回名爲Handle的IntPtr屬性的對象。

所以......你需要爲你的Windows添加一個重載的構造函數(或ShowDialog方法)形成內搭一件long作爲參數,所以你可以通過HWND到窗體的VB6類。一旦C#代碼裏面,你需要從HWND創建一個IntPtr並將其分配給一個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. 創建從給出的HWND一個新的IntPtr。
  2. 創建一個新的NativeWindow對象並將其句柄指定爲IntPtr。
  3. 將IntPtr(在finally塊中)設置爲IntPtr.Zero。

我認爲這是最後一塊導致你的問題。在我的代碼中,在完成對this.ShowDialog(nativeWindow)的調用之後,finally塊將運行。此時句柄(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(); 
} 

這些變化應該工作,但是這同樣是未經測試。

相關問題