.NET Compact Framework下的进程间通信之Windows Message

简介:

在Wince和Windows Moblie 下的进程间通信可以由以下几种技术实现。

1. Windows Message

2. Point-to-Point Message Queues

3. MSMQ

下面使用讲述.NET Compact Framework下使用Windows Message进行进程间的通信。

引用库

在CF.net下进行Windows Message的开发需要引用Microsoft.WindowsCE.Forms,该DLL一般存放于C:\Program Files\Microsoft.NET\SDK\CompactFramework\v2.0\WindowsCE\Microsoft.WindowsCE.Forms.dll

发送消息

复制代码
using  Microsoft.WindowsCE.Forms;

public   partial   class  MsgForm : Form
{
        [DllImport(
" coredll.dll " , EntryPoint  =   " RegisterWindowMessage " , SetLastError  =   true )]
        
private   static   extern   uint  RegisterWindowMessage( string  lpString);
        
private   uint  msgUid  =  RegisterWindowMessage( " MESSAGE_UID " );

public static int MSG_BROADCAST = 0xFFFF;
   
private
  void  SendMessage( object  sender)
        {
            Message msg 
=  Message.Create((IntPtr)MSG_BROADCAST, ( int )msgUid , IntPtr.Zero, IntPtr.Zero);
            MessageWindow.SendMessage(
ref  msg);
        }

}
复制代码

 

首先需要P/Invoke RegisterWindowMessage 函数,每个发送的message都有唯一的UID,这样接收方才能根据UID进行监听和接收该Message。

发送之前先create一个Message对象,参数一为接收对象,如果为进程间通信可以使用广播的形式(MSG_BROADCAST),第二个参数为message的UID,接收方利用这一表示辨别message。第三和第四分别为WParam和LParam,这是标准windows message的传递参数。

 

接收消息

复制代码
using  Microsoft.WindowsCE.Forms;

public   class  MsgWindow : MessageWindow
{
    [DllImport(
" coredll.dll " , EntryPoint  =   " RegisterWindowMessage " , SetLastError  =   true )]
    
private   static   extern   uint  RegisterWindowMessage( string  lpString);

    
private   uint  msgUid  =  RegisterWindowMessage( " MESSAGE_UID " );

    
protected   override   void  WndProc( ref  Message msg)
    {
        
if  (msg.Msg  ==  msgUid )
       {
            
// handle the message. 
       }
    }
}
复制代码

 

接收消息需要定义一个继承类,继承于MessageWindow,同时他同样需要P/Invoke RegisterWindowMessage 函数,定义接收message的唯一UID。

重写WndProc,然后通过msg.Msg 来辨别关心的消息。

 

 

使用Form处理Message

如果接收方接收到message需要更新到form的话就定义一个form的reference,这样可以利用form来处理消息。其实不一定使用Form来处理message,使用Form就能比较方便的利用ui来反映message的接收和处理情况。

复制代码
public   partial   class  MsgForm : Form
{
    
private  MsgWindow MsgWin;

    
public  MsgForm()
    {
        
// pass the form reference to messagewindow
         this .MsgWin  =   new  MsgWindow( this );
    }
}

public   class  MsgWindow : MessageWindow
{
     
private  MsgForm msgForm;

  public  MsgWindow(MsgForm msgForm)
     {
            
this .msgForm =  msgForm;
     }

  protected   override   void  WndProc( ref  Message msg)
{
      
if  (msg.Msg  ==  msgUid )
      {
       // call form to handle the message. 
         msgForm.HandleMsg();
}
}
}
复制代码

MsgWindow 保存MsgForm 的引用,这样当MsgWindow 接收到消息就可以使用form来处理。

消息中传递对象

如果在消息中传递对象,就不可以使用.NET Compact Framework里面的MessageWindow.SendMessage函数了,需要使用P/Invoke来进行发送。发送端的关键是把要传递的对象封装到COPYDATASTRUCT Structure里面,然后通过API SendMessageW进行发送,接收方辨别WM_COPYDATA消息,从LParam中分拆出对象。

