2012-05-03 23 views
6

Có cách nào để xác định xem một cửa sổ WPF đang mở có hiển thị trên màn hình được kết nối của máy tính để bàn không? Bằng cách nhìn thấy tôi có nghĩa là hình chữ nhật viền của cửa sổ giao nhau với hình chữ nhật trên màn hình của bất kỳ màn hình nào.Xác định xem một cửa sổ WPF đang mở có hiển thị trên bất kỳ màn hình nào

Tôi cần chức năng này để xác định xem cửa sổ cần được định vị lại vì cấu hình màn hình (giới hạn khu vực làm việc, số giám sát) đã thay đổi giữa lần khởi động lại ứng dụng của tôi (tiết kiệm vị trí cửa sổ).

tôi đã đưa ra mã dưới đây và có vẻ như để làm việc, nhưng nó có một số vấn đề:

  1. Tôi cần phải tham khảo các cửa sổ hình thức.
  2. Tôi cần cài đặt DPI của máy tính để bàn và chuyển đổi các cửa sổ tạo các pixel thực tế thành pixel ảo WPF.
  3. Tôi cần một cá thể Hình ảnh rõ ràng đã được hiển thị để thực hiện phép chuyển đổi.

Bạn có biết giải pháp loại bỏ một số hoặc tất cả 3 vấn đề ở trên không?

using System.Collections.Generic; 
using System.Linq; 
using System.Windows; 
using System.Windows.Forms; 
using System.Windows.Media; 

internal static class Desktop 
{ 
    private static Size dpiFactor = new Size(1.0, 1.0); 
    private static bool isInitialized; 

    public static IEnumerable<Rect> WorkingAreas 
    { 
     get 
     { 
      return 
       Screen.AllScreens.Select(
        screen => 
        new Rect(
         screen.WorkingArea.Left * dpiFactor.Width, 
         screen.WorkingArea.Top * dpiFactor.Height, 
         screen.WorkingArea.Width * dpiFactor.Width, 
         screen.WorkingArea.Height * dpiFactor.Height)); 
     } 
    } 

    public static void TryInitialize(Visual visual) 
    { 
     if (isInitialized) 
     { 
      return; 
     } 

     var ps = PresentationSource.FromVisual(visual); 
     if (ps == null) 
     { 
      return; 
     } 

     var ct = ps.CompositionTarget; 
     if (ct == null) 
     { 
      return; 
     } 

     var m = ct.TransformToDevice; 
     dpiFactor = new Size(m.M11, m.M22); 
     isInitialized = true; 
    } 
} 

Cách sử dụng của (khởi tạo) Desktop lớp:

private bool IsLocationValid(Rect windowRectangle) 
    { 
     foreach (var workingArea in Desktop.WorkingAreas) 
     { 
      var intersection = Rect.Intersect(windowRectangle, workingArea); 
      var minVisible = new Size(10.0, 10.0); 
      if (intersection.Width >= minVisible.Width && 
       intersection.Height >= minVisible.Height) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 

Cập nhật

Sử dụng màn hình ảo (SystemParameters.VirtualScreen*) không làm việc vì khi sử dụng nhiều màn hình các "máy tính để bàn "không phải là một hình chữ nhật đơn giản. Nó có thể là một đa giác. Sẽ có điểm mù trong màn hình ảo vì

  1. màn hình kết nối có thể có độ phân giải khác nhau
  2. bạn có thể cấu hình vị trí của mỗi màn hình.
+0

http: // stackoverflow.com/questions/2465646/how-do-i-know-what-monitor-a-wpf-cửa sổ-là-trong – Flot2011

+0

Mặc dù câu hỏi từ liên kết đó là khá giống nhau, nó không trả lời câu hỏi của tôi. Tôi đã đề xuất một giải pháp và tôi muốn tìm một cách để khám phá ra khỏi ba vấn đề tôi đã đề cập. – bitbonk

+0

Sau đó, các thư viện WPF và C# tiêu chuẩn không thể giúp bạn. Bạn có thể thử PInvoke, nhưng đó có lẽ là bẩn hơn. Xem câu hỏi này để biết thêm về điều đó: http://stackoverflow.com/questions/1927540/how-to-get-the-size-of-the-current-screen-in-wpf – AkselK

Trả lời

7

Mã chúng tôi sử dụng để thực hiện điều gì đó tương tự sử dụng thông tin từ SystemParameters, cụ thể là SystemParameter.VirtualScreenLeft, Top, Width và Height.

Nếu chúng ta có một lưu vị trí và kích cỡ sau đó chúng tôi xác định nếu cửa sổ là ngoài giới hạn như thế này:

bool outOfBounds = 
    (location.X <= SystemParameters.VirtualScreenLeft - size.Width) || 
    (location.Y <= SystemParameters.VirtualScreenTop - size.Height) || 
    (SystemParameters.VirtualScreenLeft + 
     SystemParameters.VirtualScreenWidth <= location.X) || 
    (SystemParameters.VirtualScreenTop + 
     SystemParameters.VirtualScreenHeight <= location.Y); 
+2

Sử dụng màn hình ảo không hoạt động vì khi sử dụng nhiều màn hình, "màn hình nền" không phải là một hình chữ nhật đơn giản. Sẽ có những điểm mù trong màn hình ảo vì a) màn hình được kết nối có thể có độ phân giải khác nhau và b) bạn có thể định cấu hình vị trí của từng màn hình. – bitbonk

