好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

跟我做WinForm开发

跟我做WinForm开发

2012-01-07 12:03 by 空逸云, 3710 visits,  收藏 ,  编辑

前言

前阵子,学英文的时候听发音,意外之中发现Google的发音相比大部分TTS发音更准确,而且读句子也没有普通TTS那种一听就是机器人的声音,心血来潮,想利用Google发音做一个小软件,所以就有了本文。

这是最后的UI成品图,可以看到,没有了常见的按钮,也没有了常见的Title框,整个布局随心所欲,GDI+?No。下面,就带大家跟我一起来用最简单的方式开发你所期望的UI吧!

自定义窗体

WinForm开发中,我们都知道窗体和控件的作用,实际上,以上的UI实现也是通过自定义窗体和用户控件实现,那该如何做,才能让窗体变成我们所想要的样子呢?

首先,新建一个窗体,在这里,我命名为MainForm.cs,打开我们就可以见到以往的样子:

选中窗体,右键=》属性,将FormBorderStyle设置成None, 窗体就变成了右图所示;接着,我再将其拖拉成我需要的长度和宽度,此时若编译运行,会发现实际上什么都东西都看不到,这正是我们所需要的效果,接着,就防止我们想呈现的元素。接着,我将其拉成一个长方形,并在四周放4个PictureBox,正中间放一个Panel。

这里需要注意的就是4个PictureBox的宽度,长度和未知,实际上我也不是拖控件,而是通过修改控件是属性,这里就需要精确到像素,聪明的你应该想到它们就是4条边框线和中间的内容块了,在这里我推荐一个软件,MarkMan,传说中的标注神器,做UI方面,特别是开发人员,很有帮助。

在将所需的图片填充上去就可以了。

 private   Image   GetResourceImg(  string   name)
{
      return   Image  .  FromStream(  Assembly  .  GetExecutingAssembly()  .  GetManifestResourceStream(name));
}
 
 void   InitFormStyle()
{
      //边框
      var   borderImg   =   GetResourceImg(  @"Speaker.Resource.Images.border.jpg"  );
      Bitmap   borderMap   =   new   Bitmap  (borderImg);
    borderMap  .  MakeTransparent(  Color  .  FromArgb(  255  ,   0  ,   255  ));
      this  .  pb_borderLeft  .  BackgroundImage   =   borderMap;
      this  .  pb_borderRight  .  BackgroundImage   =   borderMap;
      this  .  pb_borderTop  .  BackgroundImage   =   borderMap;
      this  .  pb_borderBottom  .  BackgroundImage   =   borderMap;
      //主面板
      var   mainImg   =   GetResourceImg(  @"Speaker.Resource.Images.main.jpg"  );
      this  .  pl_main  .  BackgroundImage   =   new   Bitmap  (mainImg);
      //Logo
      var   logoImg   =   GetResourceImg(  @"Speaker.Resource.Images.logo.jpg"  );
      this  .  btn_setting  .  NormalImage   =   new   Bitmap  (logoImg);
    btn_setting  .  Reset();
      //Speak Button
      var   normalImg   =   GetResourceImg(  @"Speaker.Resource.Images.button.png"  );
      var   moveImg   =   GetResourceImg(  @"Speaker.Resource.Images.buttonMove.png"  );
      var   downImg   =   GetResourceImg(  @"Speaker.Resource.Images.buttonDown.png"  );
    btn_speak  .  NormalImage   =   normalImg;
    btn_speak  .  MoveImage   =   moveImg;
    btn_speak  .  DownImage   =   downImg;
    btn_speak  .  Reset();
}
 

编译通过之后,边框雏形就出现了~:-)

自定义控件

窗体我们已经有了,接下来就是里面一些控件的实现,这里,我主要用到了两个控件,ImageButton和LightTextBox,顾名思义,ImageButton就是一个图片按钮,但它还提供鼠标按下,悬移时的图片选择;LightTextBox是一个TextBox,鼠标悬移的时候,边框高亮;

