第一个Windows应用程序--启动函数、入口点函数与退出函数

1.入口点函数

Windows 应用程序必须有一个入口点函数,应用程序开始运行时,这个函数会被调用。使用Win32 SDK开发程序的入口函数如下:

int WINAPI WinMain(
	HINSTANCE hInstanceExe,
	HINSTANCE,
	PTSTR pszCmdLine,
	int nCmdShow);

1)hInstanceExe参数实际值是一个内存基地址;系统将可执行文件的映像加载到进程地址空间中的这个位置。例如,系统打开可执行文件,并将它的内容加载到地址0x00400000,则(w)WinMain的hInstanceExe参数值为0x00400000.

可执行文件的映像具体加载到哪一个基地址,是由链接器决定的。

2)第二个参数用于16位Windows系统,对32位系统都应传递NULL

3)pszCmdLine 是用来运行程序的命令行。有些Windows程序在启动时用它来把文件装入内存

4)nCmdShow 用来指明程序最初如何显示(正常显示、最大化到全屏、最小化到任务栏)


2.启动函数

操作系统实际上并不调用我们所写的入口点函数。相反,它会调用由C/C++运行库实现并在链接时使用-entry:命令行选项来设置的一个C/C++运行时启动函数。该函数将初始化C/C++运行库,使我们能调用malloc和free之类的函数。它还确保了在我们的代码开始执行之前,我们声明的任何全局和静态C++对象都被正确构造。


入口函数和启动函数:
WinMain -- WinMainCRTStartup
wWinMain --  wWinMainCRTStartup
Main --  mainCRTStartup
Wmain --   wmainCRTStartup

其中开头的w表示Unicode版本。


在链接时,链接器将选择正确的C/C++运行库启动函数。链接器查找代码中包含四个入口函数中的哪一个,并嵌入相应的C/C++启动函数。
启动函数的用途:
1)获取指向新进程的完整命令行的一个指针
2)获取指向新进程的环境变量的一个指针
3)初始化C/C++运行库的全局变量
4)初始化C运行库内存分配函数(malloc和calloc)和其他底层I/O例程使用的堆(heap)
5)调用所有全局和静态C++对象的构造函数
完成所有这些初始化工作之后,C/C++启动函数就会调用应用程序的入口点函数。
例如写了一个_tWinMain函数,且定义了_UNICODE,其调用过程将如下所示:
GetStartupInfo(&StartupInfo);
int nMainRetVal = wWinMain((HINSTANCE)&__ImageBase, NULL, pszCommandLineUnicode, 
	(StartupInfo.dwFlags & STARTF_USESHOWWINDOW) ? StartupInfo.wShowWindow : SW_SHOWDEFAULT);

_ImageBase是一个链接器定义的伪变量,表明可执行文件被映射到应用程序内存中的什么位置。


3.exit函数

入口点函数返回后,启动函数将调用C运行库函数exit,向其传递返回值nMainRetVal。
exit函数执行以下任务:
1)调用_onexit函数调用所注册的任何一个函数
2)调用所有全局和静态C++类对象的析构函数
3)在DEBUG生成中,如果设置了_CRTDUG_LEAK_CHECK_DF标志,就通过调用_CrtDumpMemoryLeak函数来生成内存泄露报告。

4)调用操作系统的ExitProcess函数,向其传入nMainRetVal。这会导致操作系统“杀死”我们的进程,并设置它的退出码。


4.最简单的windows程序代码示例

/*
 * HelloMsg.c -- Displays "Hello, Windows" in a message box
 * guzhoudiaoke@126.com
 * 2012-11-6
 */

#include <Windows.h>

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
{
	MessageBox(NULL, TEXT("Hello Windows!"), TEXT("HelloMsg"), 0);

	return 0;
}

