2010-11-08 3 views
3

Я пытаюсь установить childForm как ребенок главного окна Excel с помощью SetParent API через PInvoke:Проблема окно позиционирования при использовании SetParent()

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

Вы немного опоздали настройки этих свойств. Доступ к свойству Handle - это то, что создает окно. –

ответ

0

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

  • Поставьте точку останова после установки слева и Top, не слева и сверху прочитать ноль?
  • Call SetParent последний.
  • Сделайте метод, который снова устанавливает Left и Top , и BeginInvoke метод.
  • Убедитесь, что ваше дочернее окно действительно ребенок. Для этого вызовите ShowDialog и попробуйте щелкнуть родительское окно . Убедитесь, что окна препятствуют фокусу родительскому окну.
1

Это зависит от вашего вызова ShowDialog, которому я верю. Если вы вызываете ShowDialog без родительского пареметра, родитель сбрасывается.

Вы можете создать класс-оболочку, который реализует IWin32Window и возвращает HWND, чтобы преуспеть. Затем вы можете передать это вызову ShowDialog childForm.

Вы также можете запросить позицию приложения excel с помощью GetWindowPos и ​​затем соответствующим образом установить childForm.

5

При использовании SetParent на форме, которая в настоящее время ребенок на рабочем столе (другими словами, один без набора родительского ), вы должны установить WS_CHILD стиль и удалить WS_POPUP стиль. (См. Раздел «Примечания» в записи MSDN.) Windows требует, чтобы все принадлежащие окнам имели набор WS_CHILD. Это также может привести к тому, что левое и верхнее свойства будут сообщать/устанавливать неправильные значения, потому что форма не знает, кто это папа. Вы можете исправить это с помощью вызова SetWindowLong после SetParent, но, прежде чем пытаться установить местоположение:

//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

Предполагая, что вы знаете, как получить hwnds из окон, которые вы хотите установить Z-порядок, вы можете использовать это 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') установлены правильно, как я упоминал в своем предыдущем ответе, чтобы предотвратить любые будущие проблемы и оставаться в соответствии с документации. –

+0

Да, Коди, я убедился, что установил эти стили. Большое спасибо за вашу помощь. –

+0

Это должен быть принятый ответ. Это спасло мой день. –