LightTextBox

新建用户控件LightTextBox,选中控件,右键=》属性,将BorderStyle改为None,这样,控件也不可见了!拖出一个TextBox,并标注为MultiLine,至此,UI就这样了,接着是控件的绘制编码;

 public   LightTextBox()
{
    SetStyle(  ControlStyles  .  OptimizedDoubleBuffer   |   ControlStyles  .  AllPaintingInWmPaint,   true  );
    InitializeComponent();
    BackColor   =   Color  .  Transparent;
    
    txt  .  Location   =   new   Point  (  3  ,   6  );
    txt  .  MouseEnter   +=   new   EventHandler  (txt_MouseEnter);
    txt  .  MouseLeave   +=   new   EventHandler  (txt_MouseLeave);
}
 

实现TextBox的鼠标悬移事件就是为了实现边框高亮效果;

 #region   Events

  void   txt_MouseLeave(  object   sender,   EventArgs   e)
{
    _isFouse   =   false  ;
      this  .  Invalidate();
}

  void   txt_MouseEnter(  object   sender,   EventArgs   e)
{
    _isFouse   =   true  ;
      this  .  Invalidate();
}
  #endregion
 

方法部分(控件实现的主要方法)

 #region   Methods
  protected override void   OnPaint(  PaintEventArgs   e)
{
      Graphics   g   =   e  .  Graphics;
    g  .  InterpolationMode   =   InterpolationMode  .  HighQualityBicubic;
    g  .  SmoothingMode   =   SmoothingMode  .  HighQuality;

    txt  .  Width   =   Width  -  6  ;
    CalculateSizeAndPosition();
    Draw(e  .  ClipRectangle, e  .  Graphics);


      base  .  OnPaint(e);
}

  private void   CalculateSizeAndPosition()
{
      if   (  !  txt  .  Multiline)
    {
        Height   =   txt  .  Height   +   9  ;
    }
      else
      {
        txt  .  Height   =   Height   -   9  ;
    }
}
  private void   Draw(  Rectangle   rectangle,   Graphics   g)
{

      #region   画背景
      using   (  SolidBrush   backgroundBrush   =   new   SolidBrush  (  Color  .  White))
    {
        g  .  FillRectangle(backgroundBrush,   2  ,   2  ,   this  .  Width   -   4  ,   this  .  Height   -   4  );
    }
      #endregion

    #region   画阴影(外边框)

      Color   drawShadowColor   =   _shadowColor;
      if   (  !  _isFouse)      //判断是否获得焦点
      {
        drawShadowColor   =   Color  .  Transparent;
    }
      using   (  Pen   shadowPen   =   new   Pen  (drawShadowColor))
    {
          if   (_radius   ==   0  )
        {
            g  .  DrawRectangle(shadowPen,   new   Rectangle  (rectangle  .  X, rectangle  .  Y, rectangle  .  Width   -   1  , rectangle  .  Height   -   1  ));
        }
          else
          {
            g  .  DrawPath(shadowPen,   DrawHelper  .  DrawRoundRect(rectangle  .  X, rectangle  .  Y, rectangle  .  Width   -   2  , rectangle  .  Height   -   1  , _radius));
        }
    }
      #endregion

    #region   画边框
      using   (  Pen   borderPen   =   new   Pen  (_borderColor))
    {
          if   (_radius   ==   0  )
        {
            g  .  DrawRectangle(borderPen,   new   Rectangle  (rectangle  .  X   +   1  , rectangle  .  Y   +   1  , rectangle  .  Width   -   3  , rectangle  .  Height   -   3  ));
        }
          else
          {
            g  .  DrawPath(borderPen,   DrawHelper  .  DrawRoundRect(rectangle  .  X   +   1  , rectangle  .  Y   +   1  , rectangle  .  Width   -   3  , rectangle  .  Height   -   2  , _radius));
        }
    }
      #endregion
  }

  #endregion
 

