天上飞来一只 发表于 2020-10-22 15:27

不包含windows.h和window.h内的任何头文件,弹框 “Hello, world!”

本帖最后由 天上飞来一只 于 2020-10-22 15:36 编辑

前言:在windows应用程序下,不包含windows.h和window.h内的任何头文件,弹框 “Hello, world!”,本文主要基于 vs2015 生成的windows应用程序的空工程进行研究,以提高对基础知识的理解。


一、VS基础配置1.打开VS2015,新建项目----win32控制台应用程序----windows应用程序,附加选项,空项目



二、windows应用程序的主入口函数wWinMain写任何一个函数应该有一个该函数的入口了。我们知道控制台的入口函数是main()函数,那么在写Windows应用程序也是main()吗?
回答当然不是了。我们用的是SDK中的WinMain()函数参考MSDN的说明
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
);
Requirements
Windows NT/2000/XP: Included in Windows NT 3.1 and later.
         Windows 95/98/Me: Included in Windows 95 and later.
            Header: Declared in Winbase.h; include Windows.h.
MSDN上已经说明需要包含 Winbase.h或者Windows.h. 那我们需要的挑战就是不使用任何头文件,也能正常弹出提示框MessageBox



三、具体流程1、先写主函数内的内容int APIENTRY WinMain(_In_ HINSTANCE hInstance,      _In_opt_ HINSTANCE hPrevInstance,      _In_ LPWSTR    lpCmdLine,      _In_ int       nCmdShow){      //MessageBox(NULL, TEXT("hello world"), TEXT("标题"), MB_OK);      return 0;}2、如果直接选择编译以上问题,相信大家看VS提示输出窗口是一大堆,莫名其妙的错误提示 这么多语法错误、未声明的标识符 为啥???现在我会一点一点的挽回那失去的耐心!优先解决掉未声明的标识符

3、解决提示“_In_”: 未声明的标识符的问题   

    _in 输入参数    _out 输出参数
    _opt 参数是可选的,就是可以为NULL
    _ecount 所指向的缓存的元素个素 也就是括号里的数字
    这些宏都被定义为空,只是让程序更容易理解!
解放方法:

宏定义

#define _In_

#define _In_opt_


4、C语言语法基础知识:在使用函数之前应该先声明,那么WinMain函数,同样也需要声明,OK,加上
//宏定义
#define _In_
#define _In_opt_

//函数声明
int APIENTRY WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
      _In_ LPWSTR lpCmdLine, _In_ int nShowCmd);

//入口函数
int APIENTRY WinMain(_In_ HINSTANCE hInstance,
      _In_opt_ HINSTANCE hPrevInstance,
      _In_ LPWSTR    lpCmdLine,
      _In_ int       nCmdShow)
{
      //MessageBox(NULL, TEXT("hello world"), TEXT("标题"), MB_OK);
      return 0;
}
5、继续F7编译,还是提示很多报错,不要放弃,继续解决错误


大家可以新的提示“HINSTANCE”: 未声明的标识符,依次解决掉WinMain函数的所有类型

解决方法:

HINSTANCE是“句柄型”数据类型HWND 是一个基本类型,一般指窗口句柄
LPSTR一种字符串数据类型
LPCSTR一种常量字符串数据类型
LPWSTR是wchar_t字符串数据类型
LPCWSTR 是常量wchar_t字符串数据类型

UINT是无符号整型数据类型

依次自定义类型
typedef void *HINSTANCE;
typedef void *HWND;
typedef char *LPSTR;
typedef const char *LPCSTR;
typedef wchar_t *LPWSTR;
typedef const wchar_t *LPCWSTR;
typedef unsigned int UINT;

6、继续F7编译,提示报错


看到这么多错误,还能坚持下来的同学,是最棒的! 可以看到提示“WinMain”: 必须是“__stdcall”

解决:
__stdcall是函数调用约定的一种,函数调用约定主要约束了两件事:1.参数传递顺序2.调用堆栈由谁(调用函数或被调用函数)清理

那么可以得出APIENTRY就是表示__stdcall,定义#define APIENTRY __stdcall
//宏定义
#define _In_
#define _In_opt_
#define APIENTRY __stdcall
//自定义数据类型
typedef void *HINSTANCE;
typedef void *HWND;
typedef char *LPSTR;
typedef const char *LPCSTR;
typedef wchar_t *LPWSTR;
typedef const wchar_t *LPCWSTR;
typedef unsigned int UINT;
//函数声明
int APIENTRY WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
      _In_ LPWSTR lpCmdLine, _In_ int nShowCmd);
//函数入口
int APIENTRY WinMain(_In_ HINSTANCE hInstance,
      _In_opt_ HINSTANCE hPrevInstance,
      _In_ LPWSTR    lpCmdLine,
      _In_ int       nCmdShow)
{
      //MessageBox(NULL, TEXT("hello world"), TEXT("标题"), MB_OK);
      return 0;
}

7、添加代码继续编译F7,无错误


8、终于到了MessageBox阶段,取消注释,编译F7等待报错。

MessageBox找不到标识符,MessageBox是函数,同样也需要声明,这里需要注意MessageBox实际分为2个版本:
int WINAPI MessageBoxA(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType);
int WINAPI MessageBoxW(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText, _In_opt_ LPCWSTR lpCaption, _In_ UINT uType);
需要进行宏定义
#ifdef UNICODE
#define MessageBoxMessageBoxW
#else
#define MessageBoxMessageBoxA
#endif
解决:NULL TEXT,MB_OK未知标识符,宏定义走起
#define __TEXT(quote) L##quote   
#define TEXT(quote) __TEXT(quote)   
#define MB_OK   0x00000000L
#defineNULL 0

#define WINAPI __stdcall

9、编译,报错

解决:
小知识点,MessageBoxA很古老,为了能够正确实现C++代码调用其他C语言代码,在MessageBoxA和MessageBoxW上必须声明C,即extern "C"

10、完整代码,求爱心!   

JuncoJet 发表于 2020-10-22 16:46

你这强迫症要治,用goasm吧

qbnw 发表于 2020-10-22 17:21

这么做的目的是为了清洁代码吗?

chen4321 发表于 2020-10-22 17:28

表情包不错,收下了,技术也学到了

痴情总被无情伤 发表于 2021-2-24 23:46

你这是把弹窗要用到的头文件的内容都搬出来了啊{:1_908:}

wCoding 发表于 2021-2-26 08:38

随着功能的增加,就全搬过来了。

AA_BB_2AB 发表于 2021-4-2 15:23

谢谢,祝您身体健康!
页: [1]
查看完整版本: 不包含windows.h和window.h内的任何头文件,弹框 “Hello, world!”