/*
测试多窗口程序
 */
#include <windows.h> HINSTANCE hInst;
    
//第一个消息循环函数
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
//第二个消息循环函数
LRESULT CALLBACK WndProc1 (HWND, UINT, WPARAM, LPARAM) ;
//开始函数
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 

PSTR szCmdLine, int iCmdShow)    
{
hInst=hInstance;
   //声明且初始化变量
   static TCHAR szAppName[] = TEXT ("BtnLook") ;
   HWND hwnd ;   
   MSG msg ;
   WNDCLASS wndclass ;
   wndclass.style = CS_HREDRAW | CS_VREDRAW ;   
   wndclass.lpfnWndProc = WndProc ;   
   wndclass.cbClsExtra = 0 ;   
   wndclass.cbWndExtra = 0 ;   
   wndclass.hInstance = hInstance ;  
   wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;  
   wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;  
   wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;  
   wndclass.lpszMenuName = NULL ;  
   wndclass.lpszClassName = szAppName ;
   //初始化结束    
   
   //注册变量
   RegisterClass (&wndclass);   
 
   //创建窗口
   hwnd = CreateWindow (szAppName, TEXT ("Button Look"),
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          NULL, NULL, hInstance, NULL) ;
    //显示窗口
    ShowWindow (hwnd, SW_SHOW) ;
    UpdateWindow (hwnd) ; //消息循环
    while (GetMessage (&msg, NULL, 0, 0))
    {  
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
        
    }  
MessageBox(NULL,"ABC","ABC",0);
    return msg.wParam ;
}
        
//第一个回调函数
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        
{
   static TCHAR szAppName1[] = TEXT ("BtnLook1") ;
   int i=0;
   switch (message)
           {
   //窗口创建时添加一个按钮
case   WM_CREATE :                    CreateWindow ( TEXT("button"),TEXT("button"),   
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
10, 
10,
200,
200,
                    hwnd,
(HMENU) 1,
((LPCREATESTRUCT) lParam)->hInstance,
NULL) ;
return 0 ;
//单击按钮时创建另一个窗口
case   WM_COMMAND :
//变量声明初始化
HWND  hwnd1 ;
MSG   msg ;
WNDCLASS  wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc1 ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance =hInst ;//这里出了问题
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName1 ;
//初始化结束
/*
//注册
RegisterClass (&wndclass); 

//创建
hwnd1 = CreateWindow (szAppName1, TEXT ("Button Look"),
                            WS_OVERLAPPEDWINDOW,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            NULL, NULL, hInst, NULL) ;//这里出了问题
//显示
ShowWindow (hwnd1, SW_SHOW) ;
UpdateWindow (hwnd1) ;

//消息循环
while (GetMessage (&msg, NULL, 0, 0))
{  
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
*/
for(;i<100;)
{}
break ; //结束
case   WM_DESTROY :
                  PostQuitMessage (0) ;
        
                  return 0 ;    }
        
           return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}//第二个回调函数
LRESULT CALLBACK WndProc1 (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)   
{
   switch (message)
           { //结束
case   WM_DESTROY :
                  PostQuitMessage (0) ;
        
                  return 0 ;    }
       return DefWindowProc (hwnd, message, wParam, lParam) ;  
}
这段代码显示一个窗口,上面添加一个按钮,现在在按钮的事件中添加了一个死循环,单击按钮就死掉了,而如果把这死循环去掉,把上面的消息循环去掉注释却可以正常运行,为什么呢?不都是死循环吗?
死循环处为
for(;i<100;){}

