2010-11-08 78 views
3

我想使用的setparent API通過PInvoke的設置childForm爲主體的Excel窗口的子:問題定位窗口()

Form childForm = new MyForm(); 
IntPtr excelHandle = (IntPtr) excelApplication.Hwnd; 
SetParent(childForm.Handle, excelHandle); 
childForm.StartPosition = FormStartPosition.Manual; 
childForm.Left = 0; 
childForm.Top = 0; 

正如你可以在上面看到,我的本意也是將孩子放在Excel窗口的左上角。但是,由於某種原因,childForm總是會在某個奇怪的位置結束。

這是什麼,我做錯了?

+1

你是一個有點晚了設置這些屬性。訪問句柄屬性是創建窗口的內容。 – 2010-11-08 13:50:38

回答

0

嘗試一些事情,診斷問題:

  • 將斷點設置左 和頂部後,不要左和上讀數爲零?
  • 最後調用SetParent。
  • 制定一個方法,再次設置Left和Top ,然後BeginInvoke該方法。
  • 確保你的子窗口真的是 這個孩子。要執行此操作,請撥打 ShowDialog,然後嘗試單擊 父窗口。確保窗口 防止焦點到父窗口。
1

這取決於你的ShowDialog調用我相信。如果您在沒有父級參數的情況下調用ShowDialog,則會重置父級。

您可以創建一個實現IWin32Window並將HWND返回給excel的包裝類。然後你可以將它傳遞給childForm的ShowDialog調用。

您也可以使用GetWindowPos查詢excel應用程序的位置,然後相應地設置childForm。

5

當使用一種形式,是目前桌面的孩子在SetParent(換言之,一個沒有父母 集),您必須設置WS_CHILD風格和刪除WS_POPUP風格。 (請參閱MSDN條目的註釋部分。)Windows要求所有擁有的窗口具有WS_CHILD樣式集。這也可能導致左側屬性和頂部屬性報告/設置錯誤的值,因爲表單不知道它是誰。您可以通過SetParent後調用SetWindowLong解決這個問題,但你嘗試設置位置之前:

//Remove WS_POPUP style and add WS_CHILD style 
const UInt32 WS_POPUP = 0x80000000; 
const UInt32 WS_CHILD = 0x40000000; 
int style = GetWindowLong(this.Handle, GWL_STYLE); 
style = (style & ~(WS_POPUP)) | WS_CHILD; 
SetWindowLong(this.Handle, GWL_STYLE, style); 
0

假設你知道如何得到你想要設置的Z順序窗口的hwnds,您可以使用此pInvoke:

public stati class WindowsApi 
    { 
    [DllImport("user32.dll")] 
    public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, 
     int X, int Y, int cx, int cy, uint uFlags); 
    } 



    public class WindowZOrderPositioner 
    { 
     public void SetZOrder(IntPtr targetHwnd, IntPtr insertAfter) 
     { 
      IntPtr nextHwnd = IntPtr.Zero; 

      WindowsAPI.SetWindowPos(targetHwnd, insertAfter, 0, 0, 0, 0, SetWindowPosFlags.NoMove | SetWindowPosFlags.NoSize | SetWindowPosFlags.NoActivate); 
    } 
7

雖然這裏的所有答案都表明完全符合邏輯的方法,但它們都不適合我。然後我嘗試了MoveWindow。出於某種原因,我不明白,它做了這項工作。

下面的代碼:

[DllImport("user32.dll", SetLastError = true)] 
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); 

... 

Form childForm = new MyForm(); 
IntPtr excelHandle = (IntPtr) excelApplication.Hwnd; 
SetParent(childForm.Handle, excelHandle); 
MoveWindow(childForm.Handle, 0, 0, childForm.Width, childForm.Height, true); 
+0

+1這是我建議嘗試的下一件事。您正在進行非託管API調用以設置窗口的父級,因此託管代碼使用的例程更改窗口位置的例程很可能不起作用。我很高興解決了你的問題,但是你仍然應該確保窗口樣式(添加'WM_CHILD'和刪除'WM_POPUP')正確設置,就像我在前面的回答中所提到的那樣,以防止將來出現任何問題並保持一致文檔。 – 2010-11-10 05:21:18

+0

是的科迪,我確定我設置了這些樣式。非常感謝你的幫助。 – 2010-11-10 07:30:55

+0

這應該是被接受的答案。它拯救了我的一天。 – 2017-08-29 14:42:00