5.运行结果


  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 C/C++ 程序中用 CreateThread 函数创建新线程播放音乐与主线程同时运行的方法如下: 1. 首先你需要包含 Windows 头文件 `Windows.h`。 2. 然后你需要声明一个线程函数,并指定线程函数的类型为 `DWORD WINAPI`。线程函数的参数是一个指向 void 类型的指针,你可以在这个指针所指向的内存中存储一些需要在线程中使用的数据。 3. 然后你可以使用 CreateThread 函数创建一个新线程,并将线程函数的地址作为参数传入。 下面是一个示例代码: ```cpp #include <Windows.h> DWORD WINAPI PlayMusic(LPVOID lpParameter) { // 在这里播放音乐 return 0; } int main() { // 创建新线程 HANDLE hThread = CreateThread(NULL, 0, PlayMusic, NULL, 0, NULL); if (hThread == NULL) { // 创建线程失败 return -1; } // 等待线程结束 WaitForSingleObject(hThread, INFINITE); return 0; } ``` 在这个示例中,我们在主线程中创建了一个新线程,并让新线程执行 PlayMusic 函数,在这个函数中播放音乐。主线程在调用 CreateThread 函数后会继续往下执行,并调用 WaitForSingleObject 函数等待新线程结束。这样主线程和新 ### 回答2: 在C/C++程序中,可以使用`CreateThread`函数来创建新线程来播放音乐,同时保持主线程的运行。下面是一个基本示例: 首先,需要包含Windows.h头文件,然后使用`CreateThread`函数来创建新线程。同时,我们需要在新线程中实现音乐播放的功能。下面是一个示例代码: ```c #include <Windows.h> #include <stdio.h> #include <stdlib.h> DWORD WINAPI PlayMusic(LPVOID lpParam) { // 在此处实现音乐播放的具体逻辑 printf("新线程播放音乐\n"); Sleep(5000); // 假设音乐播放需要5秒钟 // 结束线程 ExitThread(0); } int main() { HANDLE hThread; DWORD threadId; // 创建新线程 hThread = CreateThread(NULL, 0, PlayMusic, NULL, 0, &threadId); if (hThread == NULL) { printf("创建线程失败\n"); return 1; } // 在此处编写主线程的其他逻辑 printf("主线程继续运行\n"); Sleep(2000); // 假设主线程运行需要2秒钟 // 等待新线程结束 WaitForSingleObject(hThread, INFINITE); return 0; } ``` 在上述代码中,`PlayMusic`函数是新线程的入口函数,在该函数内实现了音乐播放的具体逻辑。主线程继续运行,并在某个时刻使用`WaitForSingleObject`函数等待新线程的结束。 需要注意的是,由于C/C++程序是单线程的,必须依赖于Windows提供的多线程机制来实现同时运行多个任务。因此,我们需要使用`CreateThread`函数创建新线程。 此外,为了确保线程安全,需要适当使用同步机制如互斥量(Mutex)等来保护共享资源,以防止多线程访问冲突。在具体的音乐播放逻辑中,可能需要考虑这些方面。 ### 回答3: 使用CreateThread函数创建新线程可以实现在C/C++程序中同时播放音乐和运行主线程。以下是具体步骤: 1. 首先,将音乐播放功能封装在一个函数中,例如"playMusic"。这个函数会负责打开音乐文件、播放音乐以及关闭文件等操作。 2. 在主线程中,使用CreateThread函数创建一个新线程,并传入指向playMusic函数的指针作为参数。例如: ```c++ HANDLE hThread; hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)playMusic, NULL, 0, NULL); ``` 这里,第一个参数为线程安全属性,默认设置为NULL;第二个参数为栈的大小,设置为0表示使用默认大小;第三个参数为线程函数的指针,将playMusic函数的地址强制转换为LPTHREAD_START_ROUTINE类型;第四个参数为传递给线程函数的参数,没有额外参数则设置为NULL;最后两个参数为线程的创建选项和线程id,设置为NULL。 3. 然后,主线程可以继续执行其他任务,不受音乐播放的影响。 4. 为了保证主线程不会在音乐播放结束之前退出,可以在主线程中调用WaitForSingleObject函数等待新线程的结束。 ```c++ WaitForSingleObject(hThread, INFINITE); ``` 这里的hThread为新线程的句柄,INFINITE表示等待无限长时间,直到新线程结束。 通过以上步骤,就可以实现在C/C++程序中使用CreateThread函数创建新线程并同时播放音乐和运行主线程。新线程会负责音乐播放,而主线程可以继续执行其他任务,直到音乐播放结束。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值