解决方案 »

  1.   


    消息循环和for(;i<100;){}是不一样的。
      

  2.   

    Windows接收I/O输入并分送到各个进程的消息队列里头,(可能是马上或者是轮到这个进程的时间片时)该进程从GetMessage (&msg, NULL, 0, 0)里头开始运行,随后窗口处理函数被调用。当消息队列里头没有消息时,GetMessage (&msg, NULL, 0, 0)会象一些挂起函数那样使进程被挂起。
      

  3.   

    这段代码显示一个窗口,上面添加一个按钮,现在在按钮的事件中添加了一个死循环,单击按钮就死掉了,而如果把这死循环去掉,把上面的消息循环去掉注释却可以正常运行--这是你说的话看来你是真的不太懂应用程序的框架结构,或者说你正在学。
    Windows的CPU在处理时是按时间片进行分配的,而这个时间片是以线程为单位的。
    以上你创建的应用程序是处在同一个线程中,而你的死循环,亦for(;i<100;){}在处理你的新窗口的创建以后就会一直占用时间片,你的程序完全没有机会发送和处理其他消息,当然也就死掉了。
      

  4.   

    GetMessage会挂起当前线程,不是进程.
    每一个窗口消息都必要返回后才会执行后续的消息处理,你在第一个窗口的消息处理里面调用了第二个消息循环,导致第一个消息处理函数无法返回.也就是第一个窗口的消息处理函数无法再处理后续消息.当然会无响应了.
    花点时间多看看MSDN里面关于消息循环的部分,这可是WINDOWS的基础再基础不过的东西了.基础,而且非常重要.
      

  5.   

    panzer_v() :
    他的理论完全正确,可以学一下。不过没说问题。
    aaronwang81(痞子) :
    你的理论是正确的,但所说的问题也并不是问题所在,不要误导LZ了。楼主,我昨天就回复过你的上一个问题,相信我吧。呵呵
      

  6.   

    aaronwang81(痞子) 
    每一个窗口消息都必要返回后才会执行后续的消息处理可是我的代码打开新窗口时并没有返回啊,怎么可以照样执行呢?
      

  7.   

    我的理解是一个线程在处理消息,他通过不同的消息调用不同的代码,如果这线程执行了一个死循环,那这样处理消息的线程就死掉了
    完全正确 +10分 呵呵
    后面的所谓线程被挂起是指CPU转而去处理其他线程了。
      

  8.   

    后面的所谓线程被挂起是指CPU转而去处理其他线程了。那这条线程都挂起了,难道他还有别的线程来处理消息?
      

  9.   

    那这条线程都挂起了,难道他还有别的线程来处理消息?我晕。挂起你的线程,意谓着CPU此时间段在处理其他的应用程序。一个系统不仅仅处理你的程序吧。一个线程内的所有消息都是由这个线程管理的,如果此线程被挂起,所有线程内的代码都不会被执行。CPU会根据当前系统内的应用程序数量,级别,自动给应用程序分配时间片,当然,被挂起也就会被唤醒。只所以这样分配时间片是因为CPU在同一时间只能处理一个线程内代码,但有多个任务存在的时候,通过时间片的分配可以在宏观上达到多任务同时处理的效果。可不可以这想理解,我在事件中创建了一个窗口,本身的窗口处理消息线程被挂起,而在新的窗口又开启了一个消息处理线程,一共两个消息处理线程,第一个被挂起了,第二个在正常工作?这个是完全错误的。不管有多少消息循环,都是在同一线程中执行的,除非你新建线程,并在其中创建窗口。MFC分配消息的机制是通过窗口句柄映射来管理不同窗口的消息的。(CHandleMap)这是你下步需要学习的东西。它存储在线程状态类AFX_MODULE_THREAD_STATE中,这是线程的私有量,用于管理线程内的信息。先说这么多,说多了你又混了!
      

  10.   

    最新发现把
    while (GetMessage (&msg, NULL, 0, 0))
    {  
    TranslateMessage (&msg) ;
    DispatchMessage (&msg) ;
    }第二个窗口里的,去掉也可以
      

  11.   

    如果在创建窗口命令后加上弹出对话框命令,在弹出对话框之前,线程以挂起了,也就是在等新的消息,可为什么在窗口结束后会弹出这对话框呢?
    找本书看看线程,进程及时间片的分配吧。你的这些问题根本就是这一个问题你不懂。
    你第二个发现也不算什么发现。一个窗口对应一个消息循环,这是无疑的。不过MFC机制把线程内所有窗口函数放在一起处理。至于怎么处理我也说过了。