2010-07-19 42 views
7

Có thể nhúng cửa sổ bảng điều khiển bên trong cửa sổ WPF không?Nhúng cửa sổ Bảng điều khiển bên trong Cửa sổ WPF

Là một nền tảng nhỏ, lúc đầu, tôi đã cố gắng triển khai cửa sổ bảng điều khiển từ đầu trong WPF, thành công ngoại trừ một vấn đề lớn - nó rất chậm. Xem câu hỏi ở đây:
VT100 Terminal Emulation in Windows WPF or Silverlight

Kể từ đó dường như không là một lựa chọn tôi thay vì nhìn vào lưu trữ một cửa sổ giao diện điều khiển thực tế trong ứng dụng WPF của tôi, mà tôi đã học được cách làm như đã mô tả ở đây:

No output to console from a WPF application?

Và điều đó thật tuyệt, bởi lý tưởng tôi muốn có cửa sổ bảng điều khiển giống như là một phần của phần còn lại của ứng dụng WPF. Tôi biết nó có thể với một ứng dụng WinForms như tôi đã nhìn thấy nó thực hiện, liên quan đến việc sử dụng SetParent Win32 API. Bạn có thể thấy một dự án ví dụ .NET nào đó với dự án này CommandBar nhúng một cửa sổ giao diện điều khiển vào vỏ:

http://www.codeproject.com/KB/cs/commandbar.aspx

Vì vậy, tôi hy vọng nó có thể được thực hiện với WPF là tốt, nhưng tôi không có ý tưởng làm thế nào bạn muốn làm điều đó. Giúp đỡ được nhiều đánh giá cao (cũng có, nếu bạn có bất kỳ giải pháp tuyệt vời cho vấn đề ban đầu của tôi về việc tạo ra một cửa sổ thiết bị đầu cuối từ đầu trong WPF kể từ đó sẽ giải quyết nhu cầu của tôi quá).

UPDATE:

Với sự giúp đỡ giúp đỡ Reed Copsey của tôi đã có thể để có được cửa sổ điều khiển nhúng. Tuy nhiên, tất nhiên nó cần phải được theo kiểu và di chuyển hoặc người nào khác nó chỉ trông giống như một cửa sổ giao diện điều khiển thường xuyên bên trong một cửa sổ WPF. Tôi cần thanh tiêu đề và đường viền lớn bị xóa. Làm nghiên cứu tôi đã tìm ra cách sử dụng API Win32 để làm điều đó như thế này:

uint style = GetWindowLong(ConsoleManager.ConsoleWindowHandle, GWL_STYLE); 
style &= ~(uint)WindowStyles.WS_CAPTION; 
style &= ~(uint)WindowStyles.WS_THICKFRAME; 
style &= ~(uint)WindowStyles.WS_DLGFRAME; 
style &= ~(uint)WindowStyles.WS_POPUP; 
SetWindowLong(ConsoleManager.ConsoleWindowHandle, GWL_STYLE, style); 
MoveWindow(ConsoleManager.ConsoleWindowHandle, 0, 0, (int)WindowsFormsHost.ActualWidth, (int)WindowsFormsHost.ActualHeight, true); 

Tuy nhiên, có một vấn đề lớn. Đối với một số lý do, cửa sổ giao diện điều khiển có một tạo phẩm dựng hình. Nó như thể nó không tự sơn lại ở phía dưới bên trái và phía trên bên phải. Chiều rộng của đồ tạo tác tương tự như chiều rộng của thanh tiêu đề và đường viền dày, và trên thực tế, nếu tôi rời khỏi đường viền dày trong kích thước của phần tạo tác sẽ đi xuống. Nhưng chỉ đơn giản là sơn lại nó sẽ không giúp đỡ vì nó xuất hiện trở lại. Tôi có thể, ví dụ, di chuyển cửa sổ ra khỏi màn hình và ngược lại để sửa chữa nó, nhưng nó lại xuất hiện sớm ngày của riêng mình:

rendering artifact http://img837.imageshack.us/img837/6241/renderissue.png

UPDATE 2: Hiệu quả xảy ra ngay cả khi tôi không cha mẹ nó vào điều khiển WindowsFormsHost. Tất cả những gì tôi cần làm để tái tạo nó là khởi động giao diện điều khiển (sử dụng AllocConsole()) và sau đó loại bỏ thanh tiêu đề của nó bằng SetWindowLong. Đây là một máy win7.

CẬP NHẬT 3: Dường như 'gây rối' với các cửa sổ khác như thế này không được hỗ trợ. Cửa sổ giao diện điều khiển tính toán văn bản của nó giả định có một chú thích, do đó, không có cách nào xung quanh việc này. Tôi nghĩ rằng lựa chọn duy nhất của tôi để có được hành vi giống như giao diện điều khiển trong WPF là có được để viết một điều khiển WinForms tùy chỉnh và sau đó nhúng vào WPF.