复制代码
  public   struct  COPYDATASTRUCT
    {
        
public   int  dwData;
        
public   int  cbData;
        
public  IntPtr lpData;
    }

    
class  cMsgStrings
    {
        
const   int  LMEM_FIXED  =   0x0000 ;
        
const   int  LMEM_ZEROINIT  =   0x0040 ;
        
const   int  LPTR  =  (LMEM_FIXED  |  LMEM_ZEROINIT);
        
const   int  WM_COPYDATA  =   0x004A ;


        [DllImport(
" coredll.dll " )]
        
public   static   extern  IntPtr LocalAlloc( int  flag,  int  size);
        [DllImport(
" coredll.dll " )]
        
public   static   extern  IntPtr LocalFree(IntPtr p);
        [DllImport(
" coredll.dll " )]
        
public   static   extern   int  SendMessageW(IntPtr hWnd,  int  Msg, IntPtr wParam, IntPtr lParam);

        
public   static  IntPtr AllocHGlobal( int  cb)
        {
            IntPtr hMemory 
=   new  IntPtr();
            hMemory 
=  LocalAlloc(LPTR, cb);
            
return  hMemory;
        }

        
public   static   void  FreeHGlobal(IntPtr hMemory)
        {
            
if  (hMemory  !=  IntPtr.Zero)
                LocalFree(hMemory);
        }

        
public   static   void  SendMsgString(IntPtr hWndDest,  string  sScript)
        {
            COPYDATASTRUCT oCDS 
=   new  COPYDATASTRUCT();
            oCDS.cbData 
=  (sScript.Length  +   1 *   2 ;
            oCDS.lpData 
=  LocalAlloc( LPTR , oCDS.cbData);
            Marshal.Copy(sScript.ToCharArray(), 
0 , oCDS.lpData, sScript.Length);
            oCDS.dwData 
=   1 ;
            IntPtr lParam 
=  AllocHGlobal(oCDS.cbData);
            Marshal.StructureToPtr(oCDS, lParam, 
false );
            SendMessageW(hWndDest, WM_COPYDATA, IntPtr.Zero, lParam);

            LocalFree(oCDS.lpData);
            FreeHGlobal(lParam);
        }
    }

// send the message with string
private   void  button1_Click( object  sender, EventArgs e)
        {
            
unsafe
            {
                cMsgStrings.SendMsgString((IntPtr)MSG_BROADCAST, textBoxMsg.Text);
            }
        }
复制代码
上面为发生端的代码,通过 cMsgStrings.SendMsgString进行发送,可以把任何managed的object封装到 COPYDATASTRUCT 进行发送

 

 

复制代码
public   class  MsgWindow : MessageWindow
    {
        
const   int  WM_COPYDATA  =   0x004A ;

        
private  FormReceiver msgForm;

        
public  MsgWindow(FormReceiver msgForm)
        {
            
this .msgForm  =  msgForm;
        }

        
protected   override   void  WndProc( ref  Message msg)
        {
            
if  (msg.Msg  ==  WM_COPYDATA)
            {
                
string  str  =  GetMsgString(msg.LParam);
                msgForm.HandleMsg(str);
            }
        }

        
public   static   string  GetMsgString(IntPtr lParam)
        {
            
if  (lParam  !=  IntPtr.Zero)
            {
                COPYDATASTRUCT st 
=  (COPYDATASTRUCT)Marshal.PtrToStructure(lParam,  typeof (COPYDATASTRUCT));
                
string  str  =  Marshal.PtrToStringUni(st.lpData);
                
return  str;
            }
            
else
            {
                
return   null ;
            }
        }
    }
复制代码

上面为接收端的代码,辨别WM_COPYDATA的消息从LParam中取出传递的对象。

 

参考文献

Message.Create Method

COPYDATASTRUCT Structure

 

源代码:WindowsMessageSender.rar 源代码展现进程间传递string的例子。
测试环境:Wince 5 + CF.net 2.0



    本文转自Jake Lin博客园博客,原文链接:http://www.cnblogs.com/procoder/archive/2009/03/16/1413176.html,如需转载请自行联系原作者


相关文章
|
2月前
使用的是.NET Framework 4.0,并且需要使用SMTP协议发送电子邮件
使用的是.NET Framework 4.0,并且需要使用SMTP协议发送电子邮件
57 1
|
4月前
|
Linux C++ Windows
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
【Azure 应用服务】Azure App Service(Windows)环境中如何让.NET应用调用SAP NetWeaver RFC函数
|
14天前
|
弹性计算 开发框架 安全
基于云效 Windows 构建环境和 Nuget 制品仓库进行 .Net 应用开发
本文将基于云效 Flow 流水线 Windows 构建环境和云效 Packages Nuget 制品仓库手把手教你如何开发并部署一个 .NET 应用,从环境搭建到实战应用发布的详细教程,帮助你掌握 .NET 开发的核心技能。
|
28天前
|
数据库连接 数据库 C#
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(上)
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(上)
|
28天前
|
数据库连接 数据库 C#
Windows下C# 通过ADO.NET方式连接南大通用GBase 8s数据库(下)
本文接续前文,深入讲解了在Windows环境下使用C#和ADO.NET操作南大通用GBase 8s数据库的方法。通过Visual Studio 2022创建项目,添加GBase 8s的DLL引用,并提供了详细的C#代码示例,涵盖数据库连接、表的创建与修改、数据的增删查改等操作,旨在帮助开发者提高数据库管理效率。
|
2月前
|
开发框架 缓存 监控
NET Framework 到 .NET 5/6 的迁移是重大的升级
本文详细介绍了从 .NET Framework 4.8 迁移到 .NET 5/6 的过程,通过具体案例分析了迁移策略与最佳实践,包括技术栈评估、代码迁移、依赖项更新及数据库访问层的调整,强调了分阶段迁移、保持代码可维护性及性能监控的重要性。
62 3
|
2月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
109 9
|
2月前
|
机器学习/深度学习 编解码 算法
【小样本图像分割-4】nnU-Net: Self-adapting Framework for U-Net-Based Medical Image Segmentation
《nnU-Net: 自适应框架用于基于U-Net的医学图像分割》是一篇2018年的论文,发表在Nature上。该研究提出了一种自适应的医学图像分割框架nnU-Net,能够自动调整模型的超参数以适应不同的数据集。通过2D和3D U-Net及级联U-Net的组合,nnU-Net在10个医学分割数据集上取得了卓越的性能,无需手动调整。该方法强调数据增强、预处理和训练策略等技巧,为医学图像分割提供了一个强大的解决方案。
103 0
【小样本图像分割-4】nnU-Net: Self-adapting Framework for U-Net-Based Medical Image Segmentation
winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
本文讨论了在基于.NET 6和.NET Framework的WinForms项目中添加图表控件的不同方法。由于.NET 6的WinForms项目默认不包含Chart控件,可以通过NuGet包管理器安装如ScottPlot等图表插件。而对于基于.NET Framework的WinForms项目,Chart控件是默认存在的,也可以通过NuGet安装额外的图表插件,例如LiveCharts。文中提供了通过NuGet添加图表控件的步骤和截图说明。
winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
|
4月前
|
开发框架 缓存 前端开发
实战.NET Framework 迁移到 .NET 5/6
从.NET Framework 迁移到.NET 5/6 是一次重要的技术革新,涵盖开发环境与应用架构的全面升级。本文通过具体案例详细解析迁移流程,包括评估现有应用、利用.NET Portability Analyzer 工具识别可移植代码、创建新项目、逐步迁移代码及处理依赖项更新等关键步骤。特别关注命名空间调整、JSON 序列化工具更换及数据库访问层重构等内容,旨在帮助开发者掌握最佳实践,确保迁移过程平稳高效,同时提升应用性能与可维护性。
157 2