Windows程序基本概念

事件驱动系统:
Windows程序的运行本质:Message Based,Event Driven。

1.Win32程序开发流程:
Windows程序分为”程序代码“和”UI资源“两个部分。
UI资源是指功能菜单、对话框外貌、程序图标、光标形状等等东西。
这些UI资源的实际内容(二进制代码)是借助各种工具产生的,并以各种扩展名存在,如.ico,.bmp,.cur等。
程序必须在一个所谓的资源描述文档.rc文件中描述它们。
RC编译器(rc.exe)读取文件的描述后将所有的UI资源文件集中制作出了一个.res文件,再与程序代码结合在一起,最后才是一个完整的Windows可执行文件。

2.函数库:
Windows支持动态链接,应用程序所调用的Windows API函数是在执行期才链接上的。
DLL Dynamic Link Library:
包括.dll .exe .fon .mod .drv .ocx都是所谓的动态链接库库函数

Windows调用的函数可以分为C runtimes和Windows API两大部分。
# C runtimes:
 libc.lib  静态链接版本
 msvcrt.lib 动态链接版本的import函数库  链接它需要msvcrt40.dll
# Windows API:
 由操作系统本身(主要是user32.dll,kernel32.dll,gdi32.dll)

3.以消息为基础,以事件驱动之Message Based,Event Driven

所有的GUI系统,都是以消息为基础的事件驱动系统。

Windows程序的运行是依靠外部发生的事件来驱动。
程序不断等待(利用while循环),等待任何可能的输入,然后做出判断,然后在作出相应的处理。
MSG msg;
while(GetMessage(msg,NULL,NULL,NULL)){
 TranslateMessage(msg);
 DispatchMessage(msg);
}
这里的输入是操作系统捕捉到,以消息形式(一种数据结构)进入程序之中。
typedef struct tagMSG{
 HWND hwnd,
 UINT message,
 WPARAM wParam,
 LPARAM lParam,
 DWOR  time,
 POINT  pt
}MSG;

输入分类:
由硬件装置所产生的消息,放在系统队列(system Queue)
由Windows系统和其他应用程序传过来的消息,放在程序队列application Queue

窗口函数:Windows Procedure  or Windows Function
接收并处理消息的主角就是窗口,每一个窗口都应该有一个函数处理消息,这个函数成为窗口处理函数。

程序进入点WinMain:
当Windows的外壳(shell)侦察到一个使用者想要执行一个Windows程序,于是调用加载器将该程序加载,然后调用C startup code,后者再调用WinMain,开始执行程序。
WinMain的四个参数由操作系统传入。

窗口类注册与窗口诞生
程序必须在产生窗口之前先利用API函数RegisterClass设定属性,此操作为注册窗口类。

窗口函数:
窗口函数通常通过利用switch/case方式判断消息种类,以决定处置方式。
由于它是被Windows系统调用,所以是一种callback函数,意思是在你的程序中,被Windows系统调用。

窗口函数一般形式:
LRESULT CALLBACK WndProc(
 HWND hwnd,
 UINT message,
 WPARAM wParam,
 LPARAM lParam
);
无论什么消息都必须被处理,所以switch/case中default:必须调用系统默认的DefWindowProc,这是Windows内部默认的消息处理函数。
窗口函数设计为callback形式,才能开放一个接口给操作系统调用。

消息映射的雏形:
试图把窗口函数的内容设计得更模块化,更一般化,一种做法:MFC消息映射表格
struct MSGMAP_ENTRY{
 UNINT nMessage,
 LONG (*pfn)(HWND,UINT,WPARAM,LPARAM);
};

struct MSGMAP_ENTRY _messageEntries[] = {
 WM_CREATE,Oncreate,
 WM_PAINT,OnPainte,
 .................
}
这样就形成了消息与消息处理例程的关联性建立起来。
MFC将其中的操作封装得更好更精致。

对话框的运行:

Windows对话框以其与父窗口的关系,分为两类:
# 令其父窗口无效,直到对话框结束 modal对话框,比较常用
# 父窗口与对话框共同运行  modelless对话框

为了做出一个对话框,程序员必须准备两样东西:
1)对话框模板dialog template:
 在rc文件中定义的一个对话框外貌,以各种方式定义对话框的大小、字形等
2)对话框函数dialog procedure:
 类似于窗口函数,但是它通常只处理WM_INITDIALOG和WM_COMMAND两个消息。
 对话框的各个控件也是小小窗口,各有自己的窗口函数,它们以消息与其管理者(父窗口)沟通。而所有控件传来的消息都是WM_COMMAND。
 Modal对话框的激活和结束,靠的是DialogBox和EndDialog两个API函数