+0

Bạn đã thực hiện điều này thành công? –

+0

@ShawnMclean Không ... các bản cập nhật đại diện cho toàn bộ câu chuyện: ( – InfinitiesLoop

+0

Bạn có thể xem các chương trình Console2 (sau này được chia làm bàn điều khiển), họ lưu trữ thành công một loạt các lời nhắc lệnh trong điều khiển tab mà không có chú thích/tiêu đề –

Trả lời

4

Bạn sẽ có thể sử dụng kỹ thuật tương tự như ứng dụng Windows Forms mà bạn đã hiển thị bằng cách sửa lại thành HwndHost. Bạn thậm chí có thể thích ứng với mã Windows Forms, và đặt nó trực tiếp vào điều khiển WindowsFormsHost.

+0

Thật dễ dàng, phải không? :) Tôi đã làm điều này: SetParent (ConsoleManager.ConsoleWindowHandle, WindowsFormsHost.Handle); Nhưng cửa sổ bảng điều khiển không hiển thị .. ngay sau khi nó được sửa chữa nó chỉ biến mất. Bất kỳ ý tưởng? – InfinitiesLoop

+0

Thử đặt Bảng điều khiển (Windows Forms) trong điều khiển WindowsFormsHost của bạn và đặt cha mẹ thành tay cầm của bảng điều khiển (thay vì kiểm soát chính nó). –

+0

Bạn biết tôi nghĩ rằng nó đã được làm việc, nó chỉ là cửa sổ đôi khi ra khỏi xem trong phụ huynh. Tôi sẽ cần phải tìm ra cách tiếp theo để ràng buộc kích thước của cả hai với nhau và để ẩn thanh tiêu đề, vv Bạn đã giúp rất nhiều, cảm ơn :) – InfinitiesLoop

5

Ngoài lời khuyên tuyệt vời của Reed Copsey về cách nhúng cửa sổ bảng điều khiển trong ứng dụng WPF, một chiến lược thay thế dễ dàng thực hiện sẽ đơn giản là đưa ra lệnh thông qua lớp Process và chuyển hướng hai luồng vào WPF gốc TextBlocks. Dưới đây là một ảnh chụp màn hình ...

enter image description here

ứng dụng WPF này (có dây để Windows Explorer menu ngữ cảnh cho các tập tin 'exe') thực hiện chương trình và đường ống kết quả vào cửa sổ thích hợp.

Được thiết kế để trợ giúp khi bạn muốn chạy tiện ích bảng điều khiển và khi bạn nhấp vào tiện ích, tiện ích sẽ chuyển sang cửa sổ bảng điều khiển và bạn sẽ không bao giờ thấy điều gì đã xảy ra. Nó cũng có dây để 'csproj' tập tin để chạy MSBuild trên chúng từ Explorer.

Điểm được rằng đôi khi nó dễ dàng hơn và khả năng mở rộng hơn để làm điều đó cho mình chứ không phải cố gắng tổ chức một cửa sổ giao diện điều khiển ...

Các bên trong của ứng dụng này sử dụng lớp này ...

public class ProcessPiper 
{ 
    public string StdOut { get; private set; } 
    public string StdErr { get; private set; } 
    public string ExMessage { get; set; } 
    public void Start(FileInfo exe, string args, Action<ProcessPiper>onComplete) 
    { 
     ProcessStartInfo psi = new ProcessStartInfo(exe.FullName, args); 
     psi.RedirectStandardError = true; 
     psi.RedirectStandardOutput = true; 
     psi.UseShellExecute = false; 
     psi.WorkingDirectory = Path.GetDirectoryName(exe.FullName); 
     Task.Factory.StartNew(() => 
      { 
       try 
       { 
        ExMessage = string.Empty; 
        Process process = new Process(); 
        process.StartInfo = psi; 
        process.Start(); 
        process.WaitForExit(); 
        StdOut = process.StandardOutput.ReadToEnd(); 
        StdErr = process.StandardError.ReadToEnd(); 
        onComplete(this); 
       } 
       catch (Exception ex) 
       { 
        ExMessage = ex.Message; 
       } 
      }); 
    } 
} 

Lớp này thực thi tệp 'exe' có tên và bắt đầu xuất và sau đó gọi Mô hình xem. Toàn bộ khoan mã hóa nên mất khoảng một giờ hoặc lâu hơn ...

Documents trên lớp Process đang ở đây: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx

Các vấn đề liên quan