2010-10-26 37 views
40

Tôi có một ứng dụng WPF và tôi cần biết cách căn giữa cửa sổ wain theo chương trình (không phải trong XAML).Làm thế nào để bạn đặt chính giữa cửa sổ chính của mình trong WPF?

Tôi cần có thể thực hiện việc này khi khởi động và để đáp ứng với các sự kiện nhất định của người dùng. Nó phải được tính toán động vì kích thước cửa sổ chính nó là động.

Cách đơn giản nhất để thực hiện việc này là gì? Dưới mã Win32 cũ, tôi sẽ gọi các hàm số liệu hệ thống và làm việc tất cả. Có phải đó vẫn là cách nó được thực hiện hoặc là có một chức năng đơn giản CenterWindowOnScreen() tôi bây giờ có thể gọi.

Trả lời

61
private void CenterWindowOnScreen() 
{ 
    double screenWidth = System.Windows.SystemParameters.PrimaryScreenWidth; 
    double screenHeight = System.Windows.SystemParameters.PrimaryScreenHeight; 
    double windowWidth = this.Width; 
    double windowHeight = this.Height; 
    this.Left = (screenWidth/2) - (windowWidth/2); 
    this.Top = (screenHeight/2) - (windowHeight/2); 
} 

Bạn có thể sử dụng phương pháp này để đặt vị trí cửa sổ vào giữa màn hình của bạn.

+0

tôi sẽ cung cấp cho bạn một cho điều đó nhưng tôi dường như nhớ lại đó là rất nhiều công việc hơn, có tính đến thanh tác vụ tài khoản, v.v. Tuy nhiên, 1 cho 'SystemParameters' và một số mã vì vậy tôi không phải đi ra ngoài để' GetSystemMetrics' bản thân mình. – paxdiablo

+0

Có thể là cách duy nhất để căn giữa lại cửa sổ sau khi thay đổi chương trình cửa sổ Chiều cao và/hoặc Chiều rộng hoặc sau khi vị trí của nó đã bị thay đổi. – azarc3

+7

Điều này chỉ hoạt động nếu bạn có 1 màn hình hoặc nếu tất cả các màn hình của bạn có cùng kích thước – JumpingJezza

3

Là một giải pháp cơ bản, bạn có thể sử dụng tài sản StartupLocation của cửa sổ, đặt nó là một trong các giá trị enum quy định tại System.Windows.WindowStartupLocation liệt kê, có một cho trung tâm của màn hình:

_wpfWindow.StartupLocation = System.Windows.WindowStartupLocation.CenterScreen; 

Thật không may nó không phải luôn luôn khá đơn giản; bạn cần tính đến nhiều màn hình, thanh tác vụ, vv Tùy chọn "CenterScreen" mở cửa sổ ở giữa màn hình có con trỏ chuột. Xem this SO question để biết nhiều thông tin hoặc tham khảo api.

78

Vâng, đối với thời gian khởi động, bạn có thể thiết lập các startup location:

window.WindowStartupLocation = WindowStartupLocation.CenterScreen; 

Sau đó, bạn sẽ cần phải truy vấn nó. Thông tin (ít nhất là cho màn hình chính) có sẵn qua SystemParameters.PrimaryScreenWidth/Chiều cao.

20
Rect workArea = System.Windows.SystemParameters.WorkArea; 
this.Left = (workArea.Width - this.Width)/2 + workArea.Left; 
this.Top = (workArea.Height - this.Height)/2 + workArea.Top; 

này sẽ đưa vào tài khoản kích thước thanh công cụ (bằng cách sử dụng System.Windows.SystemParameters.WorkArea) và vị trí (bằng cách thêm workArea.LeftworkArea.Top)

+6

Đây phải là câu trả lời được chấp nhận. – amnesia

+3

Điều này chỉ hoạt động nếu bạn có 1 màn hình, hoặc nếu tất cả màn hình của bạn có cùng kích thước – JumpingJezza

53

Không phải là nó cũng giống như đơn giản để thiết

WindowStartupLocation="CenterScreen" 

Trong Định nghĩa XAML cho cửa sổ.

+2

Tốt cho vị trí khởi động nhưng, như tôi đã chỉ ra trong câu hỏi, tôi cũng muốn thực hiện việc này từ bên trong chương trình khi cửa sổ thay đổi kích thước. – paxdiablo

+0

Xin lỗi, có bạn đã đúng. Tôi tự hỏi tại sao rất nhiều người dường như đi cho giải pháp không rõ ràng. :-) – naskew

6

Trong các yếu tố cửa sổ chỉ cần thêm này cặp thuộc tính-giá trị: WindowStartupLocation = "CenterScreen"

+3

"Lập trình, _not_ trong XAML". Trong mọi trường hợp, đây không phải là bản sao câu trả lời của Naskew sao? – paxdiablo

+0

