惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
A
About on SuperTechFans
博客园 - Franky
Engineering at Meta
Engineering at Meta
Recent Announcements
Recent Announcements
云风的 BLOG
云风的 BLOG
B
Blog
Microsoft Security Blog
Microsoft Security Blog
L
LangChain Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
U
Unit 42
Martin Fowler
Martin Fowler
Y
Y Combinator Blog
Stack Overflow Blog
Stack Overflow Blog
博客园 - 叶小钗
Vercel News
Vercel News
Apple Machine Learning Research
Apple Machine Learning Research
The Cloudflare Blog
Last Week in AI
Last Week in AI
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
爱范儿
爱范儿
V
V2EX
G
Google Developers Blog

博客园 - format

使用Arduino Nano驱动Lora模块 DIY一个物联网平台:想法 jQuery 批量操作checkbox 国内的maven镜像 Python Flask UnicodeDecodeError 编码错误解决 关于Python的web框架 NHibernate 3 中的 In 集合查询 在MVC 4 中使用自定义Membership [学习][Java] Struts2 与页面传值 (转) C++ Utf8字符转换Gb312编码,解决TinyXml中文乱码 Linux学习 -- Linux的可执行文件 WINSocket编程 发生HTTP GET请求,并接收服务器返回 Win32 API 的文件操作 - format C++ 类中封装Win32API的回调函数 Win32编程 创建从资源文件定义的对话框 Oracle 数据库 用脚本建表空间 把UserControl通过代码控制输入HTML WebService调用时候的Object Moved 异常 ICTCLAS 平台调用的封装
WIN32简单的窗体代码,带函数功能注释
format · 2010-08-13 · via 博客园 - 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);
}