Windows编程-001

article/2025/9/1 14:43:09

  • 如果建立的是Win32控制台工程(入口函数是main函数)的话,WinMain函数不能作为入口函数,如果想要解决这个问题的话,可以打开项目属性->链接器->系统->子系统,把子系统对应的“控制台”改为“窗口”。

  • 名词释义:

  • API:应用程序编程接口(Aplication Programma Interface),是一组定义、程序及协议的集合是一些预先定义的接口(如函数、HTTP接口),或指软件系统不同组成部分衔接的约定。

  • SDK:软件开发包(Software Development Kit),SDK是一些被软件工程师用于为特定的软件包、软件框架、硬件平台、操作系统等创建应用软件的开发工具的集合。它可以简单的为某个程序设计语言提供应用程序接口API的一些文件,但也可能包括能与某种嵌入式系统通讯的复杂的硬件。SDK还经常包括示例代码、支持性的技术注解或者其他的为基本参考资料澄清疑点的支持文档。

  • 窗口:包含标题栏、菜单栏、系统菜单、最下化框,最大化框,滚动等,窗口主要分为客户区和非客户区;

  • 句柄:是一个标识符,是用来标识对象或者项目的。从数据类型上来看它只是一个16位的无符号整数。应用程序几乎总是通过调用一个Windows函数来获得一个句柄,之后其他的Windows函数就可以使用该句柄,以引用相应的对象。在 Windows编程中会用到大量的句柄。在 Windows程序中并不是用物理地址来标识一个内存块、文件、任务或动态装入模块的。相反地,Windows API给这些项目分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。

  • 窗口程序的入口函数:WinMain 控制台窗口应用程序入口函数:main

  • WINAPI:本质是__stdcall,(stdcall调用方式又被称作Pascal调用方式)是C/C++调用约定的一种,意思是函数的参数从右到左推送到栈上,被调用函数在返回之前从堆栈中弹出这些参数;

WINAPI可以看做是函数调用约定,约定了:

  1. 函数的入栈方式——从右往左

  1. 函数调用后,由谁来将堆栈恢复原状

  • WINAPICALLBACKAPIENTRY:从右往左入栈,本质都是__stdcall(标准调用方式);

WINAPIV:从右往左入栈,本质是__cdecel;

//转到定义,可以看到:
#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
  • C++函数调用的几种方式:

  1. stdcall

stdcall调用方式的函数声明为:int __stdcall function(int a,intb);

stdcall的调用方式意味着:

  1. 参数从右往左依次压入堆栈;

  1. 由被调用函数自己来恢复堆栈;

  1. 函数名自动加前导下划线,后面紧跟着一个@,其后紧跟着参数的尺寸。

上面函数翻译成汇编语言将变成:

push b先压入第二个参数

push a再压入第一个参数

call function调用函数

在编译时,此函数的名字翻译成_function@8

  1. cdecl

cdecl调用函数又称为C调用方式,是C语言缺省的调用方式,它的语法为:

int function(int a,int b)//不加修饰符就是C调用方式

int __cdecl function(int a,int b)//明确指定C调用方式

cdecel调用方式决定了:

  1. 参数从右向左依次压入堆栈;

  1. 由调用者恢复堆栈;

  1. 函数名自动加前导下划线。

由于是由调用者来恢复堆栈,因此C调用方式允许函数的参数个数是不固定的,这是C语言的一大特色。

此函数被翻译为:

push b //先压入第二个参数

push a //再压入第一个参数

call function // 调用函数

add esp, 8 //清理堆栈(此内容在汇编中esp寄存器的功能部分有讲)

在编译时,此方式的函数被翻译成:__function

  • 主函数参数:

  • HINSTANCE:应用程序实例句柄类型;

//转到定义,看到本质为结构体指针:
DECLARE_HANDLE(HINSTANCE);
#define DECLARE_HANDLE(HINSTANCE)
struct HINSTANCE__
{
int unused;
};
typedef struct HINSTANCE__* HINSTANCE
  • hInstance :当前应用程序实例句柄;

  • hPreInstance:当前程序的前一个实例句柄,在32和64位机器上已废弃,现在不再使用,值为NULL,在16位机器上使用(任何一个基于GDI的Windows程序以WinMain函数作为入口被系统调用,在Win16中,hPreInstance指向程序的前一个实例句柄,但在Win32中,每一个进程都有一个独立的4G地址空间,从0到2G属于进程私有,对其他进程来说是不可见的。所以在Win32中,hPreInstance总是为NULL);

  • LPSTR:long point string;