由于字段,属性比较多,我就不贴出来了,感兴趣的可以在后续的源码中查看;此时,若将该控件放到窗体中,鼠标移

动上去,则可发现边框有一层光晕;

ImageButton

这里的自定义控件实现方式一致,都先去掉了BorderStyle,再自己控制呈现内容,所以才能达到显示特殊UI的目的;ImageButton的UI设计就不详述了,直接放出后台实现主代码;

 public   ImageButton()
{
      this  .  SetStyle(  ControlStyles  .  AllPaintingInWmPaint   |   ControlStyles  .  OptimizedDoubleBuffer,   true  );
    InitializeComponent();
    Reset();
}

  #region   Methods
  public void   Reset()
{
      if   (_normalImage   !=   null  )
    {
          this  .  BackgroundImage   =   _normalImage;
          this  .  Size   =   new   Size  (_normalImage  .  Width, _normalImage  .  Height);
    }
}
  private void   MakeTransparent(  Image   image)
{
      Bitmap   bitmap   =   image   as   Bitmap  ;
    bitmap  .  MakeTransparent(  Color  .  FromArgb(  255  ,   0  ,   255  ));
}
  #endregion

  private void   ImageButton_MouseEnter(  object   sender,   EventArgs   e)
{
      if   (_moveImage   !=   null  )
          this  .  BackgroundImage   =   _moveImage;
}

  private void   ImageButton_MouseLeave(  object   sender,   EventArgs   e)
{
      this  .  BackgroundImage   =   _normalImage;
}

  private void   ImageButton_MouseDown(  object   sender,   MouseEventArgs   e)
{
      if   (_downImage   !=   null  )
          this  .  BackgroundImage   =   _downImage;
}

  private void   ImageButton_MouseUp(  object   sender,   MouseEventArgs   e)
{
      if   (_moveImage   !=   null  )
          this  .  BackgroundImage   =   _moveImage;
}
 
MainForm

万事俱备,只欠东风;把控件都放入MainForm中,并初始其状态即可(上面第一部分代码已放出);此时,编译运行;已达到我们预期的UI效果;但是,UI效果是有了,移动效果,缩小(点击任务栏图标)等却都失效了,该怎么办?Win32API千呼万唤使出来~

 private void   pl_main_MouseDown(  object   sender,   MouseEventArgs   e)
{
      if   (e  .  Button   ==   MouseButtons  .  Left)
    {
          Win32  .  ReleaseCapture();
          Win32  .  SendMessage(Handle,   274  ,   61440   +   9  ,   0  );
    }
}
 

这里实际上是调用了Win32API,在这里,又有一个好东西分享;平时做这些Win32API交互/C#与C++交互,需

要做类型转换,特别是C++里面一些指针什么的,很是纠结, http://clrinterop.codeplex.com 能帮到你;它能根据你输入的C++函数生成C#的代码;不可谓不是一大杀器啊!

移动解决了,那缩小的问题,也必须解决了;

 protected override   CreateParams   CreateParams
{
      get
      {
          const int   WS_MINIMIZEBOX   =   0x00020000  ;    // Winuser.h中定义
          CreateParams   cp   =   base  .  CreateParams;
        cp  .  Style   =   cp  .  Style   |   WS_MINIMIZEBOX;     // 允许最小化操作  
          return   cp;
    }
}
 

重写CreateParams属性就可以了;到这里,我们的应用已经能正常显示出我们所想要的UI;但还不够,大部

分辅助类型的软件都有最小化的功能,那,我们也将其加上去吧;

NotifyIcon

这个其实很简单,就是拖一个NotifyIcon到窗体中,并绑定一个ContextMenu到这个NotifyIcon中就可以了;然后在触发一些事件;

 private void   MainForm_Resize(  object   sender,   EventArgs   e)
{
      if   (WindowState   ==   FormWindowState  .  Minimized)
    {
          this  .  Visible   =   false  ;
    }
}
 

