C# 获得另一个窗体句柄并发送消息(使用windows API)

2023-05-16

复制代码


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
 
namespace findWindowTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        // Find Window
        // 查找窗体
        // @para1: 窗体的类名 例如对话框类是"#32770"
        // @para2: 窗体的标题 例如打开记事本 标题是"无标题 - 记事本" 注意 - 号两侧的空格
        // return: 窗体的句柄
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        public static extern IntPtr FindWindow(string className, string windowName);
       
       
       
       
       
        // Find Window Ex
        // 查找窗体的子窗体
        // @para1: 父窗体的句柄 如果为null,则函数以桌面窗口为父窗口,查找桌面窗口的所有子窗口
        // @para2: 子窗体的句柄 如果为null,从@para1的直接子窗口的第一个开始查找
        // @para3: 子窗体的类名 为""表示所有类
        // @para4: 子窗体的标题 为""表示要查找的窗体无标题 如空白的textBox控件
        // return: 子窗体的句柄
        [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
        private static extern IntPtr FindWindowEx(
            IntPtr hwndParent,
            IntPtr hwndChildAfter,
            string lpszClass,
            string lpszWindow);
 
        // SendMessage
        // 向窗体发送消息
        // @para1: 窗体句柄
        // @para2: 消息类型
        // @para3: 附加的消息信息
        // @para4: 附加的消息信息
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(
            IntPtr hWnd,
            int Msg,
            IntPtr wParam,
            string lParam);
 
        // 消息类型(部分)
        const int WM_GETTEXT     = 0x000D;  // 获得窗体文本 如获得对话框标题
        const int WM_SETTEXT     = 0x000C;  // 设置窗体文本 如设置文本框内容
        const int WM_CLICK       = 0x00F5;  // 发送点击消息如调用该窗体(按钮)的"button1_Click();"
 
        // 本程序针对指定的另一程序窗体因此声名了如下变量
        IntPtr Wnd  = new IntPtr(0);// 一卡通注册程序主窗体
        IntPtr sWnd = new IntPtr(0);// GroupBox控件 此为“一卡通注册程序”主窗体的子窗体
        IntPtr txt  = new IntPtr(0);// 文本框
        IntPtr btn1 = new IntPtr(0);// 查询按钮
        IntPtr btn2 = new IntPtr(0);// 注册按钮 这三个窗体又为“GroupBox控件”的子窗体
        //IntPtr popW = new IntPtr(0);// 弹出对话框
        //IntPtr popB = new IntPtr(0);// 弹出对话框确定按钮
 
        // 文件操作
        private String filename = string.Empty;
        private StreamReader reader = null;
 
        // 从“打开文件”对话框打开txt文件 同时获得需要的窗口句柄
        private void button2_Click(object sender, EventArgs e)
        {
            label2.Text = "";
            openFileDialog1.DefaultExt = "txt";
            openFileDialog1.Filter = "文本文件|*.txt";
            openFileDialog1.RestoreDirectory = true;
            openFileDialog1.FilterIndex = 1;
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                filename = openFileDialog1.FileName;
            }
 
            // 获得窗口句柄
            Wnd  = FindWindowEx((IntPtr)0, (IntPtr)0, null, "读者一卡通注册");// 一个注册程序的窗体
            sWnd = FindWindowEx(Wnd,  (IntPtr)0, null, "条件"); // 窗体上的一个GroupBox控件
            txt  = FindWindowEx(sWnd, (IntPtr)0, null, "");     // GroupBox内的textBox控件
            btn1 = FindWindowEx(sWnd, (IntPtr)0, null, "查询"); // GroupBox内的查询按钮
            btn2 = FindWindowEx(sWnd, (IntPtr)0, null, "注册"); // GroupBox内的注册按钮
        }
 
        // 重复地把文件内读取的行
        // 将该行发送给注册程序窗体上的文本框中
        // 并“点击”查询按钮和注册按钮
        // 直到文件读取完毕
        private void button3_Click(object sender, EventArgs e)
        {
            //计数
            int count = 0;
 
            //读取文件
            if (filename == string.Empty)
            {
                button2.Focus();
                return;
            }
 
            reader = new StreamReader(filename);
            if (reader.EndOfStream)
            {
                return;
            }
 
            string str = string.Empty;
 
            do
            {
                //读取学号 保存在变量str中
                str = reader.ReadLine();
 
                //设置学号
                SendMessage(txt, WM_SETTEXT, (IntPtr)0, str);
 
                //点击查询按钮
                SendMessage(btn1, WM_CLICK, (IntPtr)0, "");
 
                //点击注册按钮
                SendMessage(btn2, WM_CLICK, (IntPtr)0, "");
 
                count++;
            }
            while(!reader.EndOfStream);
 
            reader.Close();
            filename = string.Empty;
            label1.Text = "注册人数:";
            label2.Text = Convert.ToString(count);
        }
    }
}  

复制代码

//*********

      在项目中有这样的需求,在主窗体隐藏时或者主进程运行时对其它窗体的控件或者事件进行控制,而且其它窗体是处于活动状态,而主窗体或者主进程是隐藏在后面的。这个时候使用句柄和消息来处理就比较好解决这些问题了,当然了也可以使用其它方法。比如将其它窗体在主窗体中申明并且定义,使之和主窗体一样一直存在于内存中,在各个窗体中申明公共方法,在主进程需要调用时直接调用即可,但是这样耗费了大量的系统资源。现在使用消息来解决这个问题。下面提供一个小程序,在主窗体中通过句柄和消息来控制子窗体中Label上文字变化和颜色,代码如下:

 

Windowns的API类

using System;
using System.Runtime.InteropServices;

namespace TestHwnd
{
    public class Win32API
    {
         [DllImport("user32.dll ", CharSet = CharSet.Unicode)]
        public static extern IntPtr PostMessage(IntPtr hwnd, int wMsg, string wParam, string lParam);

    }

}

 

主窗体程序(发送消息):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace TestHwnd
{
    public partial class Main : Form
    {

        //定义了一个子窗体的句柄
        public IntPtr hwndfrmTest;
        

        public Main()
        {
            InitializeComponent();
        }

     

        private void timer1_Tick(object sender, EventArgs e)
        {

            if(hwndfrmTest!=(IntPtr)0)
            {
                if(DateTime.Now.Second % 3 == 0)
                {
                    Win32API.PostMessage(hwndfrmTest, 0x60, "", "");
                }
                
                if(DateTime.Now.Second % 5 == 0)
                {
                    Win32API.PostMessage(hwndfrmTest, 0x61, "", "");
                }
                
            }
            
        }


        void Button2Click(object sender, EventArgs e)
        {
            frmTest frm=new frmTest();
            frm.Show(this);
        }
    }

子窗体程序(接收消息)

using System;
using System.Drawing;
using System.Windows.Forms;

namespace TestHwnd
{
     ///  <summary>
     ///  Description of frmTest.
     ///  </summary>
     public  partial  class frmTest : Form
    {
        Main main;
         public  frmTest()
        {
             //
             // The InitializeComponent() call is required for Windows Forms designer support.
             //
             InitializeComponent();
            
             //
             // TODO: Add constructor code after the InitializeComponent() call.
             //
        }
        
         void  FrmTest_Load( object sender, EventArgs e)
        {

            main = this.Owner as Main;

             //初始化该窗体的句柄

            main.hwndfrmTest =  this.Handle;
        }
        
         /// 重写窗体的消息处理函数DefWndProc,从中加入自己定义消息 MYMESSAGE 的检测的处理入口
         protected  override  void  DefWndProc( ref Message m)
        {
             switch (m.Msg)
            {
                 case  0x60:
                    {
                        label1.ForeColor=Color.Red;
                        label1.Text = DateTime.Now. ToString() +  "-" +  "测试成功。。。。,呵呵,变红了";
                    }
                     break;
                 case  0x61:
                    {
                        label1.ForeColor=Color.Blue;
                        label1.Text = DateTime.Now. ToString() +  "-" +  "测试成功。。。。,呵呵,变蓝了";
                    }
                     break;
                 default:
                     base. DefWndProc( ref m);
                     break;
            }
        }
        
        
        
         void  Button1Click( object sender, EventArgs e)
        {
                main.hwndfrmTest = (IntPtr) ( 0);
             this. Close();
        }
    }
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 获得另一个窗体句柄并发送消息(使用windows API) 的相关文章

  • “以管理员身份运行”时的 Windows 批处理文件起始目录

    我有一个位于目录中的批处理文件 也必须从那里运行 因为它会更新该目录中的文件 这工作得很好 除非用户以管理员身份运行批处理文件 Vista 上需要 那么起始目录是C Windows System32 有什么办法仍然能够知道批处理文件是从哪个
  • Vagrant 错误:无法挂载 VirtualBox 共享文件夹(Guest Additions、vboxsf)

    问题 我在 Windows 10 上安装了 Vagrant 这样我就可以在虚拟机中创建个人本地开发环境 我读到的有关 Vagrant 的所有内容都表明我什至可以启动多个系统并通过 NAT 端口转发测试它们之间的通信 但首先 我只想在对其余部
  • 查找所有 DHCP 和 DNS 服务器

    我有一位客户要求我找到他所有的 Dhcp 和 DNS 服务器以及一些附加信息 例如 DC 服务器和操作系统 所以我决定尝试提高我的 powershell 技能 但我对此还很陌生 所以我写了这个脚本 但我想仍然缺少一些东西 因为它不起作用 编
  • 开放简历fisherfaces

    我有这个问题 当我使用 vs2010 调试 opencv 2 4 0 facetec demo c 运行时 程序出现此错误 OpenCV错误 未知函数中图像步长错误 矩阵不连续 因此其行数无法更改 文件 src opencv modul e
  • 使用 Rust 构建的 DLL 在运行时是否需要 libgcc.dll?

    如果我构建一个 DLLRust 语言 http rust lang org 是否需要libgcc dll在运行时出现 一方面 我在互联网上的某个地方看到过一个帖子 声称是的 rustc exe has libgcc s dw2 1 dll在
  • 解密/读取/修改“.automaticDestinations-ms”和/或“.customDestinations-ms”

    有谁知道如何读取 Microsoft 为 JumpList 创建的文件 我想从 JumpList 中清除所有历史记录 最常访问的 最近关闭的 而不清除任务 我尝试使用 win7api 中的 APPID 并清除例如 google chrome
  • 如何获取Postgres当前的可用磁盘空间?

    在开始在数据库中进行某些工作之前 我需要确保至少有 1Gb 的可用磁盘空间 我正在寻找这样的东西 select pg get free disk space 是否可以 我在文档中没有找到任何相关内容 PG 9 3 操作系统 Linux Wi
  • MD 和 MKDIR 批处理命令有什么区别?

    这两个命令都会创建文件夹 我read http www computerhope com mdhlp htmMKDIR 甚至可以创建子文件夹 这只是区别吗 为什么有两个命令做同样的事情 我应该使用哪一个 除了 npocmaka 的answe
  • SQLAPI++ 的免费替代品? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有任何免费 也许是开源 的替代品SQLAPI http www sqlapi com 这个库看起来
  • 无法在 Windows 10 上运行 Python 3.7“权限被拒绝”

    当尝试使用 Git Bash 在 Windows 10 上运行 Python 3 7 时 出现以下错误 python version bash c Users Name AppData Local Microsoft WindowsApps
  • 如何在 Windows 上使用命令行获取 svn 修订信息

    我正在尝试使用此命令行获取头部的修订信息 svn info https myserver branches Code Improvements rHEAD find Revision 然而 这返回修订版 1234 由于我使用 svn inf
  • 歌曲搜索和流预览 API [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有 API 可以让我搜索歌曲 然后在我的网站上流式传输该歌曲的预览 查看了 Amazon MP3 但
  • 电报频道的帖子观看次数[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想了解有关电报频道的帖子浏览计数系统的更多信息 它是如何工作的 与此相关的API VB 部分是什么 我也有这个疑问 为了得到答案 我
  • 如何按名称杀死进程? (Win32 API)

    基本上 我有一个将启动多次的程序 因此 该程序将启动两个或多个进程 我想使用 Win32 API 并终止 终止具有特定名称的所有进程 我见过杀死一个进程的例子 但没有看到多个具有完全相同名称 但参数不同 的进程 尝试下面的代码 killPr
  • 如何使用 blazor 前端 http 请求附加令牌

    我使用 blazor 作为前端 api 已完成 JWT 配置 前端可以创建用户帐户并登录API 但现在我的前端httpclient没有设置JWT令牌 所以如果我在Api控制器中设置 授权 前端将无法访问它 api程序代码如下 builder
  • Web 应用程序的带宽和流量模拟器?

    您能否建议如何创建一个测试环境来模拟 Web 应用程序中的各种类型的带宽和流量 或者也许是一个针对本地主机执行此操作的开源程序 我认为在编写网络应用程序时这是一个非常重要的主题 但这不是一个常见的主题 我能想象创建这种环境的唯一方法是在本地
  • 如何通过文件关联执行已启动应用程序的事件?

    在尝试了一个新的 Windows 窗体项目后 我发现当您将文件类型与 Windows 中的可执行文件关联时 您可以使用以下命令找到启动应用程序的文件的文件路径args 0 from static void Main string args
  • 是否有可能劫持标准输出

    我正在尝试使用 C 重定向 Windows XP 上已运行进程的标准输出 我知道如果我自己生成进程 我可以做到这一点 但对于这个应用程序 我更喜欢一个 监听器 我可以附加到另一个进程 这在纯 Net 中可能吗 如果不可能 在 Win32 中
  • 如何从 Qt 应用程序通过 ODBC 连接到 MySQL 数据库?

    我有一个新安装的 MySQL 服务器 它监听 localhost 3306 从 Qt 应用程序连接到它的正确方法是什么 原来我需要将MySQL添加到ODBC数据源 我在遵循这个视频教程后做到了这一点 https youtu be K3GZi
  • 如何告诉 IntelliJ 使用 Java 1.6 JDK 启动 gradle?

    一个简单的问题 即使经过几个小时的尝试和搜索 我也无法弄清楚 我安装了 Java 6 和 7 如何告诉 IntelliJ 使用 JDK 版本 1 6 启动 Gradle 构建 无论我做什么 IntelliJ 都会以以下方式开始我的 grad

随机推荐