2010-11-07 20 views
10

Tôi đã tìm thấy câu hỏi này trên StackOverflow. Về cơ bản, người dùng muốn vẽ các nút tùy chỉnh trên thanh tiêu đề.Vẽ các nút tùy chỉnh trên Windows Vista/7 Aero Titlebar

Tôi đã thử mã và nhận ra nó hoạt động trong vista/7 chỉ khi Aero bị tắt. Câu hỏi của tôi là, có cách nào để vẽ các nút tùy chỉnh trên thanh tiêu đề trong khi aero được bật không?

Ngoài ra, có cách nào để đọc thông tin từ chủ đề hiện tại để tôi có thể tạo kiểu cho các nút của mình khớp với các nút hiện có hay không.


Cập nhật

Đây là một ảnh chụp màn hình từ máy tính của tôi chứng minh khái niệm trên. Tôi nhận được các nút tiêu đề bổ sung sau khi cài đặt DisplayFusion.
Notepad2 showing additional buttons.

Và tôi biết DisplayFusion là một chương trình .NET vì nó mở trong .NET Reflector. Phía xuống là chương trình bị làm xáo trộn. Không phải như tôi muốn dịch ngược chương trình hay gì cả; Tôi chỉ muốn thêm một nút vào thanh tiêu đề của tôi để làm điều gì đó khác (ví dụ như giảm thiểu cho khay hệ thống).
Dưới đây là ảnh chụp màn hình, chứng minh chương trình là một ứng dụng .NET.
.NET Reflector showing DisplayFusion

+0

Quên điều này, nó không hoạt động nữa. –

+4

Tôi biết điều đó là có thể vì có ứng dụng đa màn hình này được gọi là ** Hiển thị Fusion **. Tôi biết đó là một ứng dụng .NET vì tôi đã xem nó với .NET Reflector của Lutz Roeder. –

Trả lời

4

Chừng nào bạn sẵn sàng vẽ lại toàn bộ nội dung thanh tiêu đề, sau đó bạn có thể sử dụng phương pháp DwmExtendFrameIntoClientArea API DWM, mà liên quan đến việc thiết lập cửa sổ của bạn không có thanh tiêu đề, cho phép DWM để vẽ kính của nó vào khu vực có thể sử dụng của bạn để tạo một không gian mới trông giống như thanh tiêu đề nhưng thực tế là trong khu vực khách hàng của bạn, để bạn có thể vẽ các nút trên đó.

Nhược điểm của phương pháp này là bạn sẽ phải tạo các nút tiêu chuẩn nếu muốn. Giảm thiểu, Tối đa hóa và Đóng không có vấn đề gì để tạo lại (mặc dù bạn sẽ thấy nút tối đa hóa là nút chuyển đổi có giao diện dựa trên trạng thái), nhưng bạn có thể thấy mình gặp sự cố khi tạo lại nút trên cùng bên trái. Bạn cũng sẽ phải vẽ lại tiêu đề của bạn, tất nhiên, nhưng tôi không thể tưởng tượng bạn sẽ có bất kỳ vấn đề với điều đó.

Để đọc dữ liệu của chủ đề hiện tại trở lại để chỉnh sửa các nút của bạn như của họ, tôi xin lỗi nhưng tôi không biết gì về điều đó. Đề xuất của tôi là sử dụng tính minh bạch khi xây dựng các nút của bạn trên thanh tiêu đề và sử dụng hiệu ứng ánh sáng mờ, v.v. Bằng cách đó bạn sẽ có thể giữ lại nền kính, và chỉ cần thay đổi diện mạo của nó bằng cách phủ một màu mờ. Ngoài ra, nếu bạn làm theo cách này, thì điểm nổi bật trên kính sẽ di chuyển tự nhiên, trong khi nếu bạn chỉ có màu chủ đề, bạn sẽ thấy rằng bạn không có quyền truy cập vào phản xạ hoặc chúng tái tạo lại trong vòng không gian của các nút của bạn. Chỉ cần hai xu của tôi, tất nhiên - nếu bạn có thể tìm thấy một cách để làm màu sắc chủ đề của bạn etcetera, bằng mọi cách.

