WINDOWS核心编程--Windows程序内部运行机制(上)

简介: WINDOWS核心编程--Windows程序内部运行机制

windows程序内部运行机制


学习程序运行机制,为学习MFC打下基础。

我们常用库函数printf----这些C库函数都是编译器厂商提供的。在windows平台下面也有类似的库函数,但这是windows操作系统提供的。

所有主要的windows函数都在Windows.h头文件进行了声明。

这些api不可能都记住。我们要用的时候可以在MSDN里面查找。

从室内高人转为室外高人;

比如开发呼叫中心,我们会有厂商提供的语音卡SDK;


1668342414178.jpg


窗口与句柄


我们启动Windows系统后,看到的桌面也是个窗口,成为桌面窗口,由OS创建和维护。

窗口通过句柄识别:HWND

创建各种资源的时候也会返回他们的句柄:图标句柄HICON,光标句柄HCURSOR


消息与队列


系统反过来调用用户进程---------这个调用通过–消息—实现

事件驱动设计程序

操作系统感知到事件,投递到应用程序的消息队列

发送消息----------操作系统调用程序专门处理消息的函数--------窗口过程

typedef struct tagMSG {
    HWND        hwnd;        //该消息所属的窗口句柄
    UINT        message;    //指定消息的类型
    WPARAM      wParam;        //用于指定消息的附加信息,根据消息不同,代表不同意思
    LPARAM      lParam;        //用于指定消息的附加信息,根据消息不同,代表不同意思
    DWORD       time;        //该消息投递到消息列队当中的时间
    POINT       pt;            //该消息投递到消息列队当时,鼠标的当前位置
} MSG, *PMSG, NEAR *NPMSG, FAR *LPMSG;


第一个参数:hwnd hwnd是一个窗口句柄,用于区别该消息属于哪一个窗口,可以说是一个窗口的编号。一个消息一般都与某个窗口相关联,比如鼠标移动到某个窗口中按下鼠标左键,该窗口就会收到一个“WM_LBUTTONDOWND”的消息,而应用程序就是利用消息中的hwnd值来 确定该消息到底是属于众多窗口中的哪一个窗口的。


第二个参数:message 为消息类型,该值为一个数值,不同的数值表示不同的消息,为了便于记忆,windows 为不同的消息定义了不同的宏,WM_XXX。(WM是windows message的缩写),例如 WM_LBUTTONDOWN 消息 按下鼠标左键的消息是 WM_KEYDOWN 消息 表示按下键盘上的某个键等等。


第三个参数:wParam WPARAM类型 根据不同的消息 代表不同的意思:例如 当收到 WM_LBUTTONDOWN 消息时,wParam 鼠标按钮、Shift和Ctrl键的状态。


第四个参数:lParam LPARAM类型 WPARAM类型 根据不同的消息 代表不同的意思:例如 当收到 WM_SIZE 消息时候 lParam - 客户区的大小。 LOWORD(底位) - 客户区的宽度。 HIWORD(高位) - 客户区的高度。


第五个参数:time -表示收到该消息的时间


第六个参数:pt -表示收到该消息时鼠标的当前位置


想知道WM_XXX消息对应的具体数值?


选中后,右键点击转到定义


消息队列


OS将消息放到程序的队列,等待处理

进队消息&不进队消息

不进队消息:调用窗口过程时候,直接发送给窗口


WinMain函数


windows程序入口函数

与dos程序入口main作用相同


WinMain 函数的原型声明如下:

int WINAPI WinMain(
HINSTANCE hInstance , // handle to current instance
HINSTANCE hPrevInstance , // handle to previous instance
LPSTR lpCmdLine , // command line
int nCmdShow // show state
);


WinMain 函数接收 4 个参数,这些参数都是在系统调用 WinMain 函数时,传递给应用程序的。


第一个参数 hInstance 表示该程序当前运行的实例的句柄,这是一个数值。当程序在 Windows 下运行时,它唯一标识运行中的实例(注意,只有运行中的程序实例,才有实例句柄)。一个应用程序可以运行多个实例,每运行一个实例,系统都会给该实例分配一个句柄值,并通过 hInstance 参数传递给 WinMain 函数。


第二个参数 hPrevInstance 表示当前实例的前一个实例的句柄。通过查看 MSDN 我们可以知道,在 Win32 环境下,这个参数总是 NULL ,即在 Win32 环境下,这个参数不再起作用。


第三个参数 lpCmdLine 是一个以空终止的字符串,指定传递给应用程序的命令行参数。 例如:在 D 盘下有一个 sunxin.txt 文件,当我们用鼠标双击这个文件时将启动记事本程序( notepad.exe ),此时系统会将 D:/sunxin.txt 作为命令行参数传递给记事本程序的 WinMain 函数,记事本程序在得到这个文件的全路径名后,就在窗口中显示该文件的内容。要在 VC++ 开发环境中向应用程序传递参数,可以单击菜单 【 Project 】→【 Settings 】,选择“ Debug ” 选项卡,在“ Program arguments ”编辑框中输入你想传递给应用程序的参数。


