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

推荐订阅源

罗磊的独立博客
小众软件
小众软件
The Cloudflare Blog
博客园 - 【当耐特】
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
酷 壳 – CoolShell
酷 壳 – CoolShell
WordPress大学
WordPress大学
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
Visual Studio Blog
量子位
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
美团技术团队
S
SegmentFault 最新的问题
宝玉的分享
宝玉的分享
博客园 - 叶小钗
月光博客
月光博客
Apple Machine Learning Research
Apple Machine Learning Research
T
Tailwind CSS Blog
博客园 - 聂微东
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
J
Java Code Geeks
Y
Y Combinator Blog
D
Docker
Microsoft Azure Blog
Microsoft Azure 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窗口标题栏上添加按钮,希望对你有所帮助。