在Windows应用程序中,我们可以认为 WinMain() 函数是程序的入口,WinMain()的原型如下:

int WINAPI WinMain( 

    HINSTANCE hInstance, 

    HINSTANCE hPreInstance, 

    LPSTR lpCmdLine, 

    int nCmdShow 

); 

代码解释:

1、前面说过,资源存在于内存之后,那么一个每个程序运行之后,也被看做一个资源,它有一个属于自己的句柄,这个句柄就保存在变量 hInstance 中。

2、hPreInstance 表示当前实例的前一个实例的句柄,在Win32环境下,参数总是为NULL

3、lpCmdLine 用于存放传递给应用程序的参数,那么如何给应用程序传递参数?这里举几个例子:

  1. 通过命令行传递参数:在命令行下输入 notepad hi.txt,这里hi.txt这个文件的路径(一个字符串)这个参数被传递给应用程序 notepad

  2. 通过双击鼠标的操作:我们现在有一个 hi.txt 文档,我们在上面双击,那么hi.txt这个文件的路径将作为参数传递给 notepad,也就是说,双击操作可以把文件名作为参数传递给指定的Windows应用程序
  3. 拖拽操作:我们可以把一个叫 hi.txt 的文档,拖拽到 notepad 的程序中,那么hi.txt这个文件的路径将作为参数传递给 notepad,也就是说,拖拽操作可以把文件名作为参数传递给指定的Windows应用程序

我们可以建立一个程序,读取参数:

1) 建立头文件 StdAfx.h

#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_ #if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include <windows.h>

2) 建立test.cpp 文件

#include "stdafx.h" 

int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MessageBox(NULL,lpCmdLine,"CmdLine",0);
return 0;
}

当我们拖拽一个文件到生成的程序的时候(双击选择使用此程序打开也一样),出现:

4、nCmdShow,指定窗口第一次出现(程序刚刚启动时)时的显示方式。显示方式有多种,比如:

  1. 不显示,nCmdShow = 0;

  2. 正常显示,nCmdShow = 1;(默认为1)
  3. 最小化显示,nCmdShow = 2;
  4. 最大化显示,nCmdShow = 3;

如果需要改变系统的默认的显示方式,需要在创建窗口之前指定nCmdShow的值(通过一个简单的赋值语句nCmdShow = n)

不过,其实这里要让nCmdShow起作用,需要把nCmdShow作为参数传递给ShowWindow函数

另外,这里稍微说明一下 WINAPI 这个宏定义,我们看WinMain函数的原型:

int WINAPI WinMain(

HINSTANCE hInstance,

HINSTANCE hPreInstance,

LPSTR         lpCmdLine,

int              nCmdShow

);

WINAPI是这样定义的:
#define WINAPI      __stdcall

在VC6.0下生成的WinMain函数,实际上是:

int APIENTRY WinMain(

HINSTANCE hInstance,

HINSTANCE hPreInstance,

LPSTR         lpCmdLine,

int              nCmdShow

);

APIENTRY 这个定义为:

#define APIENTRY    WINAPI

所以归根到底都是 __stdcall,这个是什么东西了?这里解释一下:

__stdcall一种调用约定(调用函数时候的一种约定),其他的调用约定有:

__cdecl 和 __fastcall

调用约定将决定以下内容:

1)函数参数的压栈顺序,

2)由调用者还是被调用者把参数弹出栈,

3)以及产生函数修饰名的方法。

WIN32API使用的是__stdcall调用约定

标准C,C++使用的是__cdecl调用约定

__stdcall调用约定:函数的参数自右向左压栈,被调用的函数在返回前清理传送参数的内存栈

__cdecl调用约定:每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。注意:对于可变参数的成员函数,始终使用__cdecl的调用约定

