返回首页

简介
这篇文章是关于发现在Windows Vista中使用新的Windows Vista用户界面的控件。包含在项目中的一些组件(Commandlinks的ImageButton,SplitButton),就像Windows Vista的主题控制工作。
这篇文章的目的是实现大多数的界面效果(如fade-in/out)整个Windows Vista中看到的效果。背景
大多数的Windows Vista的用户可能会发现新的用户界面。每个控制是一步一个更好的Windows XP相比,它来完成的,与可爱的小褪色效果。然而,微软Visual Studio默认情况下不支持完整的Vista主题。虽然Visual Studio 2005中试图解决这一问题的视觉样式,它仍然不会允许控制,以实现整个Windows Vista的所有可见的视觉效果。
本文包括:获取对一些常用控件(按钮,复选框,单选按钮,文本框,组合框)的淡入淡出效果淡出效果,获得的图像按钮上,和保存获取工具栏上的淡出效果获取MainMenus和ContextMenus Windows Vista的主题化获得CommandLinks和SplitButtons获得不同颜色的Progressbars获得类似资源管理器的接口列表框和的TreeView
它利用USER32.DLL SendMessage函数()函数,以及uxtheme.dll setwindowtheme()一定的控制功能,为了呈现一些控制到预期的水平。先决条件
您将需要以下的东西来完成本教程:Windows Vista中NET框架2.0(已预装在Windows Vista)
其他一些(可选)有用的东西:{A}通用控件
{S0}
大多数控件都已经准备好为Windows Vista的主题化。我敢肯定,你有听说过EnableVisualStyles()的权利? EnableVisualStyles()通常被称为主题意识的控制,以获得用户界面主题。虽然Visual Studio 2005已经有了这个做的,Visual Studio 2003中并没有在默认情况下。如果你想使共同控制的主题,你可以查看希思管家} {A3的文章。
EnableVisualStyles()影响以下控制:文本框RichTextBox中HScrollBar垂直滚动条ProgressBar的TabControl的(部分)MainMenu的的ContextMenu组合框DataGrid中ListBox中ListView中TreeView的的DateTimePickerMonthCalendar分离器的TrackBarStatusBar的工具栏TreeView的ListView中按钮分组框中(部分)
虽然Visual Studio 2005支持其中包括控制视觉主题化,这些控件不具有"全"为主题,其中包括淡入淡出效果。通过设置的FlatStyle系统,可以解决这个问题。但是,这样做,图像不会显示等控制手段。在下一节中,这个问题可以很容易地解决。获取图像按钮和其他控件工作
通过设置按钮的FlatStyle系统,使得按钮和其他一些图像无法显示这些按钮。但是,本节旨在解决这个问题,通过使用尽可能少的代码。
如何来完成这件事?好了,我们需要发挥在user32.dll中发现的SendMessage()的功能。
首先,我们将需要申报的功能(但首先,你将需要进口System.Runtime.InteropServices):

//Imports the user32.dll

[DllImport("user32.dll", CharSet = CharSet.Auto)]

public static extern IntPtr SendMessage

            (IntPtr hWnd, int msg, int wParam, int lParam);


要设置一个控制的形象,我们将需要使用的BM_SETIMAGE [0x00F7]消息。现在,我们将使用一个图标(在System.Drawing声明)作为一个图像,因为它很容易得到的图标的句柄。{C}
这段代码的功能是检索您要显示的图标按钮(名为"button1的")的处理,并发送一条消息到Windows设置要使用的按钮图标。
你可以设置你想要什么样的图标设置"buttonicon"。您可以通过使用下面的代码:
buttonicon = new Icon(SystemIcons.Exclamation, 40, 40);

SetImage();


使用该系统的惊叹号图标。什么,你会得到:

如果你想使用位图/图像,而不是一个图标,你可以使用GetHIcon()从位图的方法来检索位图的处理和使用手柄设置按钮的形象。
IntPtr iconhandle = IntPtr.Zero;

Bitmap image = new Bitmap("C:\images\an_image.png");

iconhandle = image_.GetHicon();

SendMessage(this.Handle, VistaConstants.BM_SETIMAGE, 1, (int)iconhandle);


此按钮仍然支持其他正常的按钮有淡入淡出效果。
然而,有一个小问题,使用此方法。如果这个按钮的文本设置为"",无图像显示。这个问题是可以解决的CreateParams()函数的使用和分配BS_ICON主题按钮。
//CreateParams property

protected override CreateParams CreateParams

{

    get

    {

        CreateParams cParams = base.CreateParams;

        if (this.ShowIconOnly == true)

        {

            //Render button without text

            cParams.Style |= 0x00000040; // BS_ICON value

        }

    return cParams;

    }

}

这种方法是最好的做法从从按钮继承的类。CommandLinks
CommandLinks真的只是按钮,分配不同的主题。他们的主题和他们的价值观(从CommCtrl.h在Windows Vista SDK)如下:BS_COMMANDLINK [0x0000000E]
第一步是创建按钮继承一个类。然后,我们可以覆盖的CreateParams()功能,使按钮使用各自的主题。为主题的生效,您需要对系统设置按钮的FlatStyle。下面是将commandLink类:
using System;

using System.Collections.Generic;

using System.Text;

using System.Windows.Forms;

using System.Runtime.InteropServices



public class CommandLink : Button

{

    const int BS_COMMANDLINK = 0x0000000E;



    //Set button's flatstyle to system

    public CommandLink()

    {

        this.FlatStyle = FlatStyle.System;

    }



    protected override CreateParams CreateParams

    {

        get

        {

            CreateParams cParams = base.CreateParams;

            //Set the button to use Commandlink styles

            cParams.Style |= BS_COMMANDLINK;

            return cParams;

        }

    }

}

然后你可以建立项目,就像一个正常的按钮使用在Windows窗体组件(因为它是从一个正常的按钮继承)。将commandLink的样子:
{S2}
*鼠标是通过将commandLink,但PRINTSCREEN不会捕获鼠标。
按钮,支持淡入淡出效果,就像实际控制。
但是等待?将commandLink的"注意事项"在哪里?那么,我们就可以实现该功能BCM_SETNOTE [0x00001609]消息发送到Windows。我们可以纳入一个属性设置轻松将commandLink的说明。
const uint BCM_SETNOTE = 0x00001609;

//Imports the user32.dll

[DllImport("user32.dll", CharSet = CharSet.Unicode)]

static extern IntPtr SendMessage

        (HandleRef hWnd, UInt32 Msg, IntPtr wParam, string lParam);

//Note property

private string note_ = "";

public string Note

{

    get

    {

        return this.note_;

    }

    set

    {

        this.note_ = value;

        this.SetNote(this.note_);

    }

}



//Sets the button's note

void SetNote(string NoteText)

{

    //Sets the note

    SendMessage(new HandleRef(this, this.Handle), 

                BCM_SETNOTE, IntPtr.Zero, NoteText);

}


你会得到:

你也可以使用CommandLinks按钮图标/图像显示同样的方法:
{S4}的SplitButtons
{五}
就像CommandLinks,SplitButtons只是简单的按钮。您可以设置其样式SplitButton的使用的CreateParams方法:BS_SPLITBUTTON [0x0000000C]
然而,即使在设置样式,如何你会联想到一个菜单(ContextMenu中)按钮?为此,我们可以首先将发射每当splitbutton"下拉菜单"上的人点击的事件关联。首先,我们会听取重写的WndProc()方法发送到按钮的所有邮件。碰巧BCN_SETDROPDOWNSTATE [0x1606]消息将发送时,被点击下拉。此消息引发了数次,但只有一个消息发生是独一无二的,"1"的价值WPARAMS。最好的做法是在另一个类的消息进行过滤。此示例代码将火推下拉时是一个自定义事件(DropDown_Clicked)。
protected override void WndProc(ref Message m)

{

    // Listen for operating system messages; 

    // Filter out a lot of messages here

    //The dropdown glyph changes:

    //Mousedown (at dropdown area) => Dropdown Event fired 

    //                => Glyph changes => MouseUp => Glyph Changes

    switch (m.Msg)

    {

        case (VistaControls.VistaConstants.BCM_SETDROPDOWNSTATE):

        //PROBLEM: other buttons also have would encounter this message

        if (m.HWnd == this.Handle)

        {

            ////This message seems to occur when the drop down is clicked; 

            ////Occurs several times, but one of them have the value of 1 

            ////in WParams

            if (m.WParam.ToString() == "1")

            {

                DropDown_Clicked();

            }

        }

    break;

    }



    base.WndProc(ref m);

}

使用这个自定义事件,我们可以显示出,只要按下按钮的下拉部分(完整的代码演示)的ContextMenu。这还不是全部尽管。我们只分配一个推下拉时,会被解雇的事件。我们需要在合适的时间下拉字形变化。有一些消息,我们可以用它来实现字形的正确画。他们的WM_PAINT消息[0x0F的],WM_LBUTTONDOWN [0x201],WM_MOUSELEAVE 0x2A3,WM_LBUTTONUP [0x202]和WM_KILLFOCUS [0x08的]消息。我们可以运行代码时,这些消息是通过重写的WndProc()消息发送。 (代码放在这里太乱了,但完整的代码可以通过Windows Vista控制演示。)
{中六}
此控件还支持淡入淡出效果。提示文本框
在Windows Vista中的一些文本框提示用户他们应该是什么类型(例如:在搜索框中)。它通常会出现一些灰色文字的文本框上,当用户试图键入到TextBox的东西就会消失。此功能为"提示旗帜"知道。在TextBox使用EM_SETCUEBANNER [0x1501]消息,您可以启用此功能。
SendMessage(textbox1.Handle, 0x1500 + 1, IntPtr.Zero, 

                "Please type in something.");

{七}Mainmenus和Contextmenus
默认MainMenus(或MainMenuStrip)和ContextMenus(或的ContextMenuStrip)在Visual Studio 2005不完全支持Windows Vista的主题:


如果你想获得你的主菜单和上下文菜单Windows Vista主题,您将需要使用的Visual Studio 2003版本,或在Visual Studio 2005的向后兼容的版本(称为"主菜单"和"的ContextMenu") 。
您可以指定ContextMenus使用它的ContextMenu属性(可能在VB.NET隐藏在Visual Studio 2005)的控制。工具栏
虽然在Visual Studio 2005的默认工具栏做了Windows Vista的外观(如果Rendermode设置为系统),它并不拥有这一切。大多数Windows Vista上的工具栏有淡入淡出的效果。为了得到它,你将需要使用Visual Studio 2003版本或在Visual Studio 2005(及以上)的向后兼容的版本,并设置它的外形扁平,以获得褪色的效果。

,您可以使用工具栏上的按钮图像列表以及。工具栏的正确使用Visual Studio 2003中的ImageList,呼叫applications.DoEvents()函数后application.EnableVisualStyles()函数(唐Kackman )。Progressbars
在Windows Vista中,progressbars在不同的口味,最常见的是绿色的进度。不过,也有红色和黄色版本以及(有一个蓝色的版本,被称为米,但就是无法访问)。进度条的颜色似乎对应到具体的进度状态。您可以设置这些国家使用PBM_SETSTATE [0x40F]消息。国PBST_NORMAL [0x0001],PBST_ERROR [地图0x0002]和PBST_PAUSE [0x0003]。
SendMessage(progressbar1.Handle, 0x400 + 16, 0x0001, 0); //Normal; Green

SendMessage(progressbar1.Handle, 0x400 + 16, 0x0002, 0); //Error; Red

SendMessage(progressbar1.Handle, 0x400 + 16, 0x0003, 0); //Pause; Yellow

的TreeView和ListViews
默认情况下的TreeView和ListViews不具备资源管理器相同的外观:

然而,位的代码,你可以使它看起来像这样:

您将需要使用UxTheme.dll文件中发现的SetWindowTheme()函数。您可以通过使用下面的代码:
//Imports the UXTheme DLL

[DllImport("uxtheme", CharSet = CharSet.Unicode)]

public extern static Int32 SetWindowTheme

        (IntPtr hWnd, String textSubAppName, String textSubIdList);

然后,你可以设置相应的控制使用的样式使用下面的代码:
SetWindowTheme(listView1.Handle, "explorer", null);

"ListView1的"是你的ListView。你可以做的TreeView这一点。
但是,还有更多。在Windows资源管理器中,这些ListViews以及半透明的选择。您可以通过调用LVS_EX_DOUBLEBUFFER [0x00010000]扩展样式。

的TreeView在Windows资源管理器中也有淡入淡出的效果。这样就可以实现通过TVS_EX_FADEINOUTEXPANDOS [0x0040]扩展样式。
SendMessage(treeview1.Handle, 0x1100 + 44, 0x0040, 0x0040);

的TreeView也有"自动滚动"功能。您可以启用通过TVS_EX_AUTOHSCROLL [0x0020]扩展样式。
SendMessage(treeview1.Handle, 0x1100 + 44, 0x0020, 0x0020);
兴趣点
可能有几个消息或功能,可用于修改主题,可能无法在有限的文件在Windows Vista中发现的控制。当然,这是一种不寻常的,我们必须使用旧版本的控制(如MainMenu和ContextMenu),以实现新的Windows Vista的图形用户界面的全部潜力。 值得注意的事情
我没有在Visual Studio 2003测试上面的代码,我也没有运行Windows XP上的应用程序(我没有做它向后兼容",但")。
自定义控件演示一些旧的Windows版本,可能无法正常工作的CommandLinks,SplitButtons和ProgressBars。
这是在Visual Studio 2005和Windows Vista的测试。参考文献(浏览使用左侧的导航窗格)历史版本1.10:2007年06月17日日 - 几个控件添加/修改版本1.00:2007年5月20日日 - 初始

回答

评论会员:会员7994273 时间:2011/12/14
只是我一直在寻找...干杯
评论会员:游客 时间:2011/12/14
vallarasus:|独特的文章,很useuful
!jsdmj
评论会员:游客 时间:2011/12/14
我portet的C#代码从CueTextBoxVB。一切工作正常。在设计时CueBannerText将被显示,但在运行时,CueBannerText将不会显示。任何想法会发生什么?这是源:codepreImportsSystem.DrawingImportsSystem.Runtime.InteropServicesImportsSystem.ComponentModel NamespaceW7ControlsClassCueTextBoxInheritsSystem.Windows.Forms.TextBoxPrivate_cueBannerTextAsspanclass="code-SDKkeyword"String/span=spanclass="code-SDKkeyword"String/span.EmptyPrivate_showCueFocusedAsspanclass="code-SDKkeyword"Boolean/span=False FriendClassNativeMethodsPublicConstECM_FIRSTAsInteger=&H1500PublicConstEM_SETCUEBANNERAsInteger=ECM_FIRST+spanclass="code-digit"1/span <DllImport(spanclass="code-string""/spanspanclass="code-string"user32.dll"/span,CharSet:=CharSet.Unicode)>_PublicSharedFunctionSendMessage(hWndAsspanclass="code-SDKkeyword"IntPtr/span,MsgAsInteger,wParamAsInteger,lParamAsspanclass="code-SDKkeyword"String/span)AsIntegerEndFunctionEndClass <Browsable(False)>_PublicShadowsPropertyMultiline()Asspanclass="code-SDKkeyword"Boolean/spanGetReturnMyBase.MultilineEndGetSet(spanclass="code-keyword"value/spanAsspanclass="code-SDKkeyword"Boolean/span)MyBase.Multiline=FalseEndSetEndProperty <Description(spanclass="code-string""/spanspanclass="code-string"TheCuetextwhichwillbedisplayed."/span),Category(spanclass="code-string""/spanspanclass="code-string"Appearance"/span),DefaultValue(spanclass="code-string""/spanspanclass="code-string"CueBannerText"/span)>_PublicPropertyCueBannerText()Asspanclass="code-SDKkeyword"String/spanGetReturn_cueBannerTextEndGetSet(ByValspanclass="code-keyword"value/spanAsspanclass="code-SDKkeyword"String/span)_cueBannerText=spanclass="code-keyword"value/spanSetCueText(ShowCueFocused)EndSetEndProperty <Description(spanclass="code-string""/spanspanclass="code-string"Iftrue,theCuetextwillbedisplayedevenwhenthecontrolhaskeyboardfocus."/span),Category(spanclass="code-string""/spanspanclass="code-string"Appearance"/span),DefaultValue(False)>_PublicPropertyShowCueFocused()Asspanclass="code-SDKkeyword"Boolean/spanGetReturn_showCueFocusedEndGetSet(spanclass="code-keyword"value/spanAsspanclass="code-SDKkeyword"Boolean/span)_showCueFocused=spanclass="code-keyword"value/spanSetCueText(spanclass="code-keyword"value/span)EndSetEndProperty PrivateSubSetCueText(showFocusAsspanclass="code-SDKkeyword"Boolean/span)NativeMethods.SendMessage(Me.Handle,NativeMethods.EM_SETCUEBANNER,Newspanclass="code-SDKkeyword"IntPtr/span(If((showFocus),spanclass="code-digit"1/span,spanclass="code-digit"0/span)),_cueBannerText)EndSub EndClassEndNamespace/pre/code预先感谢马库斯
sudhircn83
评论会员:游客 时间:2011/12/14
多数民众赞成大文章。如何在VisualBasic.NET应用程序中使用呢?感谢
。BlackDogSpark
评论会员:游客 时间:2011/12/14
您好,如何避免申请Windows主题MenuStrip和ToolStripMenuItem控件?即在应用方面,我们希望仅适用于ListView控件的Windows主题,为其他控件,它应该有Windows经典主题。请指导我。谢谢您,的SudhirCN
德中号
评论会员:游客 时间:2011/12/14
是否有距离选择使用什么主题?我的意思是让我可以对应用程序使用不同的主题,而不是目前正在使用中的一个
。死戴夫
评论会员:游客 时间:2011/12/14
这里是我你ExplorerListView的解决方案。我已删除了输入事件的解决方法,现在它的工作原理相当不错codeprespanclass="code-keyword"public/spanspanclass="code-keyword"class/spanExplorerListView:ListView{spanclass="code-keyword"private/spanspanclass="code-keyword"const/spanspanclass="code-keyword"int/spanLVM_FIRST=0x1000;spanclass="code-comment"///spanspanclass="code-comment"Valuefromhttp://www.winehq.org/pipermail/wine-devel/2002-October/009527.html/spanspanclass="code-keyword"private/spanspanclass="code-keyword"const/spanspanclass="code-keyword"int/spanLVM_SETEXTENDEDLISTVIEWSTYLE=LVM_FIRST+spanclass="code-digit"54/span;spanclass="code-keyword"private/spanspanclass="code-keyword"const/spanspanclass="code-keyword"int/spanLVS_EX_DOUBLEBUFFER=0x00010000;[DllImport(spanclass="code-string""/spanspanclass="code-string"user32.dll"/span,CharSet=CharSet.Auto)]spanclass="code-keyword"private/spanspanclass="code-keyword"static/spanspanclass="code-keyword"extern/spanspanclass="code-SDKkeyword"IntPtr/spanSendMessage(spanclass="code-SDKkeyword"IntPtr/spanhWnd,spanclass="code-keyword"int/spanmsg,spanclass="code-keyword"int/spanwParam,spanclass="code-keyword"int/spanlParam);spanclass="code-comment"///spanspanclass="code-comment"ImportstheUXThemeDLL/span[DllImport(spanclass="code-string""/spanspanclass="code-string"uxtheme"/span,CharSet=CharSet.Unicode)]spanclass="code-keyword"private/spanspanclass="code-keyword"extern/spanspanclass="code-keyword"static/spanspanclass="code-SDKkeyword"Int32/spanSetWindowTheme(spanclass="code-SDKkeyword"IntPtr/spanhWnd,spanclass="code-SDKkeyword"String/spantextSubAppName,spanclass="code-SDKkeyword"String/spantextSubIdList);spanclass="code-keyword"protected/spanspanclass="code-keyword"override/spanspanclass="code-keyword"void/spanInitLayout(){spanclass="code-keyword"base/span.InitLayout(); SetWindowTheme(spanclass="code-keyword"this/span.Handle,spanclass="code-string""/spanspanclass="code-string"explorer"/span,spanclass="code-keyword"null/span);spanclass="code-comment"///spanspanclass="code-comment"Explorerstyle/spanSendMessage(spanclass="code-keyword"this/span.Handle,LVM_SETEXTENDEDLISTVIEWSTYLE,spanclass="code-digit"0/span,LVS_EX_DOUBLEBUFFER);spanclass="code-comment"///spanspanclass="code-comment"Blueselection/span}}/pre/code
zicarius
评论会员:游客 时间:2011/12/14
在下载源码文件ExplorerListView.csLoad事件中,您使用的行:codepreSendMessage(spanclass="code-keyword"this/span.Handle,LVM_SETEXTENDEDLISTVIEWSTYLE,spanclass="code-digit"0/span,LVS_EX_DOUBLEBUFFER);spanclass="code-comment"///spanspanclass="code-comment"Blueselection/span/pre/code然而,在Main.cs例如行316使用行:codepreVistaControls.VistaConstants.SendMessage(lv1.Handle,VistaControls.VistaConstants.LVM_SETEXTENDEDLISTVIEWSTYLE,VistaControls.VistaConstants.LVS_EX_DOUBLEBUFFER,VistaControls.VistaConstants.LVS_EX_DOUBLEBUFFER);/pre/code我注意到在0和VistaControls.VistaConstants.LVS_EX_DOUBLEBUFFER之间的第三个参数的差异-这是正确的,请
哈罗德aptroot
评论会员:游客 时间:2011/12/14
FullRowSelect不与你的ExplorerListView工作,在详细信息视图。下面是解决方案: 公共ExplorerListView(){ 使用setStyle(ControlStyles.OptimizedDoubleBuffer,TRUE); UpdateStyles()this.Enter=新的EventHandler(ExplorerListView_Load); }修改日(星期二),2009年1月27日下午07:06
死戴夫
评论会员:游客 时间:2011/12/14
解决方案使用,如果FullRowSelect不工作:公共类ExplorerListView:ListView的{... constint的LVM_SETEXTENDEDLISTVIEWSTYLE=LVM_FIRST36; ...}
Torbinho
评论会员:游客 时间:2011/12/14
SplitButton和CommandLinkXP上不工作,他们不显示在所有。它会采取什么来解决这个问题呢?(例如将回落到一个普通按钮?)
亚历山STANCIU
评论会员:游客 时间:2011/12/14
检查版本的操作系统(主要)是GT;前5应用Vista的特定代码
尼古拉斯关
评论会员:游客 时间:2011/12/14
是可以隐藏垂直线,当我使用一个详细的ListViewVista资源管理器风格?也许我们可以改变这些线的颜色?编辑:我固定自己:Vista资源管理器风格的垂直网格线使用背景图像disapeared上周一,2008年10月27日下午03:14修改
尼古拉斯关
评论会员:游客 时间:2011/12/14
任何关于如何与像WindowsVista的资源管理器中的ListView一些漂亮的每列排序/组功能的想法?imgsrc=http://www.orcode.com/upimg/2011_12_14_12_57_35_15.gif
logan1337
评论会员:游客 时间:2011/12/14
您可以通过VisualStudio中,使用设计。修改2008年3月2日(星期日),5:57
尼古拉斯关
评论会员:游客 时间:2011/12/14
您好,第一:你的项目是伟大的!BR}我的问题:我的程序一个开源控件库,他们所有的WindowsVista包含控制。我会用你的源代码稍加修改(唯一的命名空间和类名)控件库。我能这样做吗?我的网站:朱利安w.de(对不起,我不好英语,我从德国了)
wyDay
评论会员:游客 时间:2011/12/14
你可以做你想要什么都的代码,整合它,毕竟它把一些产品等,是不是本文的重点?imgsrc=http://www.orcode.com/upimg/2011_12_14_12_57_35_16.gif
logan1337
评论会员:游客 时间:2011/12/14
感谢你answere。我的网站:朱利安w.de(对不起,我不好英语,我从德国了)
Jereck
评论会员:游客 时间:2011/12/14
有谁知道如何一个Vista菜单的菜单项添加图标?目前我使用。NET中ToolStrips,但他们期待下Vista的可怕,想使用标准的系统菜单。我可以切换到一个老式的(VS2003)MainMenu控制,但它的项目不支持图标,因此是不够的,因为几乎所有我的菜单项图标。我注意到在资源管理器(例如,在"组织"菜单),这些系统菜单其实支持图标......问题是如何得到这个。。NET即使我已经使用Win32互操作,这怎么可能完成?任何想法?{O,O}。OO(有人说的MouseDown?)|)""???{BR}-??????{BR}
Prone2Moan
评论会员:游客 时间:2011/12/14
如果微软提供更多的文档......那么这将容易得多。我没有任何显示图标toolstrips的方法。然而,它似乎,微软使用了类似的技术,在WindowsXP中的上下文菜单。