设为首页 收藏本站
查看: 922|回复: 0

[经验分享] 在C#中轻松制作仿OutLook的界面

[复制链接]

尚未签到

发表于 2015-9-13 07:28:14 | 显示全部楼层 |阅读模式
  不知道从什么时候开始,许多软件都开始模仿OutLook界面,最典型的莫过于大家经常使用的QQ了,在网上搜索了好久,都没有找到几个满意的控件,干脆,自己写了一个,非常简单实用,特拿出来共享。
  新建一个项目,不妨取名为MyOutLookFace吧,在上面放一个Panel控件用作容器,取名为:panFunMain,设置Dock属性为Left(或Righ),设置BorderStyle属性为Fixed3D,添加一个ImageList控件,设置其ImageSize为“32,32”,并添加几个图标给它。
  在panFunMain中添加n个按钮(本例中n=3,用于显示有几组)和n个ListView控件(显示某组中具体内容),都用其默认的名字,注意ListView控件个数必须和按钮控件个数相同,都为n,设置各ListView控件的Lage imageList属性为刚才添加的ImageList控件,选中第一个ListView控件,在属性窗口中,选择items,并点右边的小按钮“ ”,将弹出一个对话框,在这里添加几个成员,并指定Text属性和ImageIndex属性,同样,为第二、三个ListView指定Items成员。
  为了实现自动隐藏,再添加一个计时器,最后布局如下:
  
  上面的插操作都是比较基本的,如不特殊说明,都使用其默认值,这里不再赘述。
  本文最后还会提到播放声音的方法,为合理利用资源,必须修改文件输出路径,选择菜单“项目”→“属性”,会弹出如下一个对话框,在“配置(C)”后面的组合框中选择“所有配置”,然后设置“配置属性”的“生成”项,在右边的输出路径中填上“output\”,这样,无论是编译成release文件还是debug文件,输出的可执行文件都会放到当前项目中的output文件夹下(该文件会自动创建)。
  
  至此,界面布置基本完成,切换到代码窗口,添加几个变量:
          /// <summary>
          /// 记录当前功能面板中用到的按钮
          /// </summary>
          private ArrayList ArrFunButton=new ArrayList();
  
          /// <summary>
          /// 记录当前功能面板中用到的listview
          /// </summary>
          private ArrayList ArrFunListView=new ArrayList();
          /// <summary>
          /// 功能面板的宽度
          /// </summary>
          private int m_nPanFunWidth=100;
          //功能面板隐藏后的宽度
          private int m_nPanFunHideWidth=2;
  当我们单击一个按钮后,必须显示该按钮对应的ListView,并调整该按钮的位置,故手工写一个函数:
  
               //功能按钮点击后的特效
          private void btnFun_Click(object sender, System.EventArgs e)
          {
               Button btnNow=sender as Button;
               if(btnNow==null)
                    return;
  
               //单击的按钮在数组中的索引
               int nIndex=this.ArrFunButton.IndexOf(btnNow);
               //将该按钮前面的置顶
               for(int i=1;i<=nIndex;i++)
               {
                    Button btn=ArrFunButton as Button;
                    btn.Top=((Button)ArrFunButton[i-1]).Bottom;
                    btn.Anchor=System.Windows.Forms.AnchorStyles.Left |System.Windows.Forms.AnchorStyles.Top;
               }
               //将下面的按钮下移
               for(int i=ArrFunButton.Count-1;i>nIndex;i--)
               {
                    Button btn=ArrFunButton as Button;
                    if(i==ArrFunButton.Count-1)//最后一个
                        btn.Top=this.panFunMain.Height-btn.Height-4;
                    else
                        btn.Top=((Button)ArrFunButton[i+1]).Top-btn.Height;
                    btn.Anchor=System.Windows.Forms.AnchorStyles.Left |System.Windows.Forms.AnchorStyles.Bottom;
  
               }
  
               //显示对应的listview
               for(int i=0;i<ArrFunButton.Count;i++)
               {
                    ListView lsv=ArrFunListView as ListView;
                    //当前按钮对应的ListView
                    if(i==nIndex)
                    {
                        lsv.Left=0;
                        lsv.Width=btnNow.Width;
                        lsv.Top=btnNow.Bottom;
  
                        if(nIndex==ArrFunListView.Count-1)//最后一个
                             lsv.Height=this.panFunMain.Height-btnNow.Bottom-4;
                        else
                             lsv.Height=(ArrFunButton[i+1] as Button).Top-btnNow.Bottom;
                        //将当前ListView显示出来
                        if(!lsv.Visible)
                             lsv.Visible=true;
                    }
                    else //隐藏其他listview
                    {
                        if(lsv.Visible)
                             lsv.Visible=false;
                    }
               }
  
          }
  当我们双击ListView的图标时,应用程序会根据你双击的具体项做相应处理,如QQ中弹出&#8220;发送消息&#8221;的对话框,我们这里只是简单地提示一句你双击的是哪一项,为此,也是手工添加一个函数:
          //双击listview后根据当前项执行操作
          private void lsvFun_DoubleClick(object sender, System.EventArgs e)
          {
               //双击后执行一个功能
               ListView lsv=sender as ListView;
               if(lsv==null)
                    return;
               if(lsv.SelectedItems.Count==0)
                    return;
               ListViewItem item=lsv.SelectedItems[0];
               MessageBox.Show("你双击了:"+item.Text);
          }
  本例中设置自动隐藏功能,隐藏后(宽度为nPanFunHideWidth),如果鼠标在本工具条(也就是本例中的panFunMain中的全部内容)上移动时,重新将工具条显示出来,因此,手工添加一个鼠标移动事件响应函数:
          private void FunListView_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
          {
               if(this.panFunMain.Width==m_nPanFunHideWidth)
               {
                    this.panFunMain.Width=m_nPanFunWidth;
                    this.timer1.Enabled=true;
               }
       }
  为了达到自动隐藏的目的,我们设置了一个记时器,不断检测当前鼠标位置,如果不在工具条中,自将工具宽带设置为nPanFunHideWidth,起到隐藏的作用,当然,不能设置为0,否则鼠标移不上去就再也显示不出来了。添加计时器的响应代码:
          private void timer1_Tick(object sender, System.EventArgs e)
          {
               //当前功能面板显示出来
               if(this.panFunMain.Width==m_nPanFunWidth)
               {
                    //检查光标位置是否在面板内
                    Point p1=this.panFunMain.PointToScreen(new Point(0,0));
                    Point p2=this.panFunMain.PointToScreen(new Point(panFunMain.Right,panFunMain.Bottom));
                    Point pCur=Cursor.Position;//当前鼠标光标位置
                    if(pCur.X<p1.X || pCur.X>p2.X || pCur.Y<p1.Y || pCur.Y>p2.Y)
                    {
                        //隐藏panfunmain
                        this.panFunMain.Width=m_nPanFunHideWidth;
                        this.timer1.Enabled=false;
                    }
               }//if
       }
  前面都是准备工作,添加一个函数,将上面的代码同具体的按钮和Listview控件组合起来:
                        /// <summary>
          /// 初始化功能面板
          /// </summary>
          private void InitPanFun()
          {
               //设置功能面板的位置和宽带
               this.panFunMain.Width=m_nPanFunWidth;
               this.panFunMain.Dock=DockStyle.Left;
               //记录功能按钮
               ArrFunButton.Add(this.button1);
               ArrFunButton.Add(this.button2);
               ArrFunButton.Add(this.button3);
  
               //记录功能面板中的listview,注意要和上面的button对应
               ArrFunListView.Add(this.listView1);
               ArrFunListView.Add(this.listView2);
               ArrFunListView.Add(this.listView3);
  
               int nCount=ArrFunButton.Count;
               //布置各功能按钮的位置和ListView的属性
               for(int i=nCount-1;i>=0;i--)
               {
                    Button btn=ArrFunButton as Button;
                    btn.Width=this.panFunMain.Width-4;
                    btn.Left=0;
  
                    //将按钮的单击事件和具体代码对应起来
                    btn.Click += new System.EventHandler(btnFun_Click);
                    if(i==0)
                    {
                        btn.Top=0;
                        btn.Anchor=AnchorStyles.Left |AnchorStyles.Top;
                    }
                    else
                    {
                        if(i==nCount-1)
                             btn.Top=this.panFunMain.Height-btn.Height-4;
                        else
                             btn.Top=(ArrFunButton[i+1] as Button).Top-btn.Height;
                        btn.Anchor=AnchorStyles.Left | AnchorStyles.Bottom;
                    }
                    //鼠标在按钮上移动时,同样判断当前工具条是否隐藏
                    btn.MouseMove+=new MouseEventHandler(FunListView_MouseMove);
  
                    //设置listview的anchor属性
                    ListView lsv=ArrFunListView as ListView;
                    if(lsv!=null)
                    {
                        lsv.Anchor=AnchorStyles.Left | AnchorStyles.Top |
                             AnchorStyles.Right |AnchorStyles.Bottom;
                        //隐藏功能listview
                        lsv.Visible=false;
                        //设置listview双击事件
                        lsv.DoubleClick+=new EventHandler(lsvFun_DoubleClick);
                        lsv.MouseMove+=new MouseEventHandler(FunListView_MouseMove);
  
                    }//pan
               }//for int i
  
               //将第一个功能按钮点一下
               (ArrFunButton[0] as Button).PerformClick();
               //别忘了打开记时器
               this.timer1.Enabled=true;
          }
  
  最后,添加Form1的Load事件响应函数,用来初始化工具条:
          private void Form1_Load(object sender, System.EventArgs e)
          {
               this.InitPanFun();
          }
  现在运行一下,效果是不是很不错?单击按钮时,会显示不同的分组,当鼠标离开窗口左边时,工具自动隐藏,在左边移动时,工具自动出现,双击ListView某图标后,会弹出一个对话框,告诉你点了哪一项,如下图:
  
  通过设置panFunMain的Dock属性,可以让本工具条在停泊在窗口的左边或右边,本例中代码的通用性较强(当然,如果能做成控件就更好了),很容易复制到新的软件中,上面的自动隐藏是模仿QQ做的,我们还可以做得更象QQ一点,当用户点了分组按钮后,播放一个声音,如果你安装了QQ,将其安装路径中sound文件夹下面的folder.wav声音文件复制到本项目的output文件夹中(也就是本项目EXE文件输出路径中),其中播放/停止声音的代码如下:
                    [DllImport("winmm.dll")]
          public static extern long mciSendString(string lpstrCommand,string lpstrReturnString,long length,long hwndcallback);
          /// <summary>
          /// 播放音乐文件
          /// </summary>
          /// <param name="p_FileName">音乐文件名称</param>
          private void PlayMusic(string p_FileName)
          {
               try
               {
                    mciSendString(@"close " +p_FileName ,"                                  ",0,0);
                    mciSendString(@"open " + p_FileName,"                                  ",0,0);
                    mciSendString(@"play " + p_FileName ,"                                  ",0,0);
               }
               catch
               {
               }
  
          }
        
          /// <summary>
          /// 停止当前音乐播放
          /// </summary>
          /// <param name="p_FileName">音乐文件名称</param>
          private void StopMusic(string p_FileName)
          {
               try
               {
                    mciSendString(@"close " + p_FileName,"                                  ",0,0);
               }
               catch{}
  
  由于使用了API函数,别忘了在前门添加一个应用:
  using System.Runtime.InteropServices;
  当然在,为了能播放声音,在private void btnFun_Click(object sender, System.EventArgs e)事件中加入下面两句:
               //播放声音,由于文件路径中可能有空格,因此,文件要用引号引起来
               string strFileName="\""+Application.StartupPath+"\\folder.wav"+"\"";
               this.PlayMusic(strFileName);

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-112795-1-1.html 上篇帖子: JavaScript API for Office Outlook Add-in 下篇帖子: Outlook 2007: Accounts and data files 帐户和数据文件
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表