Có một cảnh báo cho điều này mặc dù - có một luồng StackOverflow khác (http://stackoverflow.com/questions/2666979/net-framework-4-0-and-drawing-on-aero-glass-issue/4656182# 4656182) được mô tả một vấn đề với phương pháp DWM API DwmExtendFrameIntoClientArea, vì vậy nếu tôi là bạn, tôi sẽ đọc qua điều đó trước khi thử giải pháp này.

4

Tôi đã thực hiện một số nghiên cứu về điều này khi tôi triển khai quá trình này trong giải pháp đa màn hình của riêng mình. Cách DisplayFusion và TeamViewer thực hiện điều này là chồng lên một biểu mẫu tùy chỉnh trên cửa sổ mong muốn chứa các nút. Bạn có thể sử dụng Spy ++ để xác nhận điều này.

Đây là ý tưởng chung:

  1. Viết móc DLL cho việc thông báo khi một cửa sổ được tạo ra, gỡ bỏ, kích hoạt, thay đổi vị trí hoặc thay đổi kích cỡ.
  2. Tạo biểu mẫu trong suốt bằng cách sử dụng phím trong suốt hoặc sử dụng alpha-PNG and GDI+ solution này và mô phỏng (các) nút bằng cách tự vẽ nó.
  3. Khi tạo/xóa cửa sổ, bạn hiển thị/ẩn biểu mẫu thanh tiêu đề của bạn cho (các) cửa sổ mong muốn.
  4. Trên các thông báo định lại kích thước/đặt lại cửa sổ, bạn căn chỉnh lại biểu mẫu thanh tiêu đề của bạn.
  5. Khi kích hoạt cửa sổ, bạn đặt vị trí Z của cửa sổ sao cho nó ở trên cùng của cửa sổ mong muốn.

Nhận và đặt vị trí Z qua các API GetWindowSetWindowPos của API.
Hãy lưu ý rằng DLL phải được viết bằng ngôn ngữ mẹ đẻ. Tuy nhiên bạn van sử dụng một cái gì đó như thế này để làm việc xung quanh vấn đề rằng: Using Window Messages to Implement Global System Hooks in C#

Và đây là kết quả của tôi:

enter image description here

+0

Giải pháp của bạn trông đầy hứa hẹn. Tôi đã tìm cách tạo ra hình dạng trong suốt và phát hiện việc mở, di chuyển và đóng cửa sổ. Những gì tôi muốn biết là làm thế nào bạn tạo ra các nút theo chủ đề trống để tôi có thể vẽ của riêng tôi. Nếu có thể, bạn có thể tải lên giải pháp của mình không? –

+0

Bạn có thể vui lòng đăng một số mã để hiển thị cách bạn tạo các nút thanh tiêu đề trong ảnh chụp màn hình không? –

+0

@Jelle Vergeer Vui lòng xem xét thêm liên kết cho mã nguồn của "kết quả", tôi cần giải pháp này ... +1 – ElektroStudios

0

Ok, hệ thống móc là phương pháp trực tiếp để nhận thông tin về vị trí cửa sổ thay đổi và Jelle's đề xuất với hình thức minh bạch là rất tốt. Nhưng bạn có thể sử dụng một phương pháp ít xâm lấn để có được thông tin trên cửa sổ Desktop bằng cách sử dụng user32.dll

[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
public static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect); 

Cửa sổ xử lý bạn có thể nhận sử dụng EnumDesktopWindows

[DllImport("user32.dll", EntryPoint = "EnumDesktopWindows", 
ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)] 
[return: MarshalAs(UnmanagedType.Bool)] 
public static extern bool EnumDesktopWindows(IntPtr hDesktop, EnumDelegate lpEnumCallbackFunction, IntPtr lParam); 

Một ví dụ cho điều này bạn có thể nhận được từ các chủ đề getting-a-list-of-all-applications-in-c-sharp

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