Win32对话框程序(2)

接着Win32对话框程序(1)来写 ,解决遗留的问题,即理解函数及其调用关系。文章中有些地方是自己的推断,因此肯定有叙述不准确甚至错误的地方,请指正,感谢~ 

*******************************正文分割************************************

WinMain函数

Win32对话框程序(1)中说了WinMain是应用程序的入口,其输入参数有四个,根据MSDN上的叙述:

输入变量声明

说明

HINSTANCE    hInstance

此应用当前实例的句柄

HINSTANCE    hPrevInstance

此应用上一个实例的句柄,一般都是NULL

LPSTR    lpCmdLine

The command line for the application, excluding the program name

int    nCmdShow

设置窗口的显示方式,比如nCmdShow=SW_MAXIMIZE表示最大化窗口,详见MSDN

因为WinMain是应用程序的入口,即程序运行的第一个函数,所以这四个参数应该是操作系统传给WinMain的,至于操作系统是怎么把他们传进来的,现在没管~@_@~    

何为句柄?何为实例?如果我们同时运行两个记事本程序,我们会发现针对它们的不同操作是互不干扰的,这两个“窗口”即使记事本的两个实例,它们被加载在内存中的不同空间,但为了实现互不干扰的操作和处理,我们需要区分彼此,便使用句柄来标识应用程序的不同实例(两个记事本的句柄不同),我们能通过句柄访问相应对象的信息,但句柄不是指针,程序不能利用句柄来直接阅读文件中的信息,它只是一个唯一的整数值。 

lpCmdLine是不包含程序名的命令行,根据MSDN使用函数GetCommandLine()也可返回命令行字符串,不过会包含程序名。为了验证这个所谓的“命令行”是什么,在WinMain函数体开头加了两行代码将其显示出来

MessageBox(NULL, GetCommandLine(), TEXT("CMDLINE"), MB_OK);
MessageBox(NULL, lpCmdLine, TEXT("CMDLINE_1p"), MB_OK);

在VC6.0中运行,GetCommandLine()显示为完整路径包括程序名,lpCmdLine显示为空,如下:

于是我在命令行模式下运行,显示出所谓的The command line for the application究竟是什么,也许它可以用于向程序传递参数来进行交互式操作

此外,入口函数名并不一定是WinMain,也可以是main(),但需要在main函数体内显示的调用类似GetCommandLine()这样的函数来引入WinMain的四个参数并作为变量(后面需要使用),此外还有_tWinMain(需进一步查阅)

现在大体理解了WinMain函数了,接下来看看其他函数都在干什么

函数及程序框架理解

先贴WinMain函数

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    //Enable IPAddress、Calendar.etc
    InitCommonControls();
    DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, Main_Proc);
    return 0;
}

函数名

参数

说明

InitCommonControls

该函数注册并初始化通用控件窗口类,使用某些高级控件时需要调用此函数,链接器会将你的程序链接到comctl32.lib,然后在程序启动时,会加载comctl32.dll。(据MSDN,此函数已废弃,需使用InitCommonControlsEx)

DialogBox

(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, Main_Proc)

据MSDN,该函数Creates a modal dialog box from a dialog box template resource,然后将控制权交给自定义的Main_Proc函数,此回调函数通过调用EndDialog函数来终结the modal dialog box。 参数说明:参数1为包含The dialog box template的句柄,可以是NULL;参数2是The dialog box template,使用MAKEINTRESOURCE宏来讲对话框ID(整数)转化为resource type;参数3为A handle to the window that owns the dialog box;参数4为A pointer to the dialog box procedure,函数指针。

MainDlg.cpp中包含四个函数:

函数名

参数

功能

Main_Proc

(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

消息分流器,进行消息分流

Main_OnInitDialog

(HWND hwnd, HWND hwndFocus, LPARAM lParam)

return

Main_OnCommand

(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)

switch(ID),case

Main_OnClose

(HWND hwnd)

EndDialog

消息分流器

BOOL WINAPI Main_Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch(uMsg)
    {
        HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog);
        HANDLE_MSG(hWnd, WM_COMMAND, Main_OnCommand);
        HANDLE_MSG(hWnd, WM_CLOSE, Main_OnClose);
    }
 
    return FALSE;
}

HANDLE_MSG也是一个宏,它在windowsx.h中定义,如下:

#define HANDLE_MSG(hwnd, message, fn) case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))

比如代码

HANDLE_MSG(hWnd, WM_INITDIALOG, Main_OnInitDialog);