0

Mã này kiểm tra nếu một đầu cửa sổ bên trái góc bên trong ảo hộp Screen (hình chữ nhật bao gồm tất cả các màn hình có sẵn). Nó cũng sẽ chăm sóc các thiết lập đa đối tượng nơi tọa độ có thể là tiêu cực, ví dụ như màn hình chính ở bên phải hoặc ở phía dưới.

bool valid_position = 
SystemParameters.VirtualScreenLeft <= saved_location.X && 
(SystemParameters.VirtualScreenLeft + SystemParameters.VirtualScreenWidth) >= saved_location.X && 
SystemParameters.VirtualScreenTop <= saved_location.Y && 
(SystemParameters.VirtualScreenTop + SystemParameters.VirtualScreenHeight) >= saved_location.Y; 
+2

Sử dụng màn hình ảo không hoạt động vì khi sử dụng nhiều màn hình, "màn hình nền" không phải là một hình chữ nhật đơn giản. Sẽ có những điểm mù trong màn hình ảo vì a) màn hình được kết nối có thể có độ phân giải khác nhau và b) bạn có thể định cấu hình vị trí của từng màn hình. – bitbonk

0

Tôi sử dụng mã này được ghi trong dự án WPF khi khởi động; nó được viết bằng vb.net:

If My.Settings.RememberWindowPositionAndSize Then 
    If My.Settings.winMainWinState > 2 Then My.Settings.winMainWinState = WindowState.Normal 
    If My.Settings.winMainWinState = WindowState.Minimized Then My.Settings.winMainWinState = WindowState.Normal 
    Me.WindowState = My.Settings.winMainWinState 
    If My.Settings.winMainWinState = WindowState.Normal Then 
     Dim winBounds As New System.Drawing.Rectangle(CInt(My.Settings.winMainPosX), CInt(My.Settings.winMainPosY), 
                 CInt(My.Settings.winMainSizeB), CInt(My.Settings.winMainSizeH)) 
     For Each scr As System.Windows.Forms.Screen In System.Windows.Forms.Screen.AllScreens 
      If winBounds.IntersectsWith(scr.Bounds) Then 
       Me.Width = My.Settings.winMainSizeB 
       Me.Height = My.Settings.winMainSizeH 
       Me.Top = My.Settings.winMainPosY 
       Me.Left = My.Settings.winMainPosX 
       Exit For 
      End If 
     Next 
    End If 
End If 

và đây là cùng (quy đổi) mã trong C#

if (My.Settings.RememberWindowPositionAndSize) { 
    if (My.Settings.winMainWinState > 2) 
     My.Settings.winMainWinState = WindowState.Normal; 
    if (My.Settings.winMainWinState == WindowState.Minimized) 
     My.Settings.winMainWinState = WindowState.Normal; 
    this.WindowState = My.Settings.winMainWinState; 

    if (My.Settings.winMainWinState == WindowState.Normal) { 
     System.Drawing.Rectangle winBounds = new System.Drawing.Rectangle(Convert.ToInt32(My.Settings.winMainPosX), Convert.ToInt32(My.Settings.winMainPosY), Convert.ToInt32(My.Settings.winMainSizeB), Convert.ToInt32(My.Settings.winMainSizeH)); 

     foreach (System.Windows.Forms.Screen scr in System.Windows.Forms.Screen.AllScreens) { 
      if (winBounds.IntersectsWith(scr.Bounds)) { 
       this.Width = My.Settings.winMainSizeB; 
       this.Height = My.Settings.winMainSizeH; 
       this.Top = My.Settings.winMainPosY; 
       this.Left = My.Settings.winMainPosX; 
       break; 
      } 
     } 
    } 
} 
Các vấn đề liên quan