Back

/ 4 min read

Windows SDK 01笔记

Windows桌面程序

通过空项目创建

image-20240705162749414
  • WINAPI,一个调用约定宏

    image-20240705162540949
  • TEXT是,Windows SDK中的兼容字符集宏,等价于_T(xxx)宏。

  • WinMain是窗口程序的入口函数,等价于C标准中的int main()函数。

WinMain的函数签名

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
  • __stdcall调用约定,被调用者清理堆栈、参数入栈顺序从右至左。
  • WinMain函数名,Win32窗口程序调用规范定义。
  • HINSTANCEHandel Instance句柄实例,窗口句柄对象。
  • hInstance是 实例的句柄*或模块的句柄。 当可执行文件加载到内存中时,操作系统使用此值来标识可执行文件或 EXE。 某些 Windows 函数需要实例句柄,例如加载图标或位图。
    • 在程序中,关闭随机基址后,hInstance的值,统一为0x00400000,表示程序内存的首地址。image-20240705163746082
  • hPrevInstance没有任何意义。 它在 16 位 Windows 中使用,但现在始终为零。
  • pCmdLine以 Unicode 字符串的形式包含命令行参数。
  • nCmdShow是一个标志,指示主应用程序窗口是最小化、最大化还是正常显示。

关于pCmdLine参数

​ 通过配置调试环境中的参数,可以观察到参数字符串是如何存在的。

image-20240705164218529 image-20240705164246464

关于nCmdShow参数

​ 根据Stack OverFlow中的回答:

The value of the nCmdShow parameter will be one of the constants specified in ShowWindow’s API reference. It can be set by another process or system launching your application via CreateProcess. The STARTUPINFO struct that can optionally be passed to CreateProcess contains a wShowWindow member variable that will get passed to WinMain through the nCmdShow parameter.
nCmdShow 参数的值将是 ShowWindow 的 API 参考中指定的常量之一。它可以由通过 CreateProcess 启动您的应用程序的另一个进程或系统来设置。可以选择传递给 CreateProcessSTARTUPINFO 结构包含一个 wShowWindow 成员变量,该变量将通过 nCmdShow 参数。

  • 此参数通过CreateProcess创建时,进行传参。

作业

不使用头文件,创建弹窗

#pragma comment(lib, "user32.lib")
#define WINAPI __stdcall
#define HWND void*
#define LPCWSTR const wchar_t*
#define UINT unsigned int
#define MB_OK 0x00000000L
#define NULL 0
// 导入MessageBox函数的地址
extern "C" __declspec(dllimport) int __stdcall MessageBoxW(void* hWnd, const wchar_t* lpText, const wchar_t* lpCaption, unsigned int uType);
//int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
//{
// MessageBox(NULL, TEXT("Hello World!"), TEXT("Hello World!"), MB_OK);
// return 0;
//}
int main() {
MessageBoxW(NULL, L"Hello World!", L"Hello World!", MB_OK);
return 0;
}

​ 主要思路是通过,让程序静态加载user32.dll动态运行库,将MessageBoxW函数链接到程序中,进行手工调用。类似的方法也可以动态加载DLL文件,获取函数地址,通过函数指针调用的方式。此处不赘叙。