`
truelove12358
  • 浏览: 77503 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

[C#.NET][WinForm] Windows 窗口讯息接收 - WndProc 的使用

 
阅读更多

Windows窗口主要是由事件所驱动,用户所操作的动作或是系统核心触发的中断都是交由Windows先行处理,再透过WindowsMessage机制传送给窗口应用程序,在Windows里我们不需要直接与硬件沟通,也不允许直接沟通,通通都是要透过Windows核心协调分配,我们只要专心处理Windows所触发的事件就可以了;比如我们在鉴盘按下任意键,键盘所按下的中断讯号被Windows接收后,会判断目前的作用窗口并将被按下的讯息传送给那个窗口,有钮被按下了,最后KeyDown事件被触发,由Windows传送来的事件我们还可以知道是哪一个键被按下了。

这种由系统发出的讯息叫WindowsMessage,而WindowProcCallbackFunction就是用来接收WindowsMessage的一个函数,比如鼠标左键被按下时会收到WM_LBUTTONDOWN,键盘被按下时会收到VM_KEYDOWN,不管用什么语言开发WIndowsMessage传递机制都不变,只是在不同的语言所包装的方法名称不一样而已。在大内世界里System.Windows.Forms.Form已经将这些Message包装起来,WM_LBUTTONDOWN=MouseDown事件、WM_PAINT=Paint事件,然后再透过对应的EventArgs参数来判断详细的Message内容,这些事件各位其实都不陌生,因为都是我们常用的。

privatevoidForm1_KeyDown(objectsender,KeyEventArgse)

{

//鍵盤按下事件

}

privatevoidForm1_MouseDown(objectsender,MouseEventArgse)

{

//滑鼠左鍵按下

}

System.Windows.Forms.Control类别,它负责了所有可见控件的的基本处理,鼠标、键盘以及重绘操作,里面的WndProc方法就是和WindowProc函式一样,用来接收WindowsMessage指令的方法,使用方法很简单,只要覆写WndProc方法,这个窗口就能自己处理由WindowsMessage传来的讯息,接下来来练习一下怎么接收讯息,首先http://www.woodmann.com/fravia/sources/WINUSER.H包含了所有MessageID的定义,这将对我们在宣告常数时有很大的帮助喔。

WndProc方法的使用

先来看个简单的例子,在Form里覆写WndProc方法:

constintWM_MOUSEMOVE=0x0200;//定義ID

protectedoverridevoidWndProc(refMessagem)

{

if(m.Msg==WM_MOUSEMOVE)

{

stringbinary=System.Convert.ToString(m.LParam.ToInt32(),2).PadLeft(32,'0');//轉成二進制

stringlWord="";

stringhWord="";

for(inti=0;i<16;i++)

{

hWord+=binary[i].ToString();

}

for(inti=17;i<32;i++)

{

lWord+=binary[i].ToString();

}

intx=Convert.ToInt32(lWord,2);//二進制轉十進制

inty=Convert.ToInt32(hWord,2);

this.lab_WM_MOVE_1.Text=string.Format("使用WM_MOUSEMOVE,X:{0},Y:{1}",x,y);

ushortxpos=(ushort)m.LParam;//表示X座標

ushortypos=(ushort)(m.LParam.ToInt32()>>16);//表示X座標

this.lab_WM_MOVE_2.Text=string.Format("使用WM_MOUSEMOVE,X:{0},Y:{1}",xpos,ypos);

}

base.WndProc(refm);

}

稍为解释一下程序代码,鼠标的移动讯息是丢到lParam参数里了,从MSDN的WM_MOUSEMOVEMessage可以知道,里面写着lowword是X坐标,highword是Y坐标

这时有人问,LParam并没有看到什么lowword跟highword阿?,别忘了计算机是由二进制在处理数据的,VS的变量都是塞已经处理好的十进制,只要将其转回二进制,就能了解了,来复习一下计算器概论吧

stringbinary=System.Convert.ToString(m.LParam.ToInt32(),2).PadLeft(32,'0');//轉成二進制

LParam讯息是由32bit兜起来的,也就是2个16word,根据MSDN所述来处理数据。

这样一来就看的懂为什么上面的例子要处理二进制,了解二进制的处理方法后,我们再来用.NET的转型来处理,才不会一下子不知所措。

ushortxpos=(ushort)m.LParam;//表示X座標

ushortypos=(ushort)(m.LParam.ToInt32()>>16);//表示Y座標

this.label2.Text=string.Format("X:{0},Y:{1}",xpos,ypos);

上面的范例在.Net的MouseMove事件里变得更简单,只要用MouseEventArgs参数就能处理鼠标坐标了。

privatevoidForm1_MouseMove(objectsender,MouseEventArgse)

{

this.lab_WM_MOVE_2.Text=string.Format("X:{0},Y:{1}",e.X,e.Y);

}

看到这里我相信有用心看的人都稍为了解了,打铁要趁热,再来看一个例子,这次来玩玩WM_KEYDOWNMessage;没错,数据是丢到wParam,很好!这次你也看懂了,所以我们要来处理wParam参数。不过WM_KEYDOWNMessage主要显示虚拟键盘(Virtual-KeyCodes),是不包含系统键值,只有大写;若要取得系统键值,可以用WM_CHARMessage

constintWM_KEYDOWN=0x0100;

constintWM_CHAR=0x0102;

protectedoverridevoidWndProc(refMessagem)

{

if(m.Msg==WM_KEYDOWN)

{

charkeys=(char)m.WParam;

this.lab_WM_KeyDown.Text=string.Format("使用WM_KEYDOWN,按下:{0}",keys.ToString());

}

if(m.Msg==WM_CHAR)

{

charkeys=(char)m.WParam;

this.lab_WM_KeyChar.Text=string.Format("使用WM_CHAR,按下:{0}",keys.ToString());

}

base.WndProc(refm);

}

把上面程序代码的转换成.NET的事件,分别对应到KeyDown与KeyPress

privatevoidForm1_KeyDown(objectsender,KeyEventArgse)

{

this.lab_KeyDown.Text=string.Format("KeyDown事件,按下:{0}",((char)e.KeyCode).ToString());

}

privatevoidForm1_KeyPress(objectsender,KeyPressEventArgse)

{

this.lab_KeyPress.Text=string.Format("KeyPress事件,按下:{0}",e.KeyChar.ToString());

}

Message结构

由winuser.h得知,在Win32API里是宣告成这样

typedefstructtagMSG{

HWNDhwnd;

UINTmessage;

WPARAMwParam;

LPARAMlParam;

DWORDtime;

POINTpt;

}

對應到.Net的Message結構

publicstructMessage

{

publicIntPtrHWnd{get;set;}

publicintMsg{get;set;}

publicIntPtrWParam{get;set;}

publicIntPtrLParam{get;set;}

publicIntPtrResult{get;set;}

}

我拿比较重要的讯息稍微解释一下:

tagMSG.hwnd及Message.HWnd,是系统给予的唯一编码,也就是Control.Handle属性。

tagMSG.Message及Message.Msg,是WindowsMessageID,例如像WM_KEYDOWN、WM_KEYUP这些东西,定义在winuser.h里。

而WParam及LParam是存放重要讯息的参数,不同的WindowsMessageID有不同的结果,就像我们上面演练的那样,必须要去分析它们才能取得正确的信息。

结论:

在Windows世界里TestBox、Label、ComboBox控件其实都是窗口,只是窗口的类别不一样而已,记得以前常在用的窗口列举,会先找父窗口,再由父窗口里找到控件,找到自己要的控件的条件,我通常都是用窗口属性+Handle抓到我要的控件,然后再传送Message给控件。

了解到Windwos怎么接收Message后,下篇再来写怎么传递Message。

原文:http://www.dotblogs.com.tw/yc421206/archive/2011/01/24/20971.aspx

分享到:
评论

相关推荐

    c# .net winform text editer 很强大的文本编辑工具 源码 代码 支持txt word等多种格式

    《C# .NET WinForm 文本编辑器:打造多功能文本处理平台》 在软件开发领域,文本编辑器是不可或缺的工具之一,它为用户提供了编辑、查看和操作文本的能力。C# .NET 提供了一个强大的框架,使得开发者可以构建功能...

    c#.net winform进程保护示例

    在C# .NET WinForm项目中,我们可以创建一个主窗口类,继承自`System.Windows.Forms.Form`,并在其中编写代码以实现所需功能。在这个特定示例中,我们的目标是使进程免于被终结。 NKCore.dll是一个C++编写的动态...

    C# .NET WinForm 识别快递单一维码

    综上所述,开发"C# .NET WinForm 识别快递单一维码"的应用需要掌握C#编程、WinForm控件使用、条形码识别库的运用、图像处理、事件驱动编程、异步操作、错误处理、数据交互以及UI设计等多个方面的技能。通过整合这些...

    C#.NET WinForm 大型企业ERP管理系统源码ERP源码

    ERP源码_含vs2019版 0,两套大型源码。 1,vs2010和vs2019。 2,sqlserver2008以上。 3,C#. 4,附带数据库,详细安装说明。 5、赠送dxdev控件。

    C#-netcore5.0-winform-windows10-免注册调用大漠插件.7z

    标题提到的项目实现了在Windows 10操作系统上,使用C#语言和WinForms界面,无须注册即可调用大漠插件,以实现找字、找图、截图和打字等实用功能。 1. **.NET Core 5.0**: .NET Core是微软推出的一个跨平台的开发...

    SunnyUI.Net, 基于 C# .Net WinForm 开源控件库、工具类库、扩展类库、多页面开发框架

    SunnyUI.Net是一款针对C# .Net WinForm平台设计的开源控件库,它提供了丰富的UI元素和实用的工具类库,旨在简化Windows桌面应用程序的开发工作,提高开发效率。这款框架不仅包含了基础的控件扩展,还集成了多页面...

    c#.net winForm教程

    C#.NET WinForm教程是针对使用C#编程语言在.NET框架下开发Windows桌面应用程序的指导内容。WinForms是.NET Framework中的一个组件,它提供了一种简单的方式来创建交互式的图形用户界面(GUI)。在这个教程中,我们将...

    C# .NET winform条码库

    在.NET框架下,C#是一种常用的编程语言,用于构建各种应用程序,包括Windows桌面应用。WinForms是.NET Framework提供的一种用于创建此类应用的用户界面(UI)的工具集。在这个特定的场景中,"C# .NET Winform条码库...

    C# .net winform mail 发送邮件 源码

    在C# .NET环境下开发Windows桌面应用程序(Winform)时,发送邮件是一项常见的需求。标题中的"C# .net winform mail 发送邮件 源码"指的是一种使用C#编程语言,基于.NET Framework的Winform应用,实现邮件发送功能的...

    C#.net Winform 多国语言示例

    在.NET框架下,C#是一种常用的编程语言,用于构建各种应用程序,包括Windows桌面应用。WinForms是.NET Framework提供的一种用于创建Windows GUI(图形用户界面)的应用程序开发平台。本示例将详细介绍如何在C#的...

    c#.net winform的短信猫程序

    标题中的“C#.NET Winform的短信猫程序”是指使用C#编程语言和.NET Framework开发的一个桌面应用程序,该程序在Windows Forms(Winform)平台上运行,主要目的是通过硬件设备——短信猫来实现短信的发送、接收及一些...

    Iocomp .Net Winform v4.rar

    “Iocomp .Net Winform v4.rar”是一个包含VB仪表盘控件的压缩包,用于在.NET Framework环境下,特别是Visual Basic .NET(VB.Net)和VB6.0中开发应用程序时,提供图形化的数据展示功能。这个控件库也可以与组态王...

    C# .net winform sms send receive 发送 接受 短消息 发送 接受 消息

    本项目聚焦于使用C# .NET WinForm实现短信的发送和接收功能,这对于开发如企业内部通讯或客户服务系统等应用场景非常实用。 首先,我们要理解短信服务的基本原理。通常,短信发送和接收涉及到通过手机网络运营商的...

    C# .NET Winform 仿QQ自动隐藏控件

    在C# .NET框架下,Winform应用是一种常见的桌面应用程序开发平台。本主题聚焦于一个特定的控件功能——仿QQ自动隐藏控件。这个功能是受到腾讯QQ软件启发,当用户将鼠标移出特定区域时,控件会自动隐藏,鼠标移回时则...

    c#.net winform 程序加密工具 dotNET_Reactor v4.9.0.0 破解版

    c#.net winform 程序加密工具 dotNET_Reactor v4.9.0.0 破解版

    基于C#/.NET实现的Winform系统-图书馆管理系统

    《基于C#/.NET实现的Winform图书馆管理系统详解》 在信息技术日新月异的今天,图书馆管理系统已经成为了各类图书馆日常运营的重要工具。本系统利用C#编程语言和.NET框架,构建了一个完整的Winform应用程序,旨在...

    VB.Net-C#多线程Thread-代理委托delegate编程

    最近收集的VB.Net-C#多线程Thread-代理委托delegate编程。文章列表: c#.net多线程同步.txt C#WebBrowser页面与WinForm交互技巧一.txt C#多线程编程-多细全.txt C#多线程编程简单实例.txt C#多线程窗体控件安全访问....

    C# Winform,FX3U-32M,FX3u-ENET-ADP,MC协议通信

    在本文中,我们将深入探讨如何使用C# Winform与三菱FX3U-32M PLC进行基于FX3u-ENET-ADP网络模块的MC协议通信。这是一项关键的技术,对于工业自动化和远程监控系统至关重要。让我们逐一解析每个部分。 首先,C# ...

    c# .NET WinForm 邮件发送

    本主题将深入探讨如何使用C#和.NET库在WinForm应用中实现邮件发送功能。 邮件发送在现代软件中是一项基本的需求,无论是用于通知用户、发送报表还是进行客户服务。在C#中,我们可以利用System.Net.Mail命名空间中的...

    C#.Net winform TCP协议之单一服务器与多客户端聊天室demo

    在本文中,我们将深入探讨如何使用C#.NET WinForm实现基于TCP协议的单一服务器与多客户端聊天室。TCP(Transmission Control Protocol)是一种面向连接、可靠的网络传输协议,它确保了数据包的顺序发送和错误检查,...

Global site tag (gtag.js) - Google Analytics