惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

雷峰网
雷峰网
博客园 - 叶小钗
博客园_首页
阮一峰的网络日志
阮一峰的网络日志
D
Docker
J
Java Code Geeks
B
Blog
G
Google Developers Blog
小众软件
小众软件
博客园 - 聂微东
罗磊的独立博客
大猫的无限游戏
大猫的无限游戏
IT之家
IT之家
量子位
WordPress大学
WordPress大学
美团技术团队
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
宝玉的分享
宝玉的分享
腾讯CDC
Martin Fowler
Martin Fowler
V
Visual Studio Blog
D
DataBreaches.Net
Stack Overflow Blog
Stack Overflow Blog
C
Check Point Blog

博客园 - 哑吧湖大水怪

MAF框架架构设计概览 rabbitmq 相关概念 使用AutoMapper时Expression的转换 unity 三种注入示例 DNS解析过程详解 手工设置Windows服务依赖关系 .NET Micro Framework简介 .net MF 学习 数码管显示 .NET MF固件部署 LED灯控制 Hello World 你懂的 .NET MF环境的安装 str to date 摄像头操作(转) 线程间操作控件 获取客户端相关信息 任务栏的显示与隐藏 winfrom 特效 [转载]
C#实现在WinForm窗口标题栏上添加按钮
哑吧湖大水怪 · 2011-04-20 · via 博客园 - 哑吧湖大水怪

转载:http://www.csharpwin.com/csharpspace/10544r8802.shtml

在窗口标题栏上加按钮本来不是什么新鲜事了,我在VC++下早也实现过了(相信很多人也都实现过了)。今天一个朋友问我C# WinForm下可否实现,我就顺便拿C#写了一个。

  原理是一样的,都是重写窗口过程(WndProc),处理一些非客户区消息(WM_NCxxxx),可以说本来没有什么新意,可是从写这个程序的过程中,我也学到了两个技巧:

  1)、C#中重写窗口过程不用再调用SetWindowLong API了,直接overide一个WndProc就可以了。

  2)、Windows API中的HDC可以通过Graphics.FromHdc()转换为(创建出)System.Drawing.Graphics,然后就可以用.NET Framework (GID+??)提供的绘图功能方便地进行画图了。终于可以抛开讨厌的GDI API了(说实在话,在C#中调用Windows API真的太麻烦了:)).

  代码如下:

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace WindowsApplication2
{
  
/// <summary>
  
/// Form1 的摘要说明。
  
/// </summary>
  public class Form1 : System.Windows.Forms.Form
  {
    
/// <summary>
    
/// 必需的设计器变量。
    
/// </summary>
    private System.ComponentModel.Container components = null;
    
public Form1()
    {
      
//
      
// Windows 窗体设计器支持所必需的
      
//
      InitializeComponent();
      
//
      
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
      
//
    }
    
/// <summary>
    
/// 清理所有正在使用的资源。
    
/// </summary>
    protected override void Dispose(bool disposing)
    {
      
if (disposing)
      {
        
if (components != null)
        {
          components.Dispose();
        }
      }
      
base.Dispose(disposing);
    }
    
#region Windows 窗体设计器生成的代码
    
/// <summary>
    
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
    
/// 此方法的内容。
    
/// </summary>
    private void InitializeComponent()
    {
      
//
      
// Form1
      
//
      this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
      
this.ClientSize = new System.Drawing.Size(292, 266);
      
this.Name = "Form1";
      
this.Text = "Form1";
      
this.SizeChanged += new System.EventHandler(this.Form1_SizeChanged);
    }
    
#endregion
    
/// <summary>
    
/// 应用程序的主入口点。
    
/// </summary>
    [STAThread]
    
static void Main()
    {
      Application.Run(
new Form1());
    }
    [DllImport(
"User32.dll")]
    
private static extern IntPtr GetWindowDC(IntPtr hwnd);
    [DllImport(
"User32.dll")]
    
private static extern int ReleaseDC(IntPtr hwnd, IntPtr hdc);
    [DllImport(
"Kernel32.dll")]
    
private static extern int GetLastError();
    
//标题栏按钮的矩形区域。
    Rectangle m_rect = new Rectangle(205, 4, 16, 16);
    
protected override void WndProc(ref Message m)
    {
      
base.WndProc(ref m);
      
switch (m.Msg)
      {
        
case 0x86://WM_NCACTIVATE
          goto case 0x85;
        
case 0x85://WM_NCPAINT
          {
            IntPtr hDC
= GetWindowDC(m.HWnd);
            
//把DC转换为.NET的Graphics就可以很方便地使用Framework提供的绘图功能了
            Graphics gs = Graphics.FromHdc(hDC);
            gs.FillRectangle(
new LinearGradientBrush(m_rect, Color.Pink, Color.Purple, LinearGradientMode.BackwardDiagonal), m_rect);
            StringFormat strFmt
= new StringFormat();
            strFmt.Alignment
= StringAlignment.Center;
            strFmt.LineAlignment
= StringAlignment.Center;
            gs.DrawString(
"", this.Font, Brushes.BlanchedAlmond, m_rect, strFmt);
            gs.Dispose();
            
//释放GDI资源
            ReleaseDC(m.HWnd, hDC);
            
break;
          }
        
case 0xA1://WM_NCLBUTTONDOWN
          {
            Point mousePoint
= new Point((int)m.LParam);
            mousePoint.Offset(
-this.Left, -this.Top);
            
if (m_rect.Contains(mousePoint))
            {
              MessageBox.Show(
"hello");
            }
            
break;
          }
      }
    }
    
//在窗口大小改变时及时更新按钮的区域。
    private void Form1_SizeChanged(object sender, System.EventArgs e)
    {
      m_rect.X
= this.Bounds.Width - 95;
      m_rect.Y
= 4;
      m_rect.Width
= m_rect.Height = 16;
    }
  }
}

    以上介绍的是C#实现在WinForm窗口标题栏上添加按钮,希望对你有所帮助。