模块定义文件.def
Windows需要一个模块定义文件,将模块名称、程序段和数据段的内存特性、模块堆heap的大小、堆栈大小、所有callback函数等登记下来。

Windows程序的生与死
1)程序初始化过程中调用CreateWindow,为程序建立一个窗口,作为程序的屏幕。
 CreateWindow产生窗口后送出WM_CREATE直接给窗口函数,后者于是可以在此时做一些初始化工作。
2)在程序活着的过程中,不断以GetMessage从消息队列抓取消息。如果这个消息是WM_QUIT,getMessage会传回0结束while循环,从而结束整个程序
3)DispatchMessage通过Windows USER模块的协助和监督,把分派至窗口函数,消息函数在此处被判别并处理。
4)重复2,3
5)当使用者按下系统菜单中的Close命令项时,系统送出WM_CLOSE。通常系统不会拦截这个消息,于是DefWindowProc处理它
6)DefWindowProc收到WM_CLOSE消息后,调用DestroyWindow把窗口清除,DestroyWindow本身又送出WM_DESTROY
7)程序对WM_DESTROY的标准反应是调用PostQuitMessage。
8)PostQuitMessage只是送出WM_QUIT消息,准备让消息循环中的GetMessage取得,如步骤2,结束程序

空闲时间idle time的处理onidle

空闲时间,系统中没有任何的消息等待处理。
两个不同的API:
# PeekMessage()
# GetMessage()如果再次执行发现消息队列依旧为空,它会取回控制权,让程序在运行一段时间

3.console程序

console程序与Dos程序的区别:
# 编写方式
在IDE下开发,利用Windows编译器、链接器做出来的程序,就是所谓的Win32程序。
如果程序是以main为进入点,调用C runtime函数和“不牵扯GUI”的Win32 API函数,那么就是一个console程序。
console窗口将成为其标准输入输出装置。
过去在DOS环境下编译的程序,成为DOS程序,它不可能调用Win32 API.

# 程序功能
由于console程序可以调用KERNEL32.DLL等,它可以使用Windows提供的各种高级功能,包括产生进程,执行线程,取得虚拟内存,刺探操作系统的各种数据。
但是由于不能调用GUI相关API,不能有华丽的外表。
DOS和console程序都可以做printf输出和cout输出,也可以做scanf输入和cin输入。

# 可运行文件格式
DOS:MZ
console和所有Win32程序一样,所谓的PE格式。

4.进程与线程Process and Thread

 核心对象  创建方式  结束方式
 Event   CreatEvent  CloseEvent
 Mutex
 Semaphore
 File
 File_Mapping
 Process
 Thread
系统给予核心对象一个计数值usage count,没使用一次,对应计数值加1.

进程的诞生和死亡

执行一个程序必然就产生一个进程process。
最直接的方式就是双击一个可执行文件图标,执行起来的APP进程其实就是shell调用CreateProcess激活的:
1)shell调用CreateProcess激活APP.exe
2)系统产生一个“进程核心对象”,计数值+1
3)系统为此进程建立了一个4GB地址空间
4)加载器将必要的代码加载到上述地址空间中,包括APP的程序、数据以及所需的动态链接函数库DLLs。
 它们被记录在可执行文件(PE文件格式)的.idata section
5)系统为进程建立一个线程,称为主线程primary thread,线程才是CPU时间的分配对象
6)系统调用C runtime函数库的Startup Code。
7)Startup code调用APP程序的WinMain函数
8)App程序开始运行
9)使用者关闭APP主窗口,使WinMain中的消息循环结束掉,WinMain结束
10)回到Startup code
11)回到系统,系统调用ExitProcess结束进程
通过这种方式运行的所有Windows程序都是shell的子进程。

线程的诞生和死亡:
执行代码是线程的工作,一个进程建立起来,主线程就产生了,我们可以使用CreateThread产生额外的线程,系统就会帮助我们完成:
1)配置”线程对象“,其handle将成为CreateThread的返回值
2)设定计数值为1
3)配置线程的context
4)保留线程的堆栈
5)将context中的堆栈指针缓存器SS和指令指针缓存器IP设定妥当

线程的结束,或寿终正寝(执行完毕,系统调用ExitThread),或未得善终(被别的线程强制终结TerminateThread)
使用_beginthreadex取代CreateThread。

线程优先级Priority

优先级是线程调度的重要依据。线程的优先级范围从0到31(最高)。
首先需要指定”优先级等级“给进程,然后指定”相对优先级“给该进程所拥有的线程
等级   代码   优先级
idle  IDLE_PRIORITY_CLASS  4
normal  NORMAL_PRIORITY_CLASS 9(前台)或7(后台)(前台线程一般应该比后台线程调高)
high  HIGH_PRIORITY_CLASS  13
realtime  REALTIME_PRIORITY_CLASS 24

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值