format Blog

给我个权限,我format你的硬盘.

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
//一个简单的Win32应用程序

//通过这个简单的实例讲解Windows消息是如何传递的

#include 
"stdafx.h"
#include 
<windows.h>

//声明窗口过程函数
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

//定义一个全局变量,作为窗口类名
TCHAR szClassName[] = TEXT("SimpleWin32");

//应用程序主函数
int WINAPI WinMain (HINSTANCE hInstance,
                                  HINSTANCE hPrevInstance,
                                  LPSTR szCmdLine,
                                  
int iCmdShow)
{

    
//窗口类
    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 = szClassName;//类名称

    
//注册窗口类
    if(!RegisterClass (&wndclass))
    {
           MessageBox (NULL, TEXT (
"RegisterClass Fail!"), 
                   szClassName, MB_ICONERROR);
           
return 0;
    }

 

    
//建立窗口
    HWND hwnd;
    hwnd 
= CreateWindow(szClassName,//窗口类名称
           TEXT ("The Simple Win32 Application"),//窗口标题 
           WS_OVERLAPPEDWINDOW,//窗口风格,即通常我们使用的windows窗口样式
           CW_USEDEFAULT,//指定窗口的初始水平位置,即屏幕坐标系的窗口的左上角的X坐标
           CW_USEDEFAULT,//指定窗口的初始垂直位置,即屏幕坐标系的窗口的左上角的Y坐标
           CW_USEDEFAULT,//窗口的宽度
           CW_USEDEFAULT,//窗口的高度
           NULL,//父窗口句柄
           NULL,//窗口菜单句柄
           hInstance,//实例句柄
           NULL);

    ShowWindow(hwnd,iCmdShow);
//显示窗口
    UpdateWindow(hwnd);//立即显示窗口



    
//消息循环
    MSG msg;

    
/*
    GetMessage()从消息队列中取消息,对取出的消息进行转换(TranslateMessage),
    对于能够将虚拟键码转化成字符码的消息,会在消息队列里放一条WM_CHAR消息,
    最后将消息发送到相应的消息处理函数进行处理。
    循环执行这个处理过程,直到收到WM_QUIT消息,才退出循环,结束程序。
    
*/
    
while(GetMessage(&msg,0,0,0))//从消息队列中取消息 
    {
           TranslateMessage (
&msg);              //转换消息
           DispatchMessage (&msg);               //派发消息
    }
    
return msg.wParam;
    
/*---------------GetMessage---------------------------------
    GetMessage

    函数原型:
    BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);

    参数:
    lpMsg:一个指向MSG结构的指针,该结构用于存放从消息队列里取出的消息。
    hWnd:窗口句柄。如果该参数是非零值,则GetMessage只检索该窗口(也包括其子窗口)消息,如果为零,则GetMessage检索整个进程内的消息。
    wMsgFilterMin:指定被检索的最小消息值,也就是消息范围的下界限参数。
    wMsgFilterMax:上界限参数。如果wMsgFilterMin和wMsgFilterMax都为零,则不进行消息过滤,GetMessage检索所有有效的消息。

    返回值:
    GetMessage检索到WM_QUIT消息,返回值是零;其它情况,返回非零值。

    函数功能:
    这个API函数用来从消息队列中“摘取”一个消息,放到lpMsg所指的变量里。(注:如果所取窗口的消息队列中没有消息,则程序会暂停在GetMessage(…) 函数里,不会返回。)
    再通俗一点讲解GetMessage函数:
    当程序执行GetMessage()的时候,会检查消息队列,如果有消息在消息队列里,它取出该消息,将该消息填充到lpMsg所指的MSG结构,并返回TRUE值。如果此时消息队列里没有消息(消息队列为空),它会将线程阻塞,也就是将控制权交给系统,直到消息队列中有内容时,才唤醒线程继续执行。
    对于GetMessage()函数,还有一点需要说明,就是当从消息队列中取出的消息是WM_QUIT时,函数返回值是0。我们一般利用这一点退出消息循环,结束程序。
    ---------------------------------------------------------------
*/

    
/*------------------TranslateMessage---------------------
    TranslateMessage 

    函数原型:

    BOOL TranslateMessage(CONST MSG*lpMsg);

    参数:
      IpMsg:指向MSG结构的指针,该结构是函数GetMessage或PeekMessage从消息队列里取得的消息。

     函数功能:
        该函数将虚拟键消息转换为字符消息。字符消息被寄送到调用线程的消息队列里,当下一次线程调用函数GetMessage或PeekMessage时被读出。
    什么是虚拟键码呢?Windows为了方便输入管理,减少程序对设备的依赖性,将键盘上所有的按键都用一个两位十六进制数对应,这些数称为虚拟键码。虚拟键码一般以VK_开头,如:Esc键对应的虚拟键码是VK_ESCAPE;空格键对应的虚拟键码是VK_SPACE;VK_LWIN与左边的Windows徽标键相对应。
    当一个按键被按下时,会触发WM_KEYDOWN消息, WM_KEYDOWN消息的wParam参数值就是虚拟键值。通过这个值就可以判断哪个键被按下了。
    为什么我们要把虚拟键码转换为字符码呢?
    比如我们按下了‘A’键,此时我们得到的字符可能是‘A’,也可能是小写的‘a’,这由当时的大写状态(Caps Lock)以及是否同时按下了Shift键有关。TranslateMessage()函数的作用就是不用我们考虑这些问题,而是根据这些情况,自动返回一个ASCII码值,以方便用户使用。
    并不是所有的虚拟键码值都会Translate成字符码。字母、数字键都有字符码相对应,而像方向箭头键、F1—F12功能键这些按键就没有字符码相对应。当虚拟键码需要转化成字符码时,TranslateMessage()函数就在消息队列里放一条WM_CHAR消息,WM_CHAR消息的wParam参数值就是转换后的ASCII码值。
    -------------------------------------------
*/

    
/*--------------------DispatchMessage-------------------
    DispatchMessage 

    函数原型:
    LONG DispatchMessage(CONST MSG *lpmsg);

    函数功能:
    它的作用很简单,就是分派消息到窗口的消息处理函数去执行。
    -------------------------------------------
*/

    
/*-----------------PeekMessage-------------
    PeekMessage

    函数原型:
    BOOL PeekMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax,UINT wRemoveMsg);

    参数:
    lpMsg、hWnd、wMsgFilterMin、wMsgFilterMax这四个参数的意义和GetMessage对应参数的意义相同,在此不再赘述。
    wRemoveMsg:这个参数决定读消息时是否删除消息,可选值有PM_NOREMOVE和PM_REMOVE。如果您选PM_NOREMOVE,执行该函数后消息仍然留在消息队列(我称为读消息);如果您选PM_REMOVE,执行该函数后将在消息队列中移除该消息(同GetMessage())。

    返回值:
    消息队列中有消息,返回值为TRUE;消息队列中没有消息,返回值为FALSE。

    函数功能:
    PeekMessage()也是从消息队列中取消息,但它是GetMessage()不同,主要在以下两点:

    (一)、GetMessage()只能从消息队列中取走消息,也就是说,GetMessage()执行后,该消息将从消息队列中移除。
    PeekMessage()可以从消息队列中取走消息。也可以读消息,让消息继续留在消息队列里。

    (二)、当消息队列中没有消息时,GetMessage()将会阻塞线程,等待消息;而PeekMessage()与GetMessage()不同,它执行后会立刻返回,消息队列中有消息时,返回值为TRUE;消息队列中没有消息时,返回值为FALSE。

    ------------------------------------
*/

    
/*-------------------PeekMessage版的消息循环---------------------------
    //消息循环
    MSG msg;

    while(true)
    {
          if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) //从消息队列中取消息
          {
                  if(msg.message == WM_QUIT)
                        break;
                  TranslateMessage (&msg);           //转换消息
                  DispatchMessage (&msg);            //派发消息
           }
           else
                  WaitMessage();

    } //End of while(true)
    
*/

    
/*------------------WaitMessage--------------------------
    WaitMessage

    函数原型:
    BOOL WaitMessage(VOID);

    函数功能:
    这个函数的作用是当消息队列中没有消息时,将控制权交给其它线程。该函数将会使线程挂起,直到消息队列中又有新消息。
    这个函数专门和PeekMessage配合使用,当消息队列中没有消息时,挂起线程,等待消息队列中新消息的到来,这样可以减轻CPU的运算负担。
    --------------------------------------------------
*/
}

//消息处理函数

//参数:窗口句柄,消息,消息参数,消息参数

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    
//处理感兴趣的消息
    switch (message)
    {
        
case WM_DESTROY:
            
//当用户关闭窗口,窗口销毁,程序需结束,发退出消息,以退出消息循环
            PostQuitMessage(0);
            
return 0;
    }
    
//其他消息交给由系统提供的缺省处理函数
    return ::DefWindowProc (hwnd, message, wParam, lParam);
}

 

posted on 2010-08-13 16:46  format  阅读(1170)  评论(0编辑  收藏  举报