typedef CHAR *NPSTR, *LPSTR, PSTR;
//上式表示 CHAR <=> NPSTR <=> LPSTR <=> PSTR
typedef char CHAR;
//LPSTR <=> char*
//LPCSTR <=> const char*
  • lpCmdLine:[in] Pointer to a null-terminated string specifying the command line for the application, excluding the program name. To retrieve the entire command line, use the GetCommandLine function.(指向一个应用程序命令中,除了程序名的null字符结束的字符串。GetCommandLine函数可以返回整个命令行)

lpCmdLine是一个以空终止的字符串,指定传递给应用程序的命令行参数。

  • nCmdShow:窗口显示方式(最大化,最小化,普通,正常显示);

  • MessageBox:Windows编程中经常用到的一个API,作用是弹出一个消息提示框;

int WINAPI MessageBox (
In_opt HWND hWnd,
In_opt LPCTSTR lpText,      //要在消息框中显示的文本
In_opt LPCTSTR lpCaption,   //对话框标题。如果为 NULL(默认值),则使用标题“错误”
In UINT uType       //指定对话框的内容和行为。有关可用不同消息框的列表,请参阅 Windows SDK 文档中的消息框条目。默认值提供一个简单的“确定”按钮。
);

第一个参数:

HWND : 窗口句柄类型(可以理解为窗口的ID)

hWnd : 父窗口句柄,如果没有父窗口,就写NULL

HWND 本质为结构体指针

/*   HWND : 窗口句柄类型(可以理解为窗口的ID)hWnd : 父窗口句柄,如果没有父窗口,就写NULLHWND 本质为结构体指针                  */
DECLARE_HANDLE (HWND);
#define DECLARE_HANDLE(name) 
struct HWND__
{int unused;
};     typedef struct HWND__ *HWND
/*LPCTSTR:显示内容*/
//LPCTSTR在Unicode编码下
typedef LPCWSTR PCTSTR, LPCTSTR;          //LPCWSTR <=> PCTSTR <=> LPCTSTR
typedef  CONST WCHAR *LPCWSTR, *PCWSTR;   //CONST WCHAR* <=> LPCWSTR <=> PCWSTR
#define CONST               const         //CONST <=> const
typedef wchar_t WCHAR;                    //wchar_t <=> WCHAR//const wchar_t* <=>  LPCTSTR
//上述内容:LPCTSTR <=> const wchar_t*
/*LPSTR在多字节字符集情况下*/
typedef LPCTSTR PCTSTR, LPCTSTR;           //LPCTSTR  <=> PCTSTR <=> LPCTSTR
typedef  CONST CHAR *LPCWSTR, *PCWSTR;     //CONST CHAR* <=> LPCTSTR <=> PCWSTR
#define CONST const                        //CONST <=> const
typedef char CHAR;                         //char <=> CHAR
//上述内容:LPSTR <=> const char*
  • 实操

1.Hello World!

#include <Windows.h>int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine , int nCmdShow)
{int n = MessageBox(NULL, L"Hello World!", L"温馨提示", MB_OK);if (n == IDOK){MessageBox(NULL, L"点了OK", L"提示", MB_OK);}else if (n == IDNO){MessageBox(NULL, L"点了No", L"提示", MB_OK);}else if (n == IDYES){MessageBox(NULL, L"点了Yes", L"提示", MB_OK);}return 0;
}

2.FirstWindow

  • 流程:①设计窗口;②注册窗口;③创建窗口;④显示窗口;⑤更新窗口;⑥消息循环。

  • 图标制作软件:icoFX3-v3.8.1链接:https://u9baoku.lanzoui.com/b01olvqxc 密码:8udj

  • 窗口处理函数:

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
//typedef LONG_PTR            LRESULT;/*virtual LRESULT WindowProc(UINT message,        //message:指定要处理的Windows消息WPARAM wParam,       //wParam:提供用于处理的其他信息。参数值取决于消息LPARAM lParam        //lParam:提供用于处理消息的其他信息。参数值取决于消息
);
*/
  • 源代码

