windows 桌面开发 - 子类化控件(不用任何WinAPI),演示拦截Button的WM_LBUTTONDBLCLK
最近在博客里看见,有位朋友在研究如何实现 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
}
}