2012-04-11 33 views
10

Tôi đã tạo Ứng dụng Biểu mẫu Windows mới (C#) với một biểu mẫu đơn giản có chứa ListView. Sau đó, tôi đã thay đổi View Property Details và tăng kích thước của các font sử dụng trong ListView này và đây là kết quả:Chủ đề Windows ảnh hưởng đến tiêu đề ListView

Đây là cách nó trông giống trên Windows XP với chủ đề Windows Classic:
enter image description here

và đây là kết quả với chủ đề Windows XP:
enter image description here

tôi có thể ngăn chặn sự xuất hiện của ứng dụng của tôi bị ảnh hưởng bởi phong cách trực quan bằng cách xóa Application.EnableVisualStyles() cuộc gọi hoặc bằng cách thay đổi Application.VisualStyleState: enter image description here
Mặc dù thay đổi này làm cho ListView có giao diện mong muốn, nó cũng ảnh hưởng đến sự xuất hiện của các điều khiển khác. Tôi muốn ListView của mình là điều khiển duy nhất không bị ảnh hưởng bởi Visual Styles.

Tôi cũng đã tìm thấy những câu hỏi tương tự mà cố gắng để đối phó với nó:
Can you turn off visual styles/theming for just a single windows control?
How do I disable visual styles for just one control, and not its children?

Thật không may, không ai trong số các giải pháp nêu hoạt động. Dường như chính tiêu đề sẽ được tạo thành từ một số điều khiển bị ảnh hưởng bởi kiểu trực quan ngay cả khi kiểu trực quan cho điều khiển ListView bị tắt.

Bất kỳ giải pháp C# nào có thể ngăn chặn kiểu trực quan ảnh hưởng đến sự xuất hiện của tiêu đề ListView sẽ được đánh giá cao.

Trả lời

2

Sau hết nghiên cứu, tôi thấy nó ra. Cái này là khi bạn gọi

SetWindowTheme(this.Handle, "", ""); 

trong tùy chỉnh ListView lớp, nó ngăn cản visual styles từ ảnh hưởng đến sự xuất hiện của các ListView kiểm soát nhưng không phải là ListView kiểm soát tiêu đề (SysHeader32 cửa sổ), đó là cửa sổ con của ListView. Vì vậy, khi gọi SetWindowTheme chức năng, chúng ta cần phải cung cấp cho tay cầm của cửa sổ tiêu đề thay vì tay cầm của ListView:

[DllImportAttribute("uxtheme.dll")] 
private static extern int SetWindowTheme(IntPtr hWnd, string appname, string idlist); 

[DllImport("user32")] 
[return: MarshalAs(UnmanagedType.Bool)] 
private static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i); 

// Callback method to be used when enumerating windows: 
private static bool EnumWindow(IntPtr handle, IntPtr pointer) 
{ 
    GCHandle gch = GCHandle.FromIntPtr(pointer); 
    List<IntPtr> list = gch.Target as List<IntPtr>; 
    if (list == null) 
     throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>"); 
    list.Add(handle); 
    return true; 
} 

// delegate for the EnumChildWindows method: 
private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter); 

// get first child: 
private static void DisableVisualStylesForFirstChild(IntPtr parent) 
{ 
    List<IntPtr> children = new List<IntPtr>(); 
    GCHandle listHandle = GCHandle.Alloc(children); 
    try 
    { 
     EnumWindowProc childProc = new EnumWindowProc(EnumWindow); 
     EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle)); 
     if (children.Count > 0) 
      SetWindowTheme(children[0], "", ""); 
    } 
    finally 
    { 
     if (listHandle.IsAllocated) 
      listHandle.Free(); 
    } 
} 

protected override void OnHandleCreated(EventArgs e) 
{ 
    DisableVisualStylesForFirstChild(this.Handle); 
    base.OnHandleCreated(e); 
} 
+0

Vì nó dựa trên giải pháp được đề xuất bởi Kamil Lach, tôi đã trao giải câu trả lời của anh ấy với tiền thưởng mà tôi đã cung cấp. – LihO