后面,我还主要用NotifyIcon来通知用户,做提示,错误提示等;到这里,整个UI方面就已经完成了;只

剩下后面的逻辑处理,就是输入句子能发音,并且支持快捷键屏幕取词等;

随笔分类 -C#

计算一个数字有多少种排列可能 2012-02-03 09:14 by 空逸云, 613 visits,  网摘 ,  收藏 ,  编辑

 

5 Comment Categories:  C#

跟我做WinForm开发(2)-后台逻辑操作 2012-01-08 12:32 by 空逸云, 2495 visits,  网摘 ,  收藏 ,  编辑

 

25 Comment Categories:  C#

跟我做WinForm开发(1)-自定义UI 2012-01-07 12:03 by 空逸云, 3711 visits,  网摘 ,  收藏 ,  编辑

 

72 Comment Categories:  C#

细说文件读写操作(读写锁) 2011-11-15 00:20 by 空逸云, 1580 visits,  网摘 ,  收藏 ,  编辑

 

17 Comment Categories:  C#

您真的了解类型转换吗?请止步,解惑! 2011-08-29 00:11 by 空逸云, 1888 visits,  网摘 ,  收藏 ,  编辑

 

32 Comment Categories:  C# ,  CLR

您真的了解类型转换吗?请止步,求解! 2011-08-24 23:57 by 空逸云, 3744 visits,  网摘 ,  收藏 ,  编辑

 

100 Comment Categories:  C#

基于AppDomain的"插件式"开发 2011-08-01 09:58 by 空逸云, 1921 visits,  网摘 ,  收藏 ,  编辑

 

38 Comment Categories:  C#

青梅煮酒论C#:Specification pattern 2011-01-16 13:56 by 空逸云, 1757 visits,  网摘 ,  收藏 ,  编辑

 

16 Comment Categories:  C#

你正确的使用Out/Ref了吗? 2010-12-03 19:19 by 空逸云, 379 visits,  网摘 ,  收藏 ,  编辑

 

6 Comment Categories:  C#

【More Effective C#】Partial Class是怎样炼成的? 2010-10-28 08:14 by 空逸云, 1949 visits,  网摘 ,  收藏 ,  编辑

 

13 Comment Categories:  C#

【More Effective C#】掩藏在Nullable<T>后的秘密 2010-10-27 08:19 by 空逸云, 1780 visits,  网摘 ,  收藏 ,  编辑

 

21 Comment Categories:  C#

【More Effective C#】IEnumerable和IQueryable的那点事 2010-10-22 08:08 by 空逸云, 2145 visits,  网摘 ,  收藏 ,  编辑

 

22 Comment Categories:  C# ,  LINQ

【More Effective C#】区分早期执行和晚期执行 2010-10-20 08:19 by 空逸云, 1739 visits,  网摘 ,  收藏 ,  编辑

 

11 Comment Categories:  C# ,  LINQ

【More Effective C#】Lambda表达式优化 2010-10-19 08:09 by 空逸云, 2673 visits,  网摘 ,  收藏 ,  编辑

 

38 Comment Categories:  C#

【More Effective C#】LINQ表达式与方法调用的映射 2010-10-15 08:05 by 空逸云, 411 visits,  网摘 ,  收藏 ,  编辑

 

2 Comment Categories:  C#

【More Effective C#】延迟求值 2010-10-14 18:30 by 空逸云, 416 visits,  网摘 ,  收藏 ,  编辑

 

5 Comment Categories:  C#

【More Effective C#】仅声明非虚的事件 2010-10-13 08:17 by 空逸云, 178 visits,  网摘 ,  收藏 ,  编辑

 

0 Comment Categories:  C#

【More Effective C#】扩展方法

更多资料

跟我学做c#皮肤美化

WinAPI使用大全

跟我做WinForm开发(2)-后台逻辑操作

作者: 空逸云
出处: http://kongyiyun.cnblogs.com  
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于跟我做WinForm开发的详细内容...

  阅读:53次