zoukankan      html  css  js  c++  java
  • windows消息机制的有趣发现(二)

    3.一个有窗口和窗口过程函数但没有消息循环的程序

    一个程序,如果我们创建了窗口,也定义了窗口过程函数,但是没有建立消息循环会怎样呢?我们在win32控制台项目下编写如下代码:

    #include <windows.h>
    #define WM_TEST 10000
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
     
    void main()
    {
    	static TCHAR szAppName[]=TEXT("Test!");		
    	HWND hwnd;														
    	WNDCLASS wndclass = {NULL};
    	wndclass.lpfnWndProc = WndProc;
    	wndclass.style = CS_HREDRAW|CS_VREDRAW;
    	wndclass.lpszClassName	= szAppName;
    	RegisterClass(&wndclass);
    	hwnd=CreateWindow(szAppName,
    		TEXT("The Test Program"),										
    		WS_OVERLAPPEDWINDOW,											
    		CW_USEDEFAULT,												
    		CW_USEDEFAULT,												
    		CW_USEDEFAULT,													
    		CW_USEDEFAULT,
    		NULL,
    		NULL,	
    		NULL,
    		NULL);	
    	ShowWindow(hwnd,SW_SHOW);
    	UpdateWindow(hwnd);	
    
    	system("pause");
    }
    
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM IParam) 
    {	
    	switch(message)
    	{
    	case WM_TEST:
    		MessageBox(NULL,TEXT("消息响应!"),TEXT("消息响应!"),MB_OK);
    		return 50;
    	}
    	return DefWindowProc(hwnd,message,wParam,IParam);
    }

    这是一个简单的win32窗口程序,但是我们在窗口过程函数WndProc中没有定义对WN_PAINT消息的处理,在main函数中创建完窗口后也没有建立消息循环,运行程序后会发生什么呢?

    运行发现,窗口确实被创建出来了。但是鼠标移动上去就会发现该窗体如图假死一样没有了响应。这是因为包括自绘消息WM_PAINT在内的所有消息都被放入了线程的消息队列里,但是我们没有消息循环!没有取出消息队列中的消息,更没有处理这些消息,我们连窗口过程中对应WM_PAINT的消息处理函数都没有。界面自然就假死了。

    4.SendMessage和PostMessage消息的另一个区别

    之前我写过一篇博文说过SendMessage和PostMessage的却别在于SendMessage要等消息被处理完成后才返回,如果调用SendMessage后该消息一直未处理完,SendMessage会一直阻塞到处理完为止。而PostMessage不会阻塞,不等处理结果直接返回。实际上他们还有一个区别:PostMessage发送的消息会进入消息队列等待提取,而SendMessage发送的消息不进消息队列,直接交给窗口过程函数处理。为了验证这个说法,我们编写如下代码:

    #include <windows.h>
    #define WM_TEST 10000
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
     
    void main()
    {
    	static TCHAR szAppName[]=TEXT("Test!");		
    	HWND hwnd;														
    	WNDCLASS wndclass = {NULL};
    	wndclass.lpfnWndProc = WndProc;
    	wndclass.style = CS_HREDRAW|CS_VREDRAW;
    	wndclass.lpszClassName	= szAppName;
    	RegisterClass(&wndclass);
    	hwnd=CreateWindow(szAppName,
    		TEXT("The Test Program"),										
    		WS_OVERLAPPEDWINDOW,											
    		CW_USEDEFAULT,												
    		CW_USEDEFAULT,												
    		CW_USEDEFAULT,													
    		CW_USEDEFAULT,
    		NULL,
    		NULL,	
    		NULL,
    		NULL);	
    	ShowWindow(hwnd,SW_SHOW);
    	UpdateWindow(hwnd);	
    
    	int i = SendMessage(hwnd,WM_TEST,NULL,NULL);
    
    	system("pause");
    }
    
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM IParam) 
    {	
    	switch(message)
    	{
    	case WM_TEST:
    		MessageBox(NULL,TEXT("消息响应!"),TEXT("消息响应!"),MB_OK);
    		return 50;
    	}
    	return DefWindowProc(hwnd,message,wParam,IParam);
    }

    我们在创建完窗口后用SendMessage发送了一条WM_TEST的自定义消息,在窗口过程函数WndProc中我们定义对WM_TEST的处理方式为弹出一个MessageBox并返回50。

    运行后发现,纵使我们创建的窗体依然是假死状态,仍然弹出了MessageBox,并且SendMessage的返回值i为50。说明我们在窗口过程函数WndProc中定义的对WM_TEST消息的处理代码成功执行!注意,我们这个程序中是没有消息循环的,但是我们用SendMessage发送的消息还是被窗口过程函数WndProc处理了。

    我们把SendMessage改为PostMessage再试。运行后发现没有弹出MessageBox。为什么呢?因为PostMessage发送的消息要进消息队列,但我们没有消息循环,没有用GetMessage之类的函数从消息队列中取消息,更没有用DispatchMessage分发消息,所以我们用PostMessage发送的WM_TEST还在消息队列里待着呢。窗口过程函数WndProc中的代码没有执行。

    这就证明了SendMessage和PostMessage的另一个不同之处:SendMessage发送的消息直接交给对应的窗口过程函数处理,不进消息队列,而PostMessage发送的消息要进消息队列等待分发、处理。

  • 相关阅读:
    【Unity】近期整理Unity4.x 项目升级Unity5.0 过程中出现的各种常见问题,与大家共享。
    extjs Combox 调用数据
    CSDN博客2014年4月24日清理缓存
    在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法訪问server。请验证实例名称是否正确而且 SQL Server 已配置为同意远程连接。
    海思 3520D 移植Qt4.5.3 一
    Android 输入框限制字符输入数
    Making User-Managed Backups-17.4、Making User-Managed Backups of Online Tablespaces and Datafiles
    spring 使用外部属性文件
    mysql字符串替换
    maven3+eclipse搭建webAPP企业级实战《一》
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/2995477.html
Copyright © 2011-2022 走看看