当我们启动一个线程,并且要给线程函数传递的参数是窗口句柄时,我们应该这样做:

HWND hHwnd = GetSafeHwnd();

HANDLE hThread;

DWORd dwThreadId;

hThread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)DeviceOnLine, (LPVOID)hHwnd, 0, &dwThreadId);

// DeviceOnLine是线程函数,原型static UINT DeviceOnLine(LPVOID pParam);

// 注意:参数的形式是这样的 (LPVOID)hHwnd,没有地址符,注意啊!为什么要传递的参数非得是句柄呢?(对啊,为什么?)应为我们要使线程函数和主线程通信,要使用PostMessage(...)函数,所以要谈到Windows的消息机制。

// -----------------------下面是Windows消息机制

Windows系统是一个消息驱动的OS,什么是消息呢?我很难说得清楚,也很难下一个定义(谁在嘘我),我下面从不同的几个方面讲解一下,希望大家看了后有一点了解。

1、消息的组成:一个消息由一个消息名称(UINT),和两个参数(WPARAM,LPARAM)。当用户进行了输入或是窗口的状态发生改变时系统都会发送消息到某一个窗口。例如当菜单转中之后会有WM_COMMAND消息发送,WPARAM的高字中(HIWORD(wParam))是命令的ID号,对菜单来讲就是菜单ID。当然用户也可以定义自己的消息名称,也可以利用自定义消息来发送通知和传送数据。

2、谁将收到消息:一个消息必须由一个窗口接收。在窗口的过程(WNDPROC)中可以对消息进行分析,对自己感兴趣的消息进行处理。例如你希望对菜单选择进行处理那么你可以定义对WM_COMMAND进行处理的代码,如果希望在窗口中进行图形输出就必须对WM_PAINT进行处理。

3、未处理的消息到那里去了:M$为窗口编写了默认的窗口过程,这个窗口过程将负责处理那些你不处理消息。正因为有了这个默认窗口过程我们才可以利用Windows的窗口进行开发而不必过多关注窗口各种消息的处理。例如窗口在被拖动时会有很多消息发送,而我们都可以不予理睬让系统自己去处理。

4、窗口句柄:说到消息就不能不说窗口句柄,系统通过窗口句柄来在整个系统中唯一标识一个窗口,发送一个消息时必须指定一个窗口句柄表明该消息由那个窗口接收。而每个窗口都会有自己的窗口过程,所以用户的输入就会被正确的处理。例如有两个窗口共用一个窗口过程代码,你在窗口一上按下鼠标时消息就会通过窗口一的句柄被发送到窗口一而不是窗口二。

5、示例:下面有一段伪代码演示如何在窗口过程中处理消息

LONG yourWndProc(HWND hWnd,UINT uMessageType,WPARAM wP,LPARAM)
{
        switch(uMessageType)
        {//使用SWITCH语句将各种消息分开
               case(WM_PAINT):
                       doYourWindow(...);//在窗口需要重新绘制时进行输出
               break;
               case(WM_LBUTTONDOWN):
                       doYourWork(...);//在鼠标左键被按下时进行处理
               break;
               default:
                       callDefaultWndProc(...);//对于其它情况就让系统自己处理
               break;
        }
}

接下来谈谈什么是消息机制:系统将会维护一个或多个消息队列,所有产生的消息都回被放入或是插入队列中。系统会在队列中取出每一条消息,根据消息的接收句柄而将该消息发送给拥有该窗口的程序的消息循环。每一个运行的程序都有自己的消息循环,在循环中得到属于自己的消息并根据接收窗口的句柄调用相应的窗口过程。而在没有消息时消息循环就将控制权交给系统所以Windows可以同时进行多个任务。下面的伪代码演示了消息循环的用法:

while(1)
{
        id=getMessage(...);
        if(id == quit)
               break;
        translateMessage(...);
}

当该程序没有消息通知时getMessage就不会返回,也就不会占用系统的CPU时间。 下图为消息投递模式

