最近在博客里看见,有位朋友在研究如何实现 button 的双击
网址: http://www.cnblogs.com/adaiye/archive/2008/10/16/button_doubleclick2.html
他是用代码实现的其实他的精神是值得学习的,不过在按钮上加双击事件事情本身是比较囧的呵呵、我看过了了这篇文章后感慨万分,看来很多窗口开发相关的技能(所谓技能就是组成某种技术的最小单元,技术是指如何运用技能)可能园子里很多朋友还不是很熟悉(没有卖弄的意思啊),特此化几分钟时间写了点代码贴在这里,供大家学习参考、windows 开发老鸟可以直接无视这篇文章;
其实本代码段最主要是以一种外挂的方式,拦截窗口上的控件事件(windows 消息)前提是控件本身并没有实现,比如代码中的 WM_LBUTTONDBLCLK 消息 button 并没有提供相应的事件封装 (按钮双击没有意义,请不要模仿),主要为了解决一些代码比较少的操作,如果是比较多的代码最好封装成控件,便于重用;
多年不进行 windows 桌面开发了很多地方可能写的有些问题,请见谅,代码很简单我就不过多注释了;
using
System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
// 窗口上就一个按钮 Form1.Designer.cs 就不贴了
// 这个类在代码后边有说明
SubClassManager scm;
public Form1()
{
InitializeComponent();
// 1) 子类化控件并映射处理函数
scm = new SubClassManager( this .button1.Handle);
scm.SubClassWindowProc += button1_WndProc; // 事件映射
}
protected override void OnHandleDestroyed(EventArgs e)
{
// 3) 释放
scm.Dispose();
base .OnHandleDestroyed(e);
}
protected bool button1_WndProc( ref Message m)
{
// 2)这里可以接到 button1 的任何消息
// 按钮双击, .net 没有封装这个事件,这里只是为了演示子类话
// 按钮双击没有意义,请不要模仿
const int WM_LBUTTONDBLCLK = 0x0203 ;
if (m.Msg == WM_LBUTTONDBLCLK)
{
Console.WriteLine( " WM_LBUTTONDBLCLK " ); // 填写你的处理代码
}
return true ;
}
}
/// <summary>
/// 本类用于子类化控件或窗口,拦截一些.net 没有封装的消息(窗口重写 WndProc 即可不要使用本类)
/// </summary>
public class SubClassManager : System.Windows.Forms.NativeWindow,IDisposable
{
public delegate bool SubClassWndProc( ref Message m); // 消息处理函数委托
private IntPtr handle;
private bool disposed = false ;
public event SubClassWndProc SubClassWindowProc; // 消息处理事件
public SubClassManager(IntPtr hWnd)
{
handle = hWnd;
this .AssignHandle(handle);
}
protected override void WndProc( ref Message m)
{
if (SubClassWindowProc != null )
{
if (SubClassWindowProc( ref m))
{ // 如果返回 true 调用基础类
base .WndProc( ref m);
}
}
}
#region IDisposable 成员
~ SubClassManager()
{
Console.WriteLine( " 请释放 SubClassManager " );
Dispose( false );
}
private void Dispose( bool disposing)
{
if ( ! this .disposed)
{
if (disposing)
{
this .ReleaseHandle();
}
}
disposed = true ;
}
public void Dispose()
{
Dispose( true );
}
#endregion
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
// 窗口上就一个按钮 Form1.Designer.cs 就不贴了
// 这个类在代码后边有说明
SubClassManager scm;
public Form1()
{
InitializeComponent();
// 1) 子类化控件并映射处理函数
scm = new SubClassManager( this .button1.Handle);
scm.SubClassWindowProc += button1_WndProc; // 事件映射
}
protected override void OnHandleDestroyed(EventArgs e)
{
// 3) 释放
scm.Dispose();
base .OnHandleDestroyed(e);
}
protected bool button1_WndProc( ref Message m)
{
// 2)这里可以接到 button1 的任何消息
// 按钮双击, .net 没有封装这个事件,这里只是为了演示子类话
// 按钮双击没有意义,请不要模仿
const int WM_LBUTTONDBLCLK = 0x0203 ;
if (m.Msg == WM_LBUTTONDBLCLK)
{
Console.WriteLine( " WM_LBUTTONDBLCLK " ); // 填写你的处理代码
}
return true ;
}
}
/// <summary>
/// 本类用于子类化控件或窗口,拦截一些.net 没有封装的消息(窗口重写 WndProc 即可不要使用本类)
/// </summary>
public class SubClassManager : System.Windows.Forms.NativeWindow,IDisposable
{
public delegate bool SubClassWndProc( ref Message m); // 消息处理函数委托
private IntPtr handle;
private bool disposed = false ;
public event SubClassWndProc SubClassWindowProc; // 消息处理事件
public SubClassManager(IntPtr hWnd)
{
handle = hWnd;
this .AssignHandle(handle);
}
protected override void WndProc( ref Message m)
{
if (SubClassWindowProc != null )
{
if (SubClassWindowProc( ref m))
{ // 如果返回 true 调用基础类
base .WndProc( ref m);
}
}
}
#region IDisposable 成员
~ SubClassManager()
{
Console.WriteLine( " 请释放 SubClassManager " );
Dispose( false );
}
private void Dispose( bool disposing)
{
if ( ! this .disposed)
{
if (disposing)
{
this .ReleaseHandle();
}
}
disposed = true ;
}
public void Dispose()
{
Dispose( true );
}
#endregion
}
}