winmain()函数是的参数是由谁传给它的?

myjsy 2009-09-21 09:41:03
winmain()函数是的参数是由谁传给它的?
winmain()的第一个参数就是 hinstance,是一个实例句柄,
这个参数是谁传给它的呢?

一般我们调用一个函数时,必须将实参传给它,但是程序执行时,会首先执行winmain()函数,但是参数是谁传给它的呢?

第三个参数:lpcmdline,这个我还能理解,因为调用应用程序时,这个参数本身就是一个字符串。
比如:
prog.exe a1.txt
则参数就是 "a1.txt",可以传给 winmain()函数。

但是应用程序的实例句柄,是如何传给winmain()的呢?
...全文
353 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
Icic 2009-09-22
  • 打赏
  • 举报
回复
第一个参数的hinstance,其实就是这个WinMain自己所在exe的句柄
这个参数一直有效,你可以直接用来加载本exe的资源(bmp、icon等)
这个参数应该是操作系统自动调度的,无需你的干预

hPrevInstance已经基本作废了

第三个参数是命令行,和main(int argc,char*argv[])不一样的是:该命令行不再包含exe的路径信息

最后一个参数是主窗口的显示方式,是由调用者设定的
weiym 2009-09-22
  • 打赏
  • 举报
回复
可以自己去看C运行时库的源代码
#ifdef WPRFLAG
int wWinMainCRTStartup(
#else /* WPRFLAG */
int WinMainCRTStartup(
#endif /* WPRFLAG */

#else /* _WINMAIN_ */

#ifdef WPRFLAG
int wmainCRTStartup(
#else /* WPRFLAG */
int mainCRTStartup(
#endif /* WPRFLAG */

#endif /* _WINMAIN_ */

void
)

{
int initret;
int mainret;
OSVERSIONINFOA *posvi;
int managedapp;
#ifdef _WINMAIN_
_TUCHAR *lpszCommandLine;
STARTUPINFO StartupInfo;
#endif /* _WINMAIN_ */
/*
* Dynamically allocate the OSVERSIONINFOA buffer, so we avoid
* triggering the /GS buffer overrun detection. That can't be
* used here, since the guard cookie isn't available until we
* initialize it from here!
*/
posvi = (OSVERSIONINFOA *)_alloca(sizeof(OSVERSIONINFOA));

/*
* Get the full Win32 version
*/
posvi->dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
(void)GetVersionExA(posvi);

_osplatform = posvi->dwPlatformId;
_winmajor = posvi->dwMajorVersion;
_winminor = posvi->dwMinorVersion;

/*
* The somewhat bizarre calculations of _osver and _winver are
* required for backward compatibility (used to use GetVersion)
*/
_osver = (posvi->dwBuildNumber) & 0x07fff;
if ( _osplatform != VER_PLATFORM_WIN32_NT )
_osver |= 0x08000;
_winver = (_winmajor << 8) + _winminor;

/*
* Determine if this is a managed application
*/
managedapp = check_managed_app();

#ifdef _MT
if ( !_heap_init(1) ) /* initialize heap */
#else /* _MT */
if ( !_heap_init(0) ) /* initialize heap */
#endif /* _MT */
fast_error_exit(_RT_HEAPINIT); /* write message and die */

#ifdef _MT
if( !_mtinit() ) /* initialize multi-thread */
fast_error_exit(_RT_THREAD); /* write message and die */
#endif /* _MT */

/*
* Initialize the Runtime Checks stuff
*/
#ifdef _RTC
_RTC_Initialize();
#endif /* _RTC */
/*
* Guard the remainder of the initialization code and the call
* to user's main, or WinMain, function in a __try/__except
* statement.
*/

__try {

if ( _ioinit() < 0 ) /* initialize lowio */
_amsg_exit(_RT_LOWIOINIT);

#ifdef WPRFLAG
/* get wide cmd line info */
_wcmdln = (wchar_t *)__crtGetCommandLineW();

/* get wide environ info */
_wenvptr = (wchar_t *)__crtGetEnvironmentStringsW();

if ( _wsetargv() < 0 )
_amsg_exit(_RT_SPACEARG);
if ( _wsetenvp() < 0 )
_amsg_exit(_RT_SPACEENV);
#else /* WPRFLAG */
/* get cmd line info */
_acmdln = (char *)GetCommandLineA();

/* get environ info */
_aenvptr = (char *)__crtGetEnvironmentStringsA();

if ( _setargv() < 0 )
_amsg_exit(_RT_SPACEARG);
if ( _setenvp() < 0 )
_amsg_exit(_RT_SPACEENV);
#endif /* WPRFLAG */

initret = _cinit(TRUE); /* do C data initialize */
if (initret != 0)
_amsg_exit(initret);

#ifdef _WINMAIN_

StartupInfo.dwFlags = 0;
GetStartupInfo( &StartupInfo );

#ifdef WPRFLAG
lpszCommandLine = _wwincmdln();
mainret = wWinMain(
#else /* WPRFLAG */
lpszCommandLine = _wincmdln();
mainret = WinMain(
#endif /* WPRFLAG */
GetModuleHandleA(NULL),
NULL,
lpszCommandLine,
StartupInfo.dwFlags & STARTF_USESHOWWINDOW
? StartupInfo.wShowWindow
: SW_SHOWDEFAULT
);
#else /* _WINMAIN_ */

#ifdef WPRFLAG
__winitenv = _wenviron;
mainret = wmain(__argc, __wargv, _wenviron);
#else /* WPRFLAG */
__initenv = _environ;
mainret = main(__argc, __argv, _environ);
#endif /* WPRFLAG */

#endif /* _WINMAIN_ */

if ( !managedapp )
exit(mainret);

_cexit();

}
__except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
{
/*
* Should never reach here
*/

mainret = GetExceptionCode();

if ( !managedapp )
_exit(mainret);

_c_exit();

} /* end of try - except */

return mainret;
}
jasonnbfan 2009-09-22
  • 打赏
  • 举报
回复
main()的参数是入口函数调用的。

但是应用程序的实例句柄,是如何传给winmain()的呢?
使用GetModuleHandle(NULL);得到应用程序句柄,传递给main.


入口函数简单例子。
int WINAPI main()
{
HINSTANCE hInstance = GetModuleHandle(NULL);//得到当前进程的句柄,和汇编一样
LPSTR lpszCmdLine = GetCommandLine(); //获得命令行参数
int r = WinMain(hInstance, NULL, lpszCmdLine, SW_SHOWDEFAULT);//调用WinMain函数,就开始执行
ExitProcess(r); //最后结束进程
return r; // this will never be reached.
}
需要在link.exe 后加/entry:main /nodefaultlib:msvcrt90.lib参数,/entry指定入口点函数, /nodefaultlib指定不连接运行时库。

没有初始化堆,堆不能用。


ZangXT 2009-09-22
  • 打赏
  • 举报
回复
推荐一本书吧
《程序员的自我修养-链接、装载和库》
ZangXT 2009-09-22
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 zenny_chen 的回复:]
呵呵。楼主可以用命令行的方式执行你写的程序就明白了。

[/Quote]
这怎么可能呢?
不去分析程序的链接和os加载程序的过程,用多少命令行也解决不了问题。
myjsy 2009-09-22
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 aeris 的回复:]
由C/C++的运行时库传递的
[/Quote]
能说说吗?
zenny_chen 2009-09-22
  • 打赏
  • 举报
回复
呵呵。楼主可以用命令行的方式执行你写的程序就明白了。
Aeris 2009-09-22
  • 打赏
  • 举报
回复
由C/C++的运行时库传递的
信念 2009-09-21
  • 打赏
  • 举报
回复
推荐你看看windows核心编程
arong1234 2009-09-21
  • 打赏
  • 举报
回复
实际上hInstance, hPrevInstance已经没有作用了,这只在很早的windows版本中才有用
yashuwa0622 2009-09-21
  • 打赏
  • 举报
回复
如果做过单片机汇编的话,你应该知道上电启动的过程,当系统完成初始化后,会跳转至应用程序入口地址(比如main),我相信操作系统也是如此,运行一个应用程序后,系统会做一些初始化的工作,然后会跳转至一个入口地址(这里是winmain),必要的时候,会进行参数传递
zgjxwl 2009-09-21
  • 打赏
  • 举报
回复
在视图--》调试窗口--》调用堆栈那里。
zgjxwl 2009-09-21
  • 打赏
  • 举报
回复
调试程序的时候。。。直接调用堆栈就可以看到 了。。。
晨星 2009-09-21
  • 打赏
  • 举报
回复
比如有一种实现是系统启动一个进程的时候,把命令行参数塞在栈的底部。然后把相关的地址和数据组织好传给main的argc和argv。
晨星 2009-09-21
  • 打赏
  • 举报
回复
只需要知道是操作系统传递的就OK了。
「已注销」 2009-09-21
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 demon__hunter 的回复:]
一般可以说是操作系统传递的,在具体一点是os调用c/c++运行库的启动函数,然后c/c++启动函数调用winmain和main函数,从而向winmain或main函数传递参数的。
[/Quote]
还有main吗?
没有。
其实WinMain也不是WinMain,main也不是main。
kouwenlong 2009-09-21
  • 打赏
  • 举报
回复
这个问题问得好.
机智的呆呆 2009-09-21
  • 打赏
  • 举报
回复
一般可以说是操作系统传递的,在具体一点是os调用c/c++运行库的启动函数,然后c/c++启动函数调用winmain和main函数,从而向winmain或main函数传递参数的。
myjsy 2009-09-21
  • 打赏
  • 举报
回复
up

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