2012-04-11 44 views
10

我創建新的Windows Windows主題窗體包含ListView的一個簡單的表單應用程序(C#)。然後,我已經改變了View Property細節,增加了該ListView的使用,這裏的字體大小,結果如下:影響的ListView頭

這是它的外觀在Windows XP與Windows經典主題:
enter image description here

和這裏的與Windows XP主題的結果:
enter image description here

我可以阻止我的應用程序的外觀,通過視覺樣式是拆除Application.EnableVisualStyles()電話或通過改變 影響: enter image description here
雖然這種變化使得ListView中有所需的外觀,它也會影響其他控件的外觀。我想我的ListView是是不受視覺樣式的唯一控制。

我還發現,試圖解決它類似的問題:
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?

不幸的是,沒有提及解決方案的工作。 它看起來像本身會作出一些由視覺風格,即使視覺樣式的ListView控件被禁用受影響的控件的標題。

任何會阻止視覺樣式影響ListView頭部外觀的C#解決方案將不勝感激。

回答

2

用盡研究之後,我發現它。問題是,當你調用

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

定製ListView類中,它可以防止視覺樣式從影響ListView控制的appearence但不是ListView頭控制(SysHeader32窗口),這是ListView子窗口。 所以調用SetWindowTheme功能時,我們需要提供的標題窗口,而不是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

因爲它是基於Kamil Lach建議的解決方案,所以我將獎勵他的答案與我提供的賞金。 – LihO 2012-04-17 14:12:29

2

什麼禁用視覺樣式?

與此代碼,你可以爲一個控制禁用的風格(只是用ListViewConstrol而不是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指出視覺樣式導致這種變化雖然這種解決方案並不一切工作。 – LihO 2012-04-16 09:49:59

+0

我發現了爲什麼SetWindowTheme之前沒有工作。它現在的作品,檢查我的答案;) – LihO 2012-04-17 14:08:50

+0

恭喜卡米爾的賞金:) – ABH 2012-04-17 14:50:20

3

看起來這是一個known bug對其中有沒有簡單的解決方法。根據答案有:

做了很多的研究這個問題後,我們發現這是一個 Windows操作系統漏洞,該頭的comctl6.0控制忘記申請 字體信息到繪圖其DC。

但是你可以繪製列標題自己。見this article on MSDN關於如何做到這一點的詳細信息,也看listView1_DrawColumnHeader

+0

+1自己繪製它 – 2012-04-13 11:28:55

+0

自己繪製它根本沒有幫助,因爲你只能改變內容正在繪製,而不是標題的大小。 – LihO 2012-04-16 09:58:03

0

由於Botz3000在他的答覆中提到,其在Windows XP ListView一個衆所周知的問題。另一個解決方法是註冊ListView.DrawColumnHeader事件並復位標題字體在它。您必須ListView.OwnerDraw屬性設置爲true。 MSDN代碼如下;

// 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; 
} 

在這種情況下,標題字體將總是"Helvetica", 10, FontStyle.Bold並且不會被列表視圖字體來實現。 Check MSDN瞭解更多詳情。

+0

不,OwnerDraw不是這樣,它不可能影響ListView標題的高度。 – LihO 2012-04-16 09:59:16

+0

@LihO它沒有做任何事情的標題的高度,因爲它不可能在XP中。請仔細閱讀我的答案,這個想法是保持標題文本的小一點,以便它適合標題。 – ABH 2012-04-16 11:23:07

+0

但我的問題是如何「使ListView標題具有正確的高度」,而不是如何使標題文本更小... – LihO 2012-04-16 12:24:11