(有关内容参考来源:http://blog.chinaunix.net/u/22878/showart_231924.html)

(附录:系统理解Win32 API和MFC(上) -> http://www.vckbase.com/document/viewdoc/?id=487)

(附录:系统理解Win32 API和MFC(下) -> http://www.vckbase.com/document/viewdoc/?id=488)

WinMain函数详解(转载再编辑)的更多相关文章

  1. WinMain函数详解(转载)

    略加增添与修改! 工具:VC++6.0       系统:win7 64位 在Windows应用程序中,我们可以认为 WinMain() 函数是程序的入口,WinMain()的原型如下: int WI ...

  2. malloc 与 free函数详解<转载>

    malloc和free函数详解   本文介绍malloc和free函数的内容. 在C中,对内存的管理是相当重要.下面开始介绍这两个函数: 一.malloc()和free()的基本概念以及基本用法: 1 ...

  3. kzalloc 函数详解(转载)

    用kzalloc申请内存的时候, 效果等同于先是用 kmalloc() 申请空间 , 然后用 memset() 来初始化 ,所有申请的元素都被初始化为 0. view plain /** * kzal ...

  4. Linux中fork()函数详解(转载)

    [原创地址]http://blog.csdn.net/jason314/article/details/5640969 [转载地址]http://www.cnblogs.com/bastard/arc ...

  5. Interlocked.Increment()函数详解 (转载)

    原文地址 class Program { static object lockObj = new object(); ; ; //假设要处理的数据源 , ).ToList(); static void ...

  6. Linux中fork()函数详解(转载)

    linux中fork()函数详解 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事, ...

  7. 【转载】jQuery.extend 函数详解

    转载自:http://www.cnblogs.com/RascallySnake/archive/2010/05/07/1729563.html jQuery.extend 函数详解 JQuery的e ...

  8. 【转载】3D/2D中的D3DXMatrixPerspectiveFovLH和D3DXMatrixOrthoLH投影函数详解

    原文:3D/2D中的D3DXMatrixPerspectiveFovLH和D3DXMatrixOrthoLH投影函数详解 3D中z值会影响屏幕坐标系到世界坐标系之间的转换,2D中Z值不会产生影响(而只 ...

  9. 【转载】C语言itoa()函数和atoi()函数详解(整数转字符C实现)

    本文转自: C语言itoa()函数和atoi()函数详解(整数转字符C实现) 介绍 C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串. int/float to ...

随机推荐

  1. 分形之列维(levy)曲线

    莱维C形曲线(Lévy C curve)是个自我相似的分形,最先由保罗·皮埃尔·莱维在1938年的论文Plane or Space Curves and Surfaces Consisting of ...

  2. ipad协议

    getLoginQRCode (获取登录二维码)CheckLoginQRCode(检测扫码状态)ManualAuth(扫码登录)ManualAuth(62数据登录)ManualAuth(账号密码登录) ...

  3. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

  4. OCP考试062题库出现大量新题-18

    choose two Examine this command executed on a client that is remote from the database server. SQL> ...

  5. [NOIP2018]赛道修建(二分+multiset)

    考场上打了一个 \(vector\) 解法,因为我当时不会 \(multiset\) 好吧,我来讲一讲今年的 \(tgD1T3\) 首先,这题 \(55\) 分是不难想的 1. \(b_i=a_i+1 ...

  6. 07_python_集合深浅拷贝

    一.join li = ["李嘉诚", "麻花藤", "林海峰", "刘嘉玲"] s = "_".j ...

  7. C#6.0语言规范(六) 转换

    转换能够被视为是一个特定类型的表达式.转换可能会导致给定类型的表达式被视为具有不同的类型,或者它可能导致没有类型的表达式获取类型.转换可以是隐式或显式的,这决定了是否需要显式转换.例如,从类型int到 ...

  8. python------virtualenv&virtualenvwrapper的使用

    virtualenv virtualenv 的作用:为单个项目创建独立的python虚拟环境 virtualenv的使用 : 1.通过如下命令安装virtualenv $ sudo pip insta ...

  9. 关于axios及其在vue中的配置

    什么是axios?官方解释:axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中. 具有以下特点: 从浏览器中创建 XMLHttpRequests 从 nod ...

  10. centos7 初始化脚本

    #!/bin/bash # 时间: 2018-11-21 # 作者: HuYuan # 描述: CentOS 7 初始化脚本 # 加载配置文件 if [ -n "${1}" ];t ...