#include <Windows.h>
#include "resource.h"//LRESULT:
//typedef LONG_PTR            LRESULT;   long//第一个参数:窗口句柄
//当前窗口的窗口句柄//第二个参数:消息编号   unsigned int//第三个参数:WPARAM     unsigned int
//窗口附加信息//第四个参数:LPARAM     long
//窗口附加信息//窗口处理函数
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine, int nCmdShow)
{/*typedef struct tagWNDCLASSW {UINT        style;WNDPROC     lpfnWndProc;int         cbClsExtra;int         cbWndExtra;HINSTANCE   hInstance;HICON       hIcon;HCURSOR     hCursor;HBRUSH      hbrBackground;LPCWSTR     lpszMenuName;LPCWSTR     lpszClassName;
} WNDCLASSW, *PWNDCLASSW, NEAR *NPWNDCLASSW, FAR *LPWNDCLASSW;
#ifdef UNICODE
typedef WNDCLASSW WNDCLASS;UINT*///UINT    //typedef unsigned int        UINT;//一、设计窗口类wchar_t szAppClassName[] = L"My_GUI";wchar_t szWindowName[] = L"这是我的第一个Windows程序";//LoadIcon//加载一个图标文件//第一个参数:应用程序实例句柄//如果是系统资源,传递NULL//如果是自定义资源,传递hInstance//第二个参数:资源ID//LoadCursor//加载一个光标文件//第一个参数:应用程序实例句柄//如果是系统资源,传递NULL//如果是自定义资源,传递hInstance//第二个参数:资源IDWNDCLASS wc;wc.style = CS_HREDRAW | CS_VREDRAW;            //窗口类的风格wc.lpfnWndProc = WindowProc;                //窗口处理函数wc.cbClsExtra = 0;                            //窗口类的额外扩展空间大小(字节)wc.cbWndExtra = 0;                            //窗口的额外扩展空间大小(字节)wc.hInstance = hInstance;                    //当前应用程序实例句柄wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LOGO));                            //窗口图标句柄,NULL:没有图标wc.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CURSOR));                            //光标图标句柄wc.hbrBackground = CreateSolidBrush(RGB(255,255,255)); //背景画刷句柄, 0-》255,0:最暗;255:表示最亮  白色:RGB(255,255,255)  红色:RGB(255,0,0)wc.lpszMenuName = NULL;                        //菜单名wc.lpszClassName = szAppClassName;            //窗口类型名//二、注册窗口类//ATOM <= > WORD  <=> unsigned short //DWORD  double WORD   //DWORD  <=> unsigned longif (0 == RegisterClass(&wc)){MessageBox(NULL, L"此程序不能运行在Windows NT上", L"温馨提示", MB_OK);return 0;}//三、创建窗口HWND hWnd = CreateWindow(szAppClassName,                            //窗口类型名szWindowName,                            //窗口的标题WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX,//窗口的风格200,                                    //窗口左上角横坐标200,                                    //窗口左上角纵坐标800,                                    //窗口的宽度600,                                    //窗口的高度NULL,                                    //父窗口句柄NULL,                                    //菜单句柄hInstance,                                //应用程序实力句柄NULL                                    //创建窗口需要传递的信息);if (hWnd == NULL){MessageBox(NULL, L"创建窗口失败", L"温馨提示", MB_OK);return 0;}//四、显示窗口ShowWindow(hWnd, SW_SHOW);//五、更新窗口UpdateWindow(hWnd);//六、消息循环/*typedef struct tagMSG {HWND        hwnd;                        //消息发给哪一个窗口的窗口句柄UINT        message;                    //消息编号,WPARAM      wParam;                        //附加信息LPARAM      lParam;                        //附加信息DWORD       time;                        //消息投放到消息队列里面的时间POINT       pt;                            //消息放入消息队列的时候鼠标的坐标
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;*///只要收到了 WM_QUIT消息,函数返回:0MSG msg;while (GetMessage(&msg, NULL, 0, 0)){//将虚拟键消息转为字符消息TranslateMessage(&msg);//将虚拟键消息分发给窗口处理函数DispatchMessage(&msg);}return 0;//程序退出了,结束了
}//窗口处理函数
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{switch (uMsg){case WM_CLOSE://窗口关闭消息//MessageBox(NULL, L"点了关闭按钮", L"提示", MB_OK);DestroyWindow(hWnd);//销毁窗口break;case WM_DESTROY://窗口销毁消息PostQuitMessage(0); //发出一个退出消息 :WM_QUITbreak;}return DefWindowProc(hWnd, uMsg, wParam, lParam);//操作系统默认处理消息的函数
}//Windows消息机制原理

http://chatgpt.dhexx.cn/article/dePa4GP3.shtml

相关文章

windows全系1

windows操作系统专贴(一定有你想要的) 2006年12月01日 22:25 windows 98 简体中文零售版第三版 语言&#xff1a;简体中文 类型&#xff1a;操作系统 大小&#xff1a;180MB 环境&#xff1a;9x/Me/NT/2000/XP/.Net/ 授权&#xff1a;零售版 软件介绍:这个版本是SE的改进版,比前…

对不起,说句粗话——这个太屌了,windows1.0安装程序(附下载)

今天逛一个软件论坛发现的&#xff0c;只有几百K。遥想当今我刚接触windows的版本是3.1&#xff0c;当时记得很清楚哦&#xff0c;进入windows要从dos命令行进入。现在一转眼&#xff0c;变成进入伪dos是运行栏里敲cmd了。 唉&#xff0c;想当年尿尿还能疵2米多远的时候&#…

Windows入门(一)

本人正在学习Windows编程操作&#xff0c;所以进行一些记录&#xff0c;希望对刚入门的个位有所帮助。 目录 1.什么是win32编程 2. 一个简单的win32程序 2.1 创建一个空项目 2.2 入口函数 2.3 注册窗口 2.3.1 窗口回调函数 2.4 创建窗口 2.5 显示窗口 2.6 更新窗口 3.…

win11网页版

网页版地址 点它 https://win11.blueedge.me/ 其github库地址其github库地址https://github.com/blueedgetechno/win11React/

windows10/11子系统安装ubuntu22.04

学习目标&#xff1a; winfows10/11 安装wsl内核 基于wsl内核安装Ubuntu系统 基于ubuntu系统安装docker环境 学习内容&#xff1a; 系统下安装wsl2下载ubuntu安装包windows11 安装ubuntu 22.04系统ubuntu 22.04 安装dockerdocker 启动、测试 windows下安装wsl2内核 1、如果未…

快速教你在虚拟机上完美安装Windows1.0

想必不用我说大家用虚拟机安装Windows1.0时都是这样的: 今天我就来教大家如何正确安装Windows1.0 因为在1985年(Windows1.0诞生的年代)的鼠标驱动已经不匹配我们的电脑了,所以我们需要先解决鼠标这个问题。 第一步: 打开UltraISO,在里面打开我们Windows1.0第一个镜像(…

Windows:

服务主机:本地系统(网络受限) CPU利用率高&#xff0c;磁盘利用率高 解决方法&#xff1a; 方法一&#xff1a;禁用SuperFetch服务 计算机&#xff1a;—右键“管理”—SuperFetch—停止。或属性—-禁用。 开机就占用50%的内存&#xff08;共8G&#xff09; 关闭家庭组  家…

Windows1.0到Windows10三十年进化史,你还记得自己最初使用的系统吗?

从1985年Windows 1.0正式诞生到2015年Windows 10诞生&#xff0c;微软花了三十年的时间&#xff0c;从像素化桌面到现在扁平化的界面。让我们来看一下Windows 1.0到Windows10三十年来的变化。 1、1985年11月20日&#xff0c;微软发布了第一版的Windows操作系统——Windows1.0。…

【Docker】 Windows10运行Windows镜像时常见错误

项目场景:【Docker】 Windows10运行Windows镜像常见错误 很多项目要求在Windows系统下运行,但开发环境的安装相对复杂,并且难以重新配置到新设备,甚至会出现多个项目的运行环境相互冲突和干扰的情况,这时候配置好一个镜像后就可以一劳永逸解决很多问题,直接用docker拉取Window…

Windows 1.0

Windows 1.0 是微软于1985年11月发布的第一款基于dos的pc图形操作平台.要安装Windows 1.0 先安装好ms-dos2.11.对于ms-dos3以上的,只能看见一个类似资源管理器的程序.因为现在很找到一个很破旧的电脑,所以只能通过虚拟机来实现.推荐使用VMware虚拟机.先进入dos2.11,如下图所示 …

重温经典:Windows1.0系统体验和尝试自己编写Windows1.0系统

相关说明 如果你觉得文章含有侵权部分&#xff0c;可以联系CSDN私聊&#xff0c;我会适当修改。 未经允许&#xff0c;不得转载&#xff0c;如需转载&#xff0c;请CSDN私聊。 Windows Windows&#xff0c;意思是窗口&#xff0c;窗户。当然&#xff0c;他也是一个操作系统的…

[笔记]深入解析Windows操作系统《一》概念和工具

文章目录 前言1.1 Windows操作系统的版本1.2 基础概念和术语Windows API关于 .NetWin32 API 历史服务、函数、例程进程、线程和作业进程tlist /t 查看进程树任务管理查看进程Process Explorer查看进程的细节 线程纤程与用户模式调度器线程 虚拟内存内核模式和用户模式终端服务及…

Windows操作系统各版本的历史 Windows系统历史版本简介

30年间Windows系统有哪些版本&#xff1f;还记得你第一次了解到Windows操作系统存在的时候是哪一年吗&#xff1f;这些操作系统又有哪些特点呢&#xff1f;隐约知道计算机变得越来越小了吗……现在笔者将通过收集的资料&#xff0c;为各位细细解说曾经的操作系统。 30年间Wind…

[字符串]ASCII码表

数字&#xff0c;字母位置 数字0~9对应的ASCII码&#xff08;十进制&#xff09;袭为“48”~“57”大写字母A~Z对应的ASCII码&#xff08;十进制&#xff09;为“65”~“90”小写字母a~z对应的百ASCII码&#xff08;十进制&#xff09;为"97"~“122”表

ASCII 码不同的两种空格:32 和160

背景 在 Linux 下手写一个命令和拷贝 html 页面文本域中的命令执行结果完全不同&#xff0c;后者的命令无法被 Linux 识别。 问题截图 肉眼根本看不出来这两行有什么区别&#xff0c;但执行结果就是有问题。 问题定位 编写测试代码&#xff0c;执行两个字符串的 equals 方法…

ASCII码作用简介

《Linux下的^M困惑》曾提到\r对应的ASCII码十进制形式是13(无显示形式)&#xff0c;对应的八进制形式是15(显示为^M)&#xff0c;有朋友在后台反馈对ASCII码有些疑惑&#xff0c;因此在这&#xff0c;简单介绍下ASCII。 ASCII&#xff0c;英文全称是American Standard Code for…

什么是ASCII码?

ASCII 表 分类 编程技术 ASCII&#xff08;发音&#xff1a;&#xff0c;American Standard Code for Information Interchange&#xff0c;美国信息交换标准代码&#xff09;是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语&#xff0c;而其扩展版本延伸美国标准信…

ASCII码对照表(嘤嘤怪自用)

软件Visual Studio 2022 C语言 ASCII码中 字母的ASCII码大小&#xff1a; “A”为65&#xff1b;“a”为97&#xff1b;“0”为 48 同个字母的大写字母比小写字母要小32 因此字母的大小转换可以加减32实现 ASCII码 1. 数字表达字母 源代码 #include <stdio.h…

字符串 ASCII码

ASCII码、 汉字也可以表示。有7745个 字形码

ASCII码与Unicode编码

1. ASCII码 我们知道&#xff0c;在计算机内部&#xff0c;所有的信息最终都表示为一个二进制的字符串。每一个二进制位&#xff08;bit&#xff09;有0和1两种状态&#xff0c;因此八个二进制位就可以组合出256种状态&#xff0c;这被称为一个字节&#xff08;byte&#xff0…