Cảm ơn bạn đã trả lời câu trả lời này! Tôi đang làm việc trong một cửa hàng nơi chúng tôi làm mọi thứ trong xaml. Cách "lập trình" là thông minh, nhưng không phải là cách WPF. – James

5

Trong trường hợp bạn cần phải vẽ một cửa sổ trong một môi trường màn hình nhiều. Tôi đã thực hiện một lớp tĩnh nơi phương pháp sau đây có thể được tái sử dụng:

public static void PostitionWindowOnScreen(Window window, double horizontalShift = 0, double verticalShift = 0) 
{ 
    Screen screen = Screen.FromHandle(new System.Windows.Interop.WindowInteropHelper(window).Handle); 
    window.Left = screen.Bounds.X + ((screen.Bounds.Width - window.ActualWidth)/2) + horizontalShift; 
    window.Top = screen.Bounds.Y + ((screen.Bounds.Height - window.ActualHeight)/2) + verticalShift;   
} 

Trong constructor của Window bây giờ chỉ cần gọi phương thức:

this.Loaded += (s, a) => Globals.PostitionWindowOnScreen(this, 0, 0) 
+0

Vì lý do nào đó, phương pháp này đặt vị trí cửa sổ của tôi cách 20 pixel so với đầu trang? Điều này làm việc tốt hơn cho tôi so với câu trả lời đã chọn. – Andy

0

Nếu bạn nó được tối đa cùng một lúc
this.WindowState = System.Windows.WindowState.Tối đa hóa;

9

tôi phải kết hợp một vài trong số những câu trả lời để trang trải tất cả các căn cứ trong trường hợp của tôi:

  • Peter's method để tìm màn hình hiện tại - chứ không phải chỉ là màn hình chính (nghiêm túc những người có chỉ 1 màn hình tại nơi làm việc nữa?)
  • @Wild_A's method để sử dụng workarea thay vì screen bounds để tính đến khoảng trống cho thanh tác vụ.
  • Tôi phải thêm tỷ lệ DPI, cụ thể cho máy tính bảng hiển thị 1280x800 là 1024x640, nhưng điều này rất hữu ích để bao gồm các trường hợp cạnh, mà tôi đã tìm thấy câu trả lời cho here. Lưu ý biến dpiScaling là null nếu gọi trên nạp đầu tiên trước khi các giao diện người dùng được hiển thị (explained here)
//get the current monitor 
Screen currentMonitor = Screen.FromHandle(new System.Windows.Interop.WindowInteropHelper(Application.Current.MainWindow).Handle); 

//find out if our app is being scaled by the monitor 
PresentationSource source = PresentationSource.FromVisual(Application.Current.MainWindow); 
double dpiScaling = (source != null && source.CompositionTarget != null ? source.CompositionTarget.TransformFromDevice.M11 : 1); 

//get the available area of the monitor 
Rectangle workArea = currentMonitor.WorkingArea; 
var workAreaWidth = (int)Math.Floor(workArea.Width*dpiScaling); 
var workAreaHeight = (int)Math.Floor(workArea.Height*dpiScaling); 

//move to the centre 
Application.Current.MainWindow.Left = (((workAreaWidth - (myWindowWidth * dpiScaling))/2) + (workArea.Left * dpiScaling)); 
Application.Current.MainWindow.Top = (((workAreaHeight - (myWindowHeight * dpiScaling))/2) + (workArea.Top * dpiScaling)); 

nơi myWindowWidthmyWindowHeight là các biến tôi sử dụng để tự thiết lập kích thước của cửa sổ trước đó.

+0

Tôi chỉ có một màn hình - 40 "với độ phân giải 4K. Không thể biết tại sao bất cứ ai cần nhiều hơn một (hoặc những người sẽ có nhiều không gian bàn hơn).) – CramerTV

+1

@CramerTV Ha true! Lần họ thay đổi :) Mặc dù vẫn còn có liên quan để cắm vào một màn hình cho trình diễn – JumpingJezza

+0

Kết hợp tuyệt vời của hai câu trả lời, chỉ cần sử dụng nó và nó hoạt động hoàn hảo.Và có tôi sử dụng 3 màn hình một với Visual Studio, một với pdf (ebook), một với stackoverflow/outlook – JohnChris

0

Dựa trên câu trả lời @Wild_A Tôi chỉ đăng ký sự kiện SizeChanged, và thêm vào xử lý sự kiện này:

private void Window_SizeChanged(object sender, SizeChangedEventArgs e) 
{ 
    try 
    { 
     Rect workArea = SystemParameters.WorkArea; 
     this.Left = (workArea.Width - e.NewSize.Width)/2 + workArea.Left; 
     this.Top = (workArea.Height - e.NewSize.Height)/2 + workArea.Top; 
    } 
    catch (Exception ex) { ... Handel exception; } 
} 
Các vấn đề liên quan