2015-09-27 134 views
4

我想編寫一個停靠在另一個進程中運行的應用程序的WPF應用程序(這是我無法控制的第三方應用程序)。理想情況下,我希望能夠定義應用是在左側還是右側停靠。將WPF窗口附加到另一個進程的窗口

這裏是我想要做的一個例子:

Docked example

我試圖實現以下兩個例子,但沒有成功。

Attach window to window of another process - Button_Click提供了以下錯誤:

error image

Attach form window to another window in C# - Button_Click_1碼頭它的標題欄,但我不能看到整個應用程序:

App docked

以下是代碼:

namespace WpfApplicationTest 
{ 
/// <summary> 
/// Interaction logic for MainWindow.xaml 
/// </summary> 
public partial class MainWindow : Window 
{ 
    [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; 

    [DllImport("user32")] 
    private static extern bool SetWindowPos(
     IntPtr hWnd, 
     IntPtr hWndInsertAfter, 
     int x, 
     int y, 
     int cx, 
     int cy, 
     uint uFlags); 

    private IntPtr _handle; 
    private void SetBounds(int left, int top, int width, int height) 
    { 
     if (_handle == IntPtr.Zero) 
      _handle = new WindowInteropHelper(this).Handle; 

     SetWindowPos(_handle, IntPtr.Zero, left, top, width, height, 0); 
    } 

    public MainWindow() 
    { 
     InitializeComponent(); 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     Process hostProcess = Process.GetProcessesByName("notepad").FirstOrDefault(); 
     IntPtr hostHandle = hostProcess.MainWindowHandle; 

     //MyWindow window = new MyWindow(); 
     this.ShowActivated = true; 

     HwndSourceParameters parameters = new HwndSourceParameters(); 

     parameters.WindowStyle = 0x10000000 | 0x40000000; 
     parameters.SetPosition(0, 0); 
     parameters.SetSize((int)this.Width, (int)this.Height); 
     parameters.ParentWindow = hostHandle; 
     parameters.UsesPerPixelOpacity = true; 
     HwndSource src = new HwndSource(parameters); 

     src.CompositionTarget.BackgroundColor = Colors.Transparent; 
     src.RootVisual = (Visual)this.Content; 
    } 

    private void Button_Click_1(object sender, RoutedEventArgs e) 
    { 
     Process hostProcess = Process.GetProcessesByName("notepad").FirstOrDefault(); 
     if (hostProcess != null) 
     { 
      Hide(); 

      //this.WindowStyle; 

      //new WindowInteropHelper(this).SetBounds(0, 0, 0, 0, BoundsSpecified.Location); 

      //SetWindowPos(new WindowInteropHelper(this).Handle, IntPtr.Zero, 0, 0, 0, 0, 0); 
      SetBounds(0, 0, 0, 0); 

      IntPtr hostHandle = hostProcess.MainWindowHandle; 
      IntPtr guestHandle = new WindowInteropHelper(this).Handle; 

      SetWindowLong(guestHandle, GWL_STYLE, GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD); 
      SetParent(guestHandle, hostHandle); 

      Show(); 
     } 
    } 
} 
+0

你說的 '碼頭' 究竟是什麼意思? –

+0

Dock =連接到 –

+0

的一側您可以嘗試使用短語「snap to」而不是「dock to」來搜索Google。 –

回答

0

你的實現是完全錯誤的,你試圖讓你的窗口作爲你想要捕捉的窗口的子窗口。

我寫了一個小助手類來捕捉另一個窗口的標題,我希望這有助於。

WindowSnapper.cs

public class WindowSnapper 
{ 
    private struct Rect 
    { 
     public int Left { get; set; } 
     public int Top { get; set; } 
     public int Right { get; set; } 
     public int Bottom { get; set; } 

     public int Height 
     { 
      get { return Bottom - Top; } 
     } 

     public static bool operator !=(Rect r1, Rect r2) 
     { 
      return !(r1 == r2); 
     } 

     public static bool operator ==(Rect r1, Rect r2) 
     { 
      return r1.Left == r2.Left && r1.Right == r2.Right && r1.Top == r2.Top && r1.Bottom == r2.Bottom; 
     } 
    } 

    [DllImport("user32.dll")] 
    private static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle); 

    private DispatcherTimer _timer; 
    private IntPtr _windowHandle; 
    private Rect _lastBounds; 
    private Window _window; 
    private string _windowTitle; 

    public WindowSnapper(Window window, String windowTitle) 
    { 
     _window = window; 
     _window.Topmost = true; 
     _windowTitle = windowTitle; 

     _timer = new DispatcherTimer(); 
     _timer.Interval = TimeSpan.FromMilliseconds(10); 
     _timer.Tick += (x, y) => SnapToWindow(); 
     _timer.IsEnabled = false; 
    } 

    public void Attach() 
    { 
     _windowHandle = GetWindowHandle(_windowTitle); 
     _timer.Start(); 
    } 

    public void Detach() 
    { 
     _timer.Stop(); 
    } 

    private void SnapToWindow() 
    { 
     var bounds = GetWindowBounds(_windowHandle); 

     if (bounds != _lastBounds) 
     { 
      _window.Top = bounds.Top; 
      _window.Left = bounds.Left - _window.Width; 
      _window.Height = bounds.Height; 
      _lastBounds = bounds; 
     } 
    } 

    private Rect GetWindowBounds(IntPtr handle) 
    { 
     Rect bounds = new Rect(); 
     GetWindowRect(handle, ref bounds); 
     return bounds; 
    } 

    private IntPtr GetWindowHandle(string windowTitle) 
    { 
     foreach (Process pList in Process.GetProcesses()) 
     { 
      if (pList.MainWindowTitle.Contains(windowTitle)) 
      { 
       return pList.MainWindowHandle; 
      } 
     } 

     return IntPtr.Zero; 
    } 
} 

用例:

public partial class MainWindow : Window 
{ 
    private WindowSnapper _snapper; 

    public MainWindow() 
    { 
     InitializeComponent(); 

     _snapper = new WindowSnapper(this, "Notepad"); 
     _snapper.Attach(); 
    } 
} 
相關問題