2

Điều gì về tắt kiểu trực quan?

với mã này bạn có thể vô hiệu hóa phong cách cho một điều khiển (chỉ cần sử dụng ListViewConstrol thay vì ListView):

using System; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

public class ListViewControl : ListView { 
    [DllImportAttribute("uxtheme.dll")] 
    private static extern int SetWindowTheme(IntPtr hWnd, string appname, string idlist); 

    protected override void OnHandleCreated(EventArgs e) { 
    SetWindowTheme(this.Handle, "", ""); 
    base.OnHandleCreated(e); 
    } 
} 
+0

+1 để chỉ ra rằng Visual Styles gây thay đổi này mặc dù giải pháp này không làm việc chút nào. – LihO

+0

Tôi đã tìm ra lý do tại sao SetWindowTheme không hoạt động trước đây. Nó hoạt động bây giờ, kiểm tra câu trả lời của tôi;) – LihO

+0

Chúc mừng Kamil cho tiền thưởng :) – ABH

3

Hình như đây là một known bug mà không có cách giải quyết dễ dàng. Theo câu trả lời đó:

Sau khi thực hiện rất nhiều nghiên cứu với vấn đề này, chúng tôi thấy rằng đây là một hệ điều hành windows lỗi, mà quên kiểm soát tiêu đề ComCtl6.0 để áp dụng thông tin phông chữ để vẽ DC.

Tuy nhiên bạn có thể tự vẽ tiêu đề cột. Xem this article on MSDN để biết chi tiết về cách thực hiện và xem listView1_DrawColumnHeader.

+0

+1 để tự vẽ nó –

+0

Vẽ nó bản thân mình sẽ không giúp gì cả vì bạn chỉ có thể thay đổi nội dung đang được vẽ, không phải kích thước của tiêu đề. – LihO

0

Botz3000 được đề cập trong câu trả lời của mình rằng sự cố nổi tiếng của nó với ListView trong Windows XP. Một giải pháp khác là đăng ký sự kiện ListView.DrawColumnHeader và đặt lại phông chữ tiêu đề trong đó. Bạn phải đặt tài sản ListView.OwnerDraw thành true. Mã MSDN như sau;

// Draws column headers. 
private void listView1_DrawColumnHeader(object sender, 
    DrawListViewColumnHeaderEventArgs e) 
{ 
    using (StringFormat sf = new StringFormat()) 
    { 
     // Store the column text alignment, letting it default 
     // to Left if it has not been set to Center or Right. 
     switch (e.Header.TextAlign) 
     { 
      case HorizontalAlignment.Center: 
       sf.Alignment = StringAlignment.Center; 
       break; 
      case HorizontalAlignment.Right: 
       sf.Alignment = StringAlignment.Far; 
       break; 
     } 

     // Draw the standard header background. 
     e.DrawBackground(); 

     // Draw the header text. 
     using (Font headerFont = 
        new Font("Helvetica", 10, FontStyle.Bold)) 
     { 
      e.Graphics.DrawString(e.Header.Text, headerFont, 
       Brushes.Black, e.Bounds, sf); 
     } 
    } 
    return; 
} 

Trong trường hợp này phông chữ tiêu đề sẽ luôn là "Helvetica", 10, FontStyle.Bold và sẽ không bị ảnh hưởng bởi phông chữ listview. Check MSDN để biết thêm chi tiết.

+0

Không, OwnerDraw không phải là cách, nó không thể ảnh hưởng đến chiều cao của tiêu đề ListView với nó. – LihO

+0

@LihO Nó không làm bất cứ điều gì với chiều cao của tiêu đề vì nó không thể trong XP. Vui lòng đọc kỹ câu trả lời của tôi, ý tưởng là giữ cho văn bản tiêu đề nhỏ hơn để nó vừa với tiêu đề. – ABH

+0

Nhưng câu hỏi của tôi là làm thế nào để "làm cho tiêu đề ListView có chiều cao chính xác", không làm thế nào để làm cho văn bản tiêu đề nhỏ hơn ... – LihO

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