MFC学习笔记1--Win32基本程序观念

Windows程序运行本质:Message based, Event driven
程序进入点WimMain
窗口类的注册 RegisterClass,放在InitApplication函数中。
窗口类的诞生 CreateWindow,放在InitInstance函数中。
初始化完成后,WinMain进入消息循环
while(GetMessage(&msg, ...)) {
	TranslateMessage(&msg);	//转换键盘消息
	DispatchMessage(&msg);	//分派消息
}

DispatchMessage将消息送到窗口函数,窗口函数的形式为:
LRESULT CALLBACK WndProc(HWND hWnd,
						UINT message,
						WPARAM wParam,
						LPARAM lParam)

窗口函数通常利用switch/case方式判断消息种类,以决定处置方式,switch/case指令中的default:处必须调用DefWindowProc;这是Windows默认消息处理函数。
消息映射(Message Map):将数据和处理数据的方法封装起来。
对话框的运行:
1.modal对话框:令其父窗口无效,直到对话框结束。激活DialogBox,结束EndDialog。
2.modeless对话框:父窗口与对话框同时运行。
对话框包括:
1.对话框模块(dialog template)
2.对话框函数(dialog procedure) WM_INITDIALOG , WM_COMMAND
模块定义文件(.DEF)
资源描述文件(.RC)
【窗口的生命周期】
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的标准反应是调用postQuitMessgae.
8.PostQuitMessage没什么其他操作,就只送出WM_QUIT消息,准备让消息循环中的GetMessage取得,如步骤2,结束消息循环。

空闲时间的处理:OnIdle
  空闲时间(idle time):系统没有任何消息等待处理的时候。
  传统SDK程序如果要处理空闲时间,可采用PeekMessage方式取代WinMain中传统高的消息循环:
while(true) {
	if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
		if(msg.message == WM_QUIT) break;
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
}


GetMessage:遇Idle跳过。
PeekMessage:遇Idle取回控制权,执行一段时间。
Console程序:不牵扯任何窗口、对话框、控件的程序。
MFC Console程序的特点:
1.程序进入点仍为main
2.需载入所使用的类的头文件
3.可直接使用与GUI无关的MFC类。(如:CStdio,CString)
4.编辑时指定 /MT,表示使用多线程版本的C runtime函数库。
Visual C++提供6个C runtime函数库产品:
/ML Single-Threaded(static)
/MT Multithreaded(static)
/MD Multithreaded DLL(dynamic import library)
/MLd Debug Single-Threaded(static)
/MTd Debug Multithreaded(static)
/MDd Debug Multithreaded DLL(dynamic import library)
进程与线程(Process and Thread)
核心对象(kernel object):系统的一种资源,系统给予核心对象一个计数值(usage count)作为管理之用。
核心对象包括:event, mutex, semaphore, file, file-mapping, process, thread
以handle作为识别;handle每被使用一次,对应的计数加1.
核心对象的结束方式:调用CloseHandle.
一个进程的诞生与死亡:
1.shell 调用 CreateProcess 激活 App.exe.
2.系统产生一个“进程核心对象”,计数值为1.
3.系统为此进程建立一个4GB地址空间。
4.加载器将必要的代码加载到上述地址空间中,包括App.exe的程序、数据,以及所需的动态链接函数库(DLLs)。加载器如何知道要加载哪些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的子进程。
产生子进程:CreateProcess
当系统为我们产生“进程对象”和“线程对象”时,它会把两个对象的handle填入此结构的相关字段中,应用程序从这里获得这些handles。
进程结束本身:
VOID ExitProcess(UINT fuExitCode);
进程结束另一进程:
BOOL TerminateProcess(HANDLE hProcess, UINT fuExitCode);
结束子进程:CloseHandle
一个线程的诞生与死亡:
  调用CreateThread,系统会帮助完成:
1.配置“线程对象”,其handle将成为CreateThread的返回值。
2.设定计数值1.
3.配置线程的context。
4.保留线程的堆栈。
5.将context中的堆栈指针缓存器(SS)和指令指针缓存器(IP)设定妥当。
线程是CPU分配时间的单位。
工作切换(context switch)其实就是对线程的context的切换。
以_beginthreadex 取代 CreateThread
范例:
#include <windows.h>
#include <process.h>
unsigned __stdcall myfunc(void* p);


int main() {
    unsigned long thd;
    unsigned tid;


    thd = _beginthreadex(NULL,
                         0,
                         myfunc,
                         0,
                         0,
                         &tid);
    if(thd != NULL) {
        CloseHandle(thd);
    }
}


unsigned __stdcall myfunc(void* p) {
    //do your job...
}


线程优先级(Priority)
  0(最低)至31(最高)  idle, normal, high, realtime.
  SetThreadPriority 设定优先级
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值