WPF实现类似360安全卫士界面的程序源码分享
下面通过图文并茂的方式给大家介绍wpf实现类似360安全卫士界面的程序源码分享,点击此处下载源码哦。
以前学习windows form编程的时候,总感觉自己做的界面很丑,看到360安全卫士、迅雷等软件的ui设计都非常美观,心里总是憧憬着要是自己能实现这样的ui效果该多好!!!另一个困扰我的问题是,这个ui皮肤是如何用技术实现的呢?!虽然好多年过去了,但心里的憧憬和疑惑一直没有消失,而且越来越强烈。在日常的工作和学习中,自己在网上也经常留意类似的技术或者文章。最近在学习wpf的过程中,看到网上也有仿360和仿迅雷ui设计的资源,通过对资源的学习和自己的动手实践,终于实现了下面的仿360安全卫士界面:
由于项目文件比较多,这里罗列出核心的过程和代码:
1、vs解决方案结构:
wpfpagetransitions是一个wpf类库,实现ui页面切换动画效果,支持多种动画,可以通过transitiontype属性进行设置,其原理是定义了多个切换动画类型的storyboard,程序根据配置的transitiontype去执行匹配的storyboard动画(分出入动画,xxxxxxin和xxxxxxout)。360ui是一个wpf 桌面应用程序,styles文件夹下存放了定义的按钮样式、菜单项样式、页签样式等样式和需要的所有ui切图资源。pages文件夹下存放切换的详细子页面。
(备注:图片资源和部分文件来自互联网,特别感谢kxfang360项目提供的360整套配图和布局文件)
2、页面切换控件核心代码:
<usercontrol x:class="wpfpagetransitions.pagetransition" xmlns="http://schemas.microsoft.com/winfx//xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx//xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/" xmlns:d="http://schemas.microsoft.com/expression/blend/" xmlns:local="clr-namespace:wpfpagetransitions" mc:ignorable="d" d:designheight="" d:designwidth=""> <usercontrol.resources> <style targettype="{x:type contentpresenter}"> <setter property="layouttransform"> <setter.value> <scaletransform /> </setter.value> </setter> </style> <local:centerconverter x:key="centerconverter"/> <!-- slide and fade --> <storyboard x:key="slideandfadein" > <thicknessanimation duration="::." storyboard.targetproperty="margin" from=",,-," to="" decelerationratio="." /> <doubleanimation duration="::." storyboard.targetproperty="opacity" from="" to="" /> </storyboard> <storyboard x:key="slideandfadeout"> <thicknessanimation duration="::." storyboard.targetproperty="margin" to="-,,," accelerationratio="."/> <doubleanimation duration="::." storyboard.targetproperty="opacity" to="" /> </storyboard> <!-- fade --> <storyboard x:key="fadein" > <doubleanimation duration="::." storyboard.targetproperty="opacity" from="" to="" /> </storyboard> <storyboard x:key="fadeout"> <doubleanimation duration="::." storyboard.targetproperty="opacity" to="" /> </storyboard> <!-- slide --> <storyboard x:key="slidein" > <thicknessanimation duration="::." storyboard.targetproperty="margin" from=",,-," to="" decelerationratio="." /> </storyboard> <storyboard x:key="slideout"> <thicknessanimation duration="::." storyboard.targetproperty="margin" to="-,,," accelerationratio="."/> </storyboard> <!-- grow --> <storyboard x:key="growin" > <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scalex)" from="" to="" duration="::." decelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scaley)" from="" to="" duration="::." decelerationratio="." /> </storyboard> <storyboard x:key="growout"> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scalex)" to="" duration="::." accelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scaley)" to="" duration="::." accelerationratio="." /> </storyboard> <!-- grow and fade --> <storyboard x:key="growandfadein" > <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scalex)" from="" to="" duration="::." decelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scaley)" from="" to="" duration="::." decelerationratio="." /> <doubleanimation duration="::." storyboard.targetproperty="opacity" from="" to="" /> </storyboard> <storyboard x:key="growandfadeout"> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scalex)" to="" duration="::." accelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scaley)" to="" duration="::." accelerationratio="." /> <doubleanimation duration="::." storyboard.targetproperty="opacity" to="" /> </storyboard> <!-- flip --> <storyboard x:key="flipin" > <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(skewtransform.anglex)" from="-" to="" duration="::." decelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(skewtransform.angley)" from="-" to="" duration="::." decelerationratio="." /> </storyboard> <storyboard x:key="flipout"> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(skewtransform.anglex)" to="" duration="::." accelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(skewtransform.angley)" to="" duration="::." accelerationratio="." /> </storyboard> <!-- flip and fade --> <storyboard x:key="flipandfadein" > <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(skewtransform.anglex)" from="-" to="" duration="::." decelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(skewtransform.angley)" from="-" to="" duration="::." decelerationratio="." /> <doubleanimation duration="::." storyboard.targetproperty="opacity" from="" to="" /> </storyboard> <storyboard x:key="flipandfadeout"> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(skewtransform.anglex)" to="" duration="::." accelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(skewtransform.angley)" to="" duration="::." accelerationratio="." /> <doubleanimation duration="::." storyboard.targetproperty="opacity" to="" /> </storyboard> <!-- spin --> <storyboard x:key="spinin" > <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(rotatetransform.angle)" from="-" to="" duration="::." decelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scalex)" from="" to="" duration="::." decelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scaley)" from="" to="" duration="::." decelerationratio="." /> </storyboard> <storyboard x:key="spinout"> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(rotatetransform.angle)" to="" duration="::." accelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scalex)" to="" duration="::." accelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scaley)" to="" duration="::." accelerationratio="." /> </storyboard> <!-- spin and fade --> <storyboard x:key="spinandfadein" > <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(rotatetransform.angle)" from="-" to="" duration="::." decelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scalex)" from="" to="" duration="::." decelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scaley)" from="" to="" duration="::." decelerationratio="." /> <doubleanimation duration="::." storyboard.targetproperty="opacity" from="" to="" /> </storyboard> <storyboard x:key="spinandfadeout"> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(rotatetransform.angle)" to="" duration="::." accelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scalex)" to="" duration="::." accelerationratio="." /> <doubleanimation storyboard.targetproperty="(rendertransform).(transformgroup.children)[].(scaletransform.scaley)" to="" duration="::." accelerationratio="." /> <doubleanimation duration="::." storyboard.targetproperty="opacity" to="" /> </storyboard> </usercontrol.resources> <grid name="page"> <contentcontrol name="contentpresenter" > <contentcontrol.rendertransform> <transformgroup> <scaletransform scalex="" scaley="" centerx="{binding relativesource={relativesource ancestortype=grid, mode=findancestor}, path=actualwidth, converter={staticresource centerconverter}}" centery="{binding relativesource={relativesource ancestortype=grid, mode=findancestor}, path=actualheight, converter={staticresource centerconverter}}" /> <skewtransform anglex="" angley="" centerx="{binding relativesource={relativesource ancestortype=grid, mode=findancestor}, path=actualwidth, converter={staticresource centerconverter}}" centery="{binding relativesource={relativesource ancestortype=grid, mode=findancestor}, path=actualheight, converter={staticresource centerconverter}}" /> <rotatetransform angle="" centerx="{binding relativesource={relativesource ancestortype=grid, mode=findancestor}, path=actualwidth, converter={staticresource centerconverter}}" centery="{binding relativesource={relativesource ancestortype=grid, mode=findancestor}, path=actualheight, converter={staticresource centerconverter}}" /> <translatetransform x="" y="" /> </transformgroup> </contentcontrol.rendertransform> </contentcontrol> </grid> </usercontrol> using system; using system.collections.generic; using system.linq; using system.text; using system.windows; using system.windows.controls; using system.windows.data; using system.windows.documents; using system.windows.input; using system.windows.media; using system.windows.media.imaging; using system.windows.navigation; using system.windows.shapes; using system.threading.tasks; using system.windows.media.animation; namespace wpfpagetransitions { public partial class pagetransition : usercontrol { stack<usercontrol> pages = new stack<usercontrol>(); public usercontrol currentpage { get; set; } public static readonly dependencyproperty transitiontypeproperty = dependencyproperty.register("transitiontype", typeof(pagetransitiontype), typeof(pagetransition), new propertymetadata(pagetransitiontype.slideandfade)); public pagetransitiontype transitiontype { get { return (pagetransitiontype)getvalue(transitiontypeproperty); } set { setvalue(transitiontypeproperty, value); } } public pagetransition() { initializecomponent(); } public void showpage(usercontrol newpage) { pages.push(newpage); task.factory.startnew(() => shownewpage()); } void shownewpage() { dispatcher.invoke((action)delegate { if (contentpresenter.content != null) { usercontrol oldpage = contentpresenter.content as usercontrol; if (oldpage != null) { oldpage.loaded -= newpage_loaded; unloadpage(oldpage); } } else { shownextpage(); } }); } void shownextpage() { usercontrol newpage = pages.pop(); newpage.loaded += newpage_loaded; contentpresenter.content = newpage; } void unloadpage(usercontrol page) { storyboard hidepage = (resources[string.format("{}out", transitiontype.tostring())] as storyboard).clone(); hidepage.completed += hidepage_completed; hidepage.begin(contentpresenter); } void newpage_loaded(object sender, routedeventargs e) { storyboard shownewpage = resources[string.format("{}in", transitiontype.tostring())] as storyboard; shownewpage.begin(contentpresenter); currentpage = sender as usercontrol; } void hidepage_completed(object sender, eventargs e) { contentpresenter.content = null; shownextpage(); } } }
3、like360main核心代码为:
其中allowstransparency="true" windowstyle="none" background="{x:null}"的目的是让wpf窗体隐藏默认的边框,这样可以允许用背景图片填充wpf定义窗体外观。在这区间可以自定义关闭、最小化和最大化按钮等。
mouseleftbuttondown="window_mouseleftbuttondown" 目的是为了支持窗体拖动。fontfamily="simsun" textoptions.textformattingmode="display"的目的是为了解决wpf中文字体显示模糊的问题。
<window x:class="_ui.likemain" xmlns="http://schemas.microsoft.com/winfx//xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx//xaml" title="likemain" height="" width="" fontfamily="simsun" allowstransparency="true" windowstyle="none" xmlns:pagetransitions="clr-namespace:wpfpagetransitions;assembly=wpfpagetransitions" background="{x:null}" mouseleftbuttondown="window_mouseleftbuttondown" textoptions.textformattingmode="display" > <window.resources> <lineargradientbrush x:key="mybrush" endpoint=".," startpoint=".,"> <gradientstop color="#cfffffff"/> <gradientstop color="#ffebdd" offset=""/> </lineargradientbrush> </window.resources> <border borderbrush="black" borderthickness="" cornerradius="" margin=""> <border.effect> <dropshadoweffect shadowdepth="" opacity="."/> </border.effect> <border.background> <imagebrush imagesource="styles/skin/frame.jpg"/> </border.background> <grid> <grid.rowdefinitions> <rowdefinition height="."/> <rowdefinition height="."/> <rowdefinition/> <rowdefinition height="."/> </grid.rowdefinitions> <!--上标题栏--> <label content="安全卫士界面" horizontalalignment="left" width="." foreground="#aeff" fontweight="bold" textoptions.textformattingmode="display"/> <rectangle margin="" stroke="black" horizontalalignment="right" width="." grid.row="" strokethickness=""> <rectangle.fill> <imagebrush imagesource="styles/skin/logo.png" stretch="uniform"/> </rectangle.fill> </rectangle> <button content="x" horizontalalignment="right" margin=",,.," style="{dynamicresource sysbuttonstyle}" width="." name="closebutton" click="closebutton_click" /> <button content="max" horizontalalignment="right" margin=",,.," style="{dynamicresource maxbuttonstyle}" width="." name="maxbutton" click="maxbutton_click"> <button.background> <imagebrush imagesource="styles/skin/button/max.png" stretch="uniform"/> </button.background> </button> <button content="mni" horizontalalignment="right" margin=",,.," style="{dynamicresource maxbuttonstyle}" width="." name="mnibutton" click="mnibutton_click"> <button.background> <imagebrush imagesource="styles/skin/button/mni.png" stretch="uniform"/> </button.background> </button> <button x:name="menubutton" horizontalalignment="right" margin=",,.," style="{dynamicresource mbuttonstyle}" width="." click="menubutton_click"> <button.background> <imagebrush imagesource="styles/skin/button/m.png" stretch="uniform"/> </button.background> </button> <popup x:name="menu" allowstransparency="true" margin=",-,," placementtarget="{binding elementname=menubutton}" staysopen="false" popupanimation="scroll"> <grid height="." width="" margin="" horizontalalignment="left"> <border borderthickness="" cornerradius="" background="#ffefefef" margin=""> <border.effect> <dropshadoweffect shadowdepth="" opacity="."/> </border.effect> <stackpanel margin=","> <menuitem header="设 置" style="{dynamicresource menuitemstyle}"/> <menuitem header="更 新"/> <menuitem header="关 于"/> <menuitem header="退 出"/> </stackpanel> </border> </grid> </popup> <rectangle stroke="black" strokethickness="" width="" margin=",,.,." horizontalalignment="right" height=""> <rectangle.fill> <lineargradientbrush endpoint=".," startpoint=".,"> <gradientstop color="#"/> <gradientstop offset="" color="#addd"/> </lineargradientbrush> </rectangle.fill> </rectangle> <rectangle stroke="black" strokethickness="" width="" margin=",,.,." horizontalalignment="right" height=""> <rectangle.fill> <lineargradientbrush endpoint=".," startpoint=".,"> <gradientstop color="#"/> <gradientstop offset="" color="#addd"/> </lineargradientbrush> </rectangle.fill> </rectangle> <rectangle stroke="black" strokethickness="" width="" margin=",,.,." horizontalalignment="right" height=""> <rectangle.fill> <lineargradientbrush endpoint=".," startpoint=".,"> <gradientstop color="#"/> <gradientstop offset="" color="#addd"/> </lineargradientbrush> </rectangle.fill> </rectangle> <rectangle height="" margin=",,.," stroke="black" strokethickness="" verticalalignment="top"> <rectangle.fill> <lineargradientbrush endpoint=".," startpoint=".,"> <gradientstop color="#ffffff"/> <gradientstop offset="" color="#addd"/> </lineargradientbrush> </rectangle.fill> </rectangle> <!--上导航栏--> <tabcontrol name="tab" grid.rowspan="" margin="" style="{dynamicresource tabcontrolstyle}" grid.row="" background="{x:null}" selectionchanged="tabcontrol_selectionchanged"> <tabitem header="电脑体验" height="" margin=",,," width="" style="{dynamicresource tabitemstyle}" textoptions.textformattingmode="display"> <tabitem.background> <imagebrush imagesource="styles/skin/ico/ico_examine.png"/> </tabitem.background> <grid margin="" background="{dynamicresource mybrush}"> <grid.columndefinitions> <columndefinition width=".*"/> <columndefinition width=".*"/> <columndefinition width=".*"/> </grid.columndefinitions> <grid.rowdefinitions> <rowdefinition height="."/> <rowdefinition height="."/> <rowdefinition height="."/> <rowdefinition height="."/> </grid.rowdefinitions> <!--详细--> <label content="电脑体检" horizontalalignment="left" margin="" width="." height="" fontsize="." fontweight="bold" grid.column="" grid.row="" grid.columnspan="" /> <pagetransitions:pagetransition name="ptransitioncontrol_" margin="" transitiontype="slideandfade" grid.column="" grid.row="" grid.columnspan="" grid.rowspan=""/> </grid> </tabitem> <tabitem header="查杀木马" height="" margin=",,," width="" style="{dynamicresource tabitemstyle}"> <tabitem.background> <imagebrush imagesource="styles/skin/ico/ico_dsmain.png"/> </tabitem.background> <grid margin="" background="{dynamicresource mybrush}"> <grid.columndefinitions> <columndefinition width=".*"/> <columndefinition width=".*"/> <columndefinition width=".*"/> </grid.columndefinitions> <grid.rowdefinitions> <rowdefinition height="."/> <rowdefinition height="."/> <rowdefinition height="."/> <rowdefinition height="."/> </grid.rowdefinitions> <!--详细--> <label content="查杀木马" horizontalalignment="left" margin="" width="." height="" fontsize="." fontweight="bold" grid.column="" grid.row="" grid.columnspan="" /> <pagetransitions:pagetransition name="ptransitioncontrol_" margin="" transitiontype="slideandfade" grid.column="" grid.row="" grid.columnspan="" grid.rowspan=""/> </grid> </tabitem> <tabitem header="清理插件" height="" margin=",,," width="" style="{dynamicresource tabitemstyle}"> <tabitem.background> <imagebrush imagesource="styles/skin/ico/ico_plugincleaner.png"/> </tabitem.background> <grid margin="" background="{dynamicresource mybrush}"> <grid.columndefinitions> <columndefinition width=".*"/> <columndefinition width=".*"/> <columndefinition width=".*"/> </grid.columndefinitions> <grid.rowdefinitions> <rowdefinition height="."/> <rowdefinition height="."/> <rowdefinition height="."/> <rowdefinition height="."/> </grid.rowdefinitions> <!--详细--> <label content="清理插件" horizontalalignment="left" margin="" width="." height="" fontsize="." fontweight="bold" grid.column="" grid.row="" grid.columnspan="" /> <pagetransitions:pagetransition name="ptransitioncontrol_" margin="" transitiontype="slideandfade" grid.column="" grid.row="" grid.columnspan="" grid.rowspan=""/> </grid> </tabitem> <tabitem header="修复漏洞" height="" margin=",,," width="" style="{dynamicresource tabitemstyle}"> <tabitem.background> <imagebrush imagesource="styles/skin/ico/ico_vulrepair.png"/> </tabitem.background> <grid background="{dynamicresource mybrush}"/> </tabitem> <tabitem header="清理垃圾" height="" margin=",,," width="" style="{dynamicresource tabitemstyle}"> <tabitem.background> <imagebrush imagesource="styles/skin/ico/ico_rubbishcleaner.png"/> </tabitem.background> <grid background="{dynamicresource mybrush}"/> </tabitem> <tabitem header="清理痕迹" height="" margin=",,," width="" style="{dynamicresource tabitemstyle}"> <tabitem.background> <imagebrush imagesource="styles/skin/ico/ico_tracecleaner.png"/> </tabitem.background> <grid background="{dynamicresource mybrush}"/> </tabitem> <tabitem header="系统修复" height="" margin=",,," width="" style="{dynamicresource tabitemstyle}"> <tabitem.background> <imagebrush imagesource="styles/skin/ico/ico_sysrepair.png"/> </tabitem.background> <grid background="{dynamicresource mybrush}"/> </tabitem> <tabitem header="功能大全" height="" margin=",,," width="" style="{dynamicresource tabitemstyle}"> <tabitem.background> <imagebrush imagesource="styles/skin/ico/ico_advtools.png"/> </tabitem.background> <grid background="{dynamicresource mybrush}"/> </tabitem> <tabitem header="软件管家" height="" margin=",,," width="" style="{dynamicresource tabitemstyle}"> <tabitem.background> <imagebrush imagesource="styles/skin/ico/ico_softmgr.png"/> </tabitem.background> <grid background="{dynamicresource mybrush}"/> </tabitem> </tabcontrol> <!--导航详细--> <!--下状态栏--> <label content="欢迎使用仿系统" margin="" grid.row="" foreground="#aeff" fontweight="bold" borderthickness="" borderbrush="white" horizontalalignment="left" width="." textoptions.textformattingmode="display" /> <label content="已连接网络" margin="" grid.row="" foreground="#aeff" fontweight="bold" borderthickness="" borderbrush="white" horizontalalignment="right" width="" textoptions.textformattingmode="display" /> </grid> </border> </window> using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; using system.windows; using system.windows.controls; using system.windows.data; using system.windows.documents; using system.windows.input; using system.windows.media; using system.windows.media.imaging; using system.windows.shapes; namespace _ui { /// <summary> /// likemain.xaml 的交互逻辑 /// </summary> public partial class likemain : window { public likemain() { initializecomponent(); } private void closebutton_click(object sender, routedeventargs e) { this.close(); } private void maxbutton_click(object sender, routedeventargs e) { if (windowstate == windowstate.normal) windowstate = windowstate.maximized; else windowstate = windowstate.normal; } private void mnibutton_click(object sender, routedeventargs e) { this.windowstate = windowstate.minimized; } private void menubutton_click(object sender, routedeventargs e) { menu.isopen = true; } private void window_mouseleftbuttondown(object sender, mousebuttoneventargs e) { //拖动 this.dragmove(); } private void tabcontrol_selectionchanged(object sender, selectionchangedeventargs e) { int index = this.tab.selectedindex; if (index == ) { //可以设置transitiontype wpfpage 来更改界面出入的动画效果 //this.ptransitioncontrol_.transitiontype = wpfpagetransitions.pagetransitiontype.spinandfade; pages.index newpage = new pages.index(); this.ptransitioncontrol_.showpage(newpage); } else if (index == ) { pages.scan newpage = new pages.scan(); this.ptransitioncontrol_.showpage(newpage); } else if (index == ) { pages.scan newpage = new pages.scan(); this.ptransitioncontrol_.showpage(newpage); } else { pages.index newpage = new pages.index(); this.ptransitioncontrol_.showpage(newpage); } } } }
当用户单击tab页签时(切换事件),程序 用pages.index newpage = new pages.index();先实例化一个page子页面(实际继承usercontrol),然后调用 this.ptransitioncontrol_1.showpage(newpage);将子页面进行加载(本质上是ptransitioncontrol_1.content=newpage)。
4、运行代码,界面如下:
下面是360安全卫士界面截图,可对比一下,还是比较相似的。
上一篇: 三种C/C++创建文件夹和路径的方法
下一篇: 10个C#程序员经常用到的实用代码片段