在16位的系统中系统中只有一个消息队列,所以系统必须等待当前任务处理消息后才可以发送下一消息到相应程序,如果一个程序陷如死循环或是耗时操作时系统就会得不到控制权。这种多任务系统也就称为协同式的多任务系统。Windows3.X就是这种系统。

而32位的系统中每一运行的程序都会有一个消息队列,所以系统可以在多个消息队列中转换而不必等待当前程序完成消息处理就可以得到控制权。这种多任务系统就称为抢先式的多任务系统。Windows95/NT就是这种系统。

// -------------------------------------------

不知道,你还记得那个线程函数吗?下面是定义

UINT DeviceOnLine(LPVOID pParam)
{
        HWND hHwnd = (HWND)pParam;    // 转化参数

...

CString str;

str.Format("test");

::PostMessage(hHwnd, WM_MY_MESSAGE, (WPARAM)str, NULL);   // 向hHwnd句柄PostMessage

// 要是static类型的,记住static函数的使用方法:一个版本,仅仅与类对话,没有this指针。

...

}

如果要使用PostMessage很多次,我们可以象下面这样独立出一个函数(由于我们是在static的线程函数里面使用,所以声明的也是static):

static int AddMessage(HWND hWnd, CString str)
 {
        if(str.GetLength() <= 0)
             return 0;
        char *newMess = new char[str.GetLength() + 1];
        strcpy(newMess,str);
        ::PostMessage(hWnd,WM_MY_MESSAGE,(WPARAM)newMess,0);
        return 0;
 }

现在,我们已经把我们需要的消息发了出去,那我们就还要处理它,不然我们还发它们干吗呢,呵呵(废话,快点说吧)!

首先:在类中声明处理函数,比如 afx_msg LRESULT AddMessageEx(WPARAM wPapam, LPAPAM lPapam);

其次:在Message Map中加入映射,比如:

BEGIN_MESSAGE_MAP(CTestDlg, CDialog)

ON_MESSAGE(WM_MY_MESSAGE, AddMessageEx)

END_MESSAGE_MAP

最后,实现处理函数:

LRESULT CTestDlg::AddMessageEx(WPARAM wParam, LPARAM lParam)
{
 char* newMsg = (char*)wParam;
 if(newMsg == NULL)
  return -1;
...    // 这里就可以使用我们接收的消息啦,哈哈!目的完成。

delete newMsg;
 return 0;
}

对了,还有一个比不可少的,就是在stdafx.h文件中加入,自己定义的消息

#define WM_MY_MESSAGE (WM_USER+123)

原文地址:http://blog.chinaunix.net/uid-20680966-id-1896390.html

*********************************以上是转载内容**************************************有空继续编辑**************************************************
 