1668342570115.jpg


第四个参数 nCmdShow 指定程序的窗口应该如何显示,例如最大化、最小化、隐藏等。这个参数的值由该程序的调用者所指定,在调用ShowWindow()时可以使用到该值。


窗口的创建


设计一个窗口类


windows给我们设计好了,只需要做填空,就能创建很好的类

结构WNDCLASS包含一个窗口类的全部信息,也是Windows编程中使用的基本数据结构之一,应用程序通过定义一个窗口类确定窗口的属性,定义如下:

typedef struct _WNDCLASS {
  UINT style;
  WNDPROC lpfnWndProc;
  int cbClsExtra;
  int cbWndExtra;
  HINSTANCE hInstance;
  HICON hIcon;
  HCURSOR hCursor;
  HBRUSH hbrBackground;
  LPCTSTR lpszMenuName;
  LPCTSTR lpszClassName;
} WNDCLASS, *PWNDCLASS;


style: 指定类风格。这些风格可通过按位或操作组合起来。风格如下:


CS_BYTEALIGNCLIENT: 在字节边界上(在x方向上)定位窗口的用户区域的位置


CS_BYTEALIGNWINDOW: 在字节边界上(在x方向上)定位窗口的位置


CS_CLASSDC: 该窗口类的所有窗口实例都共享一个窗口类DC


CS_DBLCLKS: 允许向窗口发送双击鼠标键的消息


CS_GLOBALCLASS: 当调用CreateWindow 或 CreateWindowEx 函数来创建窗口时允许它的hInstance参数和注册窗口类时传递给


RegisterClass 的 hInstance参数不同。如果不指定该风格,则这两个 hInstance 必须相同。


CS_HREDRAW: 当水平长度改变或移动窗口时,重画整个窗口


CS_NOCLOSE: 禁止系统菜单的关闭选项


CS_OWNDC: 给予每个窗口实例它本身的DC。注意,尽管这样是很方便,但它必须慎重使用,因为每个DC大约要占800个字节的内存。


CS_PARENTDC: 将子窗口的裁剪区域设置到父窗口的DC中去,这样子窗口便可以在父窗口上绘制自身。注意,这是子窗口还是从系统缓存中获取DC,而不是使用父窗口的DC。使用该风格可以提高系统性能。


CS_SAVEBITS: 以位图形式保存被该窗口遮挡的屏幕部分,这样当给窗口移动以后,系统便可以用该保存的位图恢复屏幕移动的相应部分,从而系统不用向被该窗口遮挡的窗口发送 WM_PAINT 消息。该特性对于菜单类型的窗口比较合适,因为它通常是简短的显示一下之后便消失。设置该特性将增加显示该窗口的时间,因为它通常要先分配保存位图的内存。


CS_VREDRAW: 当垂直长度改变或移动窗口时,重画整个窗口


CS_开头的类样式(class style)


在WinUser.h里面,被定义为16位的常量

1668342623846.jpg

转为2进制发现-----16位上只有一个1

如果重绘窗口----------去掉某个样式可以&(某个样式取反)

由此可以用或( | )运算-------把两个样式组合起来


lpfnWndProc—一个函数指针-----指向 窗口过程函数(是一个回调函数)


特定事件发生产生有另一方调用,用于相应事件


窗口过程函数-----地址赋给lpfnWndProc成员变量

1668342649385.jpg

1668342665189.jpg

1668342672374.jpg

WNDPROC被定义为窗口过程函数的指针类型,窗口过程函数的格式必须与WNDPROC相同


__stdcall与__cedcl—这是两个不同的函数调用约定,定义了弹出栈的不同的约定,到底是谁弹出,让被调用函数还是调用函数弹出


printf用的是__cdecl调用约定,VS开发环境也是


Win32的函数都默认用__stdcall调用


第三个成员变量–cbClsExtra


OS为系统每个窗口类管理一个WNDCLASS结构

这是类附加内存-----所有窗口共享

用于存储类的附加信息

一般就直接设置0


第四个----cbWndExtra


附加内存空间------------窗口附加内存

没有使用就设置0即可


第五个hInstance —窗口过程的实际句柄


第六个 hIcon 图标句柄


1668342718780.jpg

VC++开发中,自定义菜单图标被命名为.rc----------资源脚本

VC++中,资源是通过标识符ID来识别的

ID是在resource.h的宏

他的lpIconname是一个指针,指向资源


第七个–hCursor是一个光标资源


第八个hbrBackground—窗口类的背景画刷句柄


第九个lpszMenuName----以空终止的字符串—指定菜单资源的名字


菜单不是一个窗口


第十个lpszClassName----以空终止的字符串—指定窗口类的名字


设计了新的型号的汽车,要起个名字

设计了新类型的窗口也要为该类型窗口取个名字


注册窗口类


相当于设计完后要government审批

批准后才能生产

调用RegisterClass注册

只有一个参数----上一步骤中所设计窗口类的对象的指针


创建窗口


用Create Window创建窗口


#define CreateWindowW(lpClassName, lpWindowName, dwStyle, x, y,\
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam)\


