2011-02-07 94 views
3

我有一個wpf子窗口,允許使用DragMove()方法進行拖動。 但是,我需要允許窗口只在其父窗口控件的邊界內被拖動。使窗口在特定邊界內可拖動WPF

任何人都可以提出一種方法來實現這一目標嗎? 謝謝!

回答

5

有兩種方法可以做到這一點。

使用LocationEnded

如果你處理這個事件,您可以更改頂部或左側是所有者窗口的範圍內。 例如

private void Window_LocationChanged(object sender, EventArgs e) 
    { 

     if (this.Left < this.Owner.Left) 
      this.Left = this.Owner.Left; 

     //... also right top and bottom 
     // 
    } 

這是很容易寫,但它違反了,因爲它沒有束縛它只是推窗回拖動窗口的地方,當用戶放開鼠標按鈕的Principle of least astonishment

使用AddHook

正如彼得在an answer指出了一個類似的問題,你可以互操作的Windows消息和阻止拖動窗口。這具有限制實際拖動窗口的的好效果。

下面是一些示例代碼,我把共同爲AddHook方法

開始加載至加鉤

//In Window_Loaded the handle is there (earlier its null) so this is good time to add the handler 

    private void Window_Loaded(object sender, RoutedEventArgs e) 
    { 

     WindowInteropHelper helper = new WindowInteropHelper(this); 
     HwndSource.FromHwnd(helper.Handle).AddHook(HwndSourceHookHandler); 
    } 

在你只想尋找移動或移動消息處理函數中的窗口。然後你會看到lParam矩形,看看它是否超出界限。如果是這樣,您需要更改lParam矩形的值並將其重新編組。爲了簡潔起見,我只做了左側。你仍然需要寫出正確的,頂部和底部的情況。

private IntPtr HwndSourceHookHandler(IntPtr hwnd, int msg, IntPtr wParam, 
    IntPtr lParam, ref bool handled) 
     { 


const int WM_MOVING = 0x0216; 
     const int WM_MOVE = 0x0003; 


     switch (msg) 
     { 
      case WM_MOVING: 
       { 


        //read the lparm ino a struct 

        MoveRectangle rectangle = (MoveRectangle)Marshal.PtrToStructure(
         lParam, typeof(MoveRectangle)); 


        // 

        if (rectangle.Left < this.Owner.Left) 
        { 
         rectangle.Left = (int)this.Owner.Left; 
         rectangle.Right = rectangle.Left + (int)this.Width; 
        } 



        Marshal.StructureToPtr(rectangle, lParam, true); 

        break; 
       } 
      case WM_MOVE: 
       { 
        //Do the same thing as WM_MOVING You should probably enacapsulate that stuff so don'tn just copy and paste 

        break; 
       } 


     } 

     return IntPtr.Zero; 

    } 

該結構的lParam的

[StructLayout(LayoutKind.Sequential)] 
    //Struct for Marshalling the lParam 
    public struct MoveRectangle 
    { 
     public int Left; 
     public int Top; 
     public int Right; 
     public int Bottom; 

    } 

最後要注意,你需要弄清楚如果子窗口被允許比父窗口做大做什麼。

+0

非常感謝康拉德。我會試試這個,讓你知道。 – Dan 2011-02-08 16:32:38