实际被替换为

case (WM_INITDIALOG): return HANDLE_WM_CREATE((hwnd), (wParam), (lParam), (Main_OnInitDialog))

可见,可见消息分流器的作用就是当消息出现时将控制权交给不同的程序,一些相关的参数也会同时传给相应程序。 

如WM_INITDIALOG等为消息,由操作系统传递给程序,根据MSDN,WM_INITDIALOG消息是在对话框马上要显示前(即对话框内存中已经准备好了,但还没有显示在屏幕上)发给程序的,程序可以在此时执行一些初始化操作;同理,WM_COMMAND消息和WM_CLOSE消息从字面就基本可以理解。 

接下来把其他三个函数的代码都贴在下面:

BOOL Main_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
{
    return TRUE;
}
 
void Main_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
{
    switch(id)
    {
        case IDC_OK:
        {           
            MessageBox(hwnd,TEXT("欢迎"),TEXT("问好"),MB_OK);
        }
        break;
        default:
        break;
    }
}
 
void Main_OnClose(HWND hwnd)
{
    EndDialog(hwnd, 0);
}

可见,Main_Proc函数是一直在执行中的,时刻等待操作系统传递消息进来,根据不同消息将控制权交予不同的函数,包括初始化和关闭函数,当然实现功能最主要的在函数Main_OnCommand中,对话框中有菜单和不同的控件,通过ID对他们进行标示,如果用户对他们进行了某种操作(比如单击),则在Main_OnCommand函数体内进入相应的case,执行其中的代码,如上,当点击“确定”按钮是会弹出“欢迎”对话框。

**********************************************************************************************

以上就是《C语言也能干大事》中介绍的对话框程序的基本框架,当然,对话框程序应该是Windows编程中很简单的,还有很多其他的内容需要学习,此外,学习windows编程很重要的一部分就是掌握尽可能多的API,万丈高楼平地起,一步步来~

遗留问题

操作系统是如何向程序传递参数的(不急迫),即更深入的理解Windows的消息传递机制;其他……

参考

  1. C语言也能干大事http://rupeng.com/forum/forum-52-1.html
  2. WinMain和main http://blog.163.com/hanyinlong@126/blog/static/99751486201212345130881/
  3. 消息分流器http://www.cnblogs.com/ifaithu/articles/2478841.html

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏NetCore

流畅地HtmlHelper-Asp.Net MVC

今天抛开 Fluent NHibernate 不谈,我们来谈谈 Asp.Net MVC ,在MVC的View中,我们经常会使用HtmlHelper来生成各种ht...

21580
来自专栏Flutter入门

Weex是如何在Android客户端上跑起来的

Weex可以通过自己设计的DSL,书写.we文件或者.vue文件来开发界面,整个页面书写分成了3段,template、style、script,借鉴了成熟的MV...

57050
来自专栏逸鹏说道

我这么玩Web Api(二)

数据验证,全局数据验证与单元测试 目录 一、模型状态 - ModelState 二、数据注解 - Data Annotations 三、自定义数据注解 四、全局...

55460
来自专栏calvin

.net core 源码解析-mvc route的注册,激活,调用流程(三)

mvc的入口是route,当前请求的url匹配到合适的route之后,mvc根据route所指定的controller和action激活controller并调...

26150
来自专栏开发 & 算法杂谈

Intel Pin-JIT模式和Probe模式下库函数的替换

这篇文章主要介绍一下Intel Pin在JIT模式和Probe模式下对库换数的替换,以及实现中有哪写需要注意的地方。

28860
来自专栏debugeeker的专栏

source insight coredump分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/detai...

9310
来自专栏Android 开发学习

JsBridge 源码分析

20730
来自专栏林德熙的博客

WPF 拼音输入法

实际上本文是在使用一个好用的软件 希沃白板 的时候发现在里面很难输入拼音来做课堂活动。

56220
来自专栏张善友的专栏

ASP.NET AJAX 控件开发基础

在 JavaScript 当前广泛使用的版本中,它缺少 .NET 开发人员所熟悉的几个 OOP 的关键概念,而 ASP.NET AJAX 可以模拟其中的大多数,...

22360
来自专栏大内老A

Enterprise Library Policy Injection Application Block 之四:如何控制CallHandler的执行顺序

一、为什么CallHandler需要进行排序 PIAB为我们提供了一个很好地实现AOP的方式。AOP旨在实现Business Logic和Non-Busines...

195100

扫码关注云+社区

领取腾讯云代金券