lpClassName 指定窗口类名称----------注册过的名字
lpWindowName指定窗口名称---------标题栏名字
dwStyle--------窗口样式,不同的汽车颜色---------可以指定WS_OVERLAPPEDWINDOW
#define WS_OVERLAPPEDWINDOW (WS_OVERLAPPED     | \//层叠的窗口,一个标题栏和一个边框
                             WS_CAPTION        | \ //有标题栏的窗口
                             WS_SYSMENU        | \ //标题栏上带有系统菜单的窗口口
                             WS_THICKFRAME     | \ //有可调节边框
                             WS_MINIMIZEBOX    | \//有最小化
                             WS_MAXIMIZEBOX)

1668342801459.jpg

父窗口对子窗口有影响: 销毁,在父窗口被销毁前销毁


/符号的意义


“\” 用于连接通常有两个方面:

①:在典型情况下用于转义连续多行的宏定义。(如上)

②:在逻辑上把下一行当作当前行的延续,它可以用于连接长字符串。(如下)


char a[] = "Hi! How are you? I am \
fine, thank you!";


注意: 在 \ 后面不能有其他字符,空格也不行!


显示及更新窗口


显示出来 ShowWindow

ShowWindow(
    _In_ HWND hWnd,
    _In_ int nCmdShow);


nCmdShow------------窗口显示状态

1668342894755.jpg

相关文章
|
3月前
|
Linux 虚拟化 iOS开发
VMware Fusion 13.6.4 OEM BIOS 2.7 - 在 macOS 中运行 Windows 虚拟机的最佳方式
VMware Fusion 13.6.4 OEM BIOS 2.7 - 在 macOS 中运行 Windows 虚拟机的最佳方式
417 3
|
3月前
|
Windows
Windows下版本控制器(SVN)-验证是否安装成功+配置版本库+启动服务器端程序
Windows下版本控制器(SVN)-验证是否安装成功+配置版本库+启动服务器端程序
128 2
|
4月前
|
Windows
Windows下版本控制器(SVN)-启动服务器端程序
Windows下版本控制器(SVN)-启动服务器端程序
135 4
|
5月前
|
安全 Devops 测试技术
AppSpider 7.5.018 for Windows - Web 应用程序安全测试
AppSpider 7.5.018 for Windows - Web 应用程序安全测试
113 0
AppSpider 7.5.018 for Windows - Web 应用程序安全测试
|
8月前
|
安全 JavaScript Java
AppSpider Pro 7.5.015 for Windows - Web 应用程序安全测试
AppSpider Pro 7.5.015 for Windows - Web 应用程序安全测试
119 12
AppSpider Pro 7.5.015 for Windows - Web 应用程序安全测试
|
7月前
|
Windows
Windows程序的数字签名证书怎么申请
Windows程序的数字签名证书申请流程包括:准备企业资料(营业执照、税务登记证等),提交申请表及企业资料。经过初审、实名认证和二审后,等待1-5个工作日审核结果。审核通过后,CA机构颁发证书并通过邮件或邮寄方式发送。收到证书后按指南安装并使用签名工具对程序进行数字签名,确保软件完整性和可信度。注意证书有效期、管理和兼容性问题。
|
7月前
|
自然语言处理 安全 测试技术
HCL AppScan Standard 10.8.0 (Windows) - Web 应用程序安全测试
HCL AppScan Standard 10.8.0 (Windows) - Web 应用程序安全测试
406 0
HCL AppScan Standard 10.8.0 (Windows) - Web 应用程序安全测试
|
7月前
|
算法 关系型数据库 测试技术
WHQL微软驱动签名方案,让驱动程序在Windows系统流畅运行
WHQL认证(Windows徽标认证)是微软设立的严格测试标准,旨在确保驱动程序的兼容性、稳定性和互通性。本文介绍了三种WHQL微软驱动签名方案:单系统签名、多系统签名和硬件兼容性测试方案,分别满足不同开发商的需求。通过WHQL认证,不仅能消除Windows安装警告,提升用户体验,还能获得“Designed for Windows”徽标授权,入列全球Windows Catalog及HCL产品表,提升品牌权威性和采购优先权。此外,访问微软OCA可获取错误反馈,助力产品质量改进。选择合适的签名方案,让驱动在Windows系统中流畅运行!
|
29天前
|
运维 安全 网络安全
Windows Server 2019拨号“找不到设备”?Error 1058解决指南
Windows Server 2019拨号报错1058?别急!这不是硬件故障,而是关键服务被禁用。通过“服务依存关系”排查,依次启动“安全套接字隧道协议”“远程接入连接管理”和“路由与远程访问”服务,仅需4步即可恢复PPPoE或VPN拨号功能,轻松解决网络中断问题。
128 1
|
1月前
|
存储 SQL 人工智能
Windows Server 2025 中文版、英文版下载 (2025 年 9 月更新)
Windows Server 2025 中文版、英文版下载 (2025 年 9 月更新)
692 3
Windows Server 2025 中文版、英文版下载 (2025 年 9 月更新)

热门文章

最新文章