句柄线程做参数和PostMessage的用法的更多相关文章

  1. C++数组做参数

    首先,看一下下面这段代码: void changearr(int a[],int n){    cout<<sizeof(a)<<endl;         // 输出4}in ...

  2. C++ 中数组做参数的分析

    C++ 中数组做参数的分析 1.数组降价问题? "数组引用"以避免"数组降阶",数组降阶是个讨厌的事,这在C语言中是个无法解决的问题,先看一段代码,了解什么是& ...

  3. ASP.NET Boilerplate 学习 AspNet Core2 浏览器缓存使用 c#基础,单线程,跨线程访问和线程带参数 wpf 禁用启用webbroswer右键菜单 EF Core 2.0使用MsSql/MySql实现DB First和Code First ASP.NET Core部署到Windows IIS QRCode.js:使用 JavaScript 生成

    ASP.NET Boilerplate 学习   1.在http://www.aspnetboilerplate.com/Templates 网站下载ABP模版 2.解压后打开解决方案,解决方案目录: ...

  4. 用 ThreadPoolExecutor/ThreadPoolTaskExecutor 线程池技术提高系统吞吐量(附带线程池参数详解和使用注意事项)

    1.概述 在Java中,我们一般通过集成Thread类和实现Runnnable接口,调用线程的start()方法实现线程的启动.但如果并发的数量很多,而且每个线程都是执行很短的时间便结束了,那样频繁的 ...

  5. 使用hibernate validate做参数校验

    1.为什么使用hibernate validate ​ 在开发http接口的时候,参数校验是必须有的一个环节,当参数校验较少的时候,一般是直接按照校验条件做校验,校验不通过,返回错误信息.比如以下校验 ...

  6. 动态线程池(DynamicTp)之动态调整Tomcat、Jetty、Undertow线程池参数篇

    大家好,这篇文章我们来介绍下动态线程池框架(DynamicTp)的adapter模块,上篇文章也大概介绍过了,该模块主要是用来适配一些第三方组件的线程池管理,让第三方组件内置的线程池也能享受到动态参数 ...

  7. 【Java分享客栈】SpringBoot线程池参数搜一堆资料还是不会配,我花一天测试换你此生明白。

    一.前言   首先说一句,如果比较忙顺路点进来的,可以先收藏,有时间或用到了再看也行:   我相信很多人会有一个困惑,这个困惑和我之前一样,就是线程池这个玩意儿,感觉很高大上,用起来很fashion, ...

  8. c#线程带参数

    c#线程带参数 ThreadStart threadStart = delegate { LoadPicture(ds.Tables[0]); }; Thread thread = new Threa ...

  9. 做参数可以读取参数 保存参数 用xml文件的方式

    做参数可以读取参数 保存参数 用xml文件的方式 好处:供不同用户保存适合自己使用的参数

随机推荐

  1. 小程序动态添加class及调接口传递多个参数

    1.动态添加class <view class="step2 {{indication == 2 ?'on':''}}"> <view class='tc lef ...

  2. 完整的Django入门指南学习笔记4

    前言 这一章节将会全面介绍 Django 的身份认证系统,我们将实现注册.登录.注销.密码重置和密码修改的整套流程. 同时你还会了解到如何保护某些试图以防未授权的用户访问,以及如何访问已登录用户的个人 ...

  3. 函数和函数模版在一个。cpp中的情况!(除了左移和右移,其他的不要用友元函数!!!)

    // 友元函数和运算符重载的碰撞.cpp : 定义控制台应用程序的入口点. // #include <iostream> using namespace std; template < ...

  4. Ubuntu下忘记MySQL root密码解决方法

    1.忘了mysql密码,从网上找到的解决方案记录在这里. 编辑mysql的配置文件/etc/mysql/my.cnf,在[mysqld]段下加入一行“skip-grant-tables”. 2.重启服 ...

  5. 2017-3-29/HTTP协议1

    1. 讲讲你对http的理解. HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传输协议,是一个客户端和服务器端请求和 ...

  6. 第 3 章 HTML5 网页中的文本和图像

    文字和图像是网页中最主要.最常用的元素. 在互联网高速发展的今天,网站已经成为一个展示与宣传自我的通信工具(公司或个人可以通过网站介绍公司的服务与产品或介绍自己).这些都离不开网站中的网页,而网页的内 ...

  7. spring-boot 全面认知

    https://blog.csdn.net/ityouknow/article/details/80490926,这个链接非常全面的讲解了spring-boot的内容,从初级到中级,到最后的提升,觉得 ...

  8. java后台判断浏览器的版本

    public static void main(String[] args) {              String agent=request.getHeader("User-Agen ...

  9. Physical Limits of ASM

    Oracle version 7, only 1,022 datafiles per database could be used.  Oracle version 11g, support 65,5 ...

  10. .net mvc 列名 'Discriminator' 无效

    环境:asp.net 4.0 + MVC 4 + Entity Framework 5异常:使用code first 碰到错误:列名 'Discriminator' 无效.这是一个很少见的错误,搜索了 ...