Windows内核开发

Windows内核开发

Unit01对话框

对话框是一种很特殊的窗口,体现在消息的处理上

//普通窗口处理消息:自定义函数调用缺省消息处理函数
WndProc(...){
	...
	DefWindowProc(...);
}

//对话框窗口处理消息:缺省函数调用自定义函数
缺省函数(...){
	...
	自定义函数(...);
	....
}

01对话框原理

  • 对话框的分类
    • 模式对话框:当对话框显示时,会禁止本进程其他窗口和用户交互操作
    • 无模式对话框:在对话框显示后,其他窗口仍然可以和用户交互操作
  • 对话框基本使用
    • 1.对话框处理函数
    • 2.注册窗口类(不用程序员自己注册窗口类,系统已经注册好对话框的窗口类)
    • 3.创建对话框
    • 4.对话框的关闭
  • 对话框窗口处理函数(并非真正的对话框窗口处理函数)
INT CALLBACK DialogProc(//函数名自定义
	HWND hwndDlg, //窗口句柄
	UINT uMsg, //消息ID
 	WPARAM wParam, //消息参数
	LPARAM lParam//消息参数
);
//返回TRUE,缺省处理函数不需要处理
//返回FaLSE,交给缺省处理函数处理
//不需要调用缺省对话框处理函数

Windows内核开发_第1张图片

02模式对话框

  • 创建模式对话框
int DialogBox(
	HINSTANCE hInstance,//应用程序实例句柄
	LPCTSTR lpTemplate,//对话框资源ID
	HWND hWndParent, //对话框窗口
	DLGPROC lpDialogFunc//自定义函数
); 
//DialogBox是一个阻塞函数,只有当对话框关闭后,才会返回,继续执行后续代码
//返回值是通过EndDialog设置
  • 关闭对话框
BOOL EndDialog(
	HWND hDlg,//关闭的对话框窗口句柄
	int nResult//关闭的返回值
); 
//关闭模式对话框,只能适应EndDialog,不能使用DestoryWindow等函数
//nResult是DialogBox函数退出时的返回值
  • 对话框的消息:WM_INITDIALOG对话框创建之后显示之前,通过对话框窗口处理函数,可以完成自己的初始化相关的操作

示例代码:
Windows内核开发_第2张图片
Windows内核开发_第3张图片

Windows内核开发_第4张图片

Windows内核开发_第5张图片

#include 
#include "resource.h"

HINSTANCE g_hInstance = 0;

INT CALLBACK DlgProc(HWND hWndlg,UINT msgID,WPARAM wParam,LPARAM lParam){
	switch(msgID){
	case WM_INITDIALOG:
		MessageBox(hWndlg, "WM_INITDIALOG", "Infor", MB_OK);
		break;
	case WM_CREATE://为了验证对话框没有这个消息
		MessageBox(hWndlg, "WM_CREATE", "Infor", MB_OK);
		break;
	case WM_SYSCOMMAND:
		if(wParam == SC_CLOSE){
			//销毁对话框
			EndDialog(hWndlg,100);//两个功能销毁知名的对话框、解除DialogBox的阻塞
			//DestroyWindow(hWndlg);//只是销毁对话框,但是并没有解除解除DialogBox的阻塞,所以不能用
		}
		break;
	}
	return FALSE;//将消息交给真正的对话框窗口系统处理函数的后续代码帮我们处理
}

void OnCommand(HWND hWnd, WPARAM wParam){
	switch(LOWORD(wParam)){
	case ID_MODEL:
		int nRet = DialogBox(g_hInstance, (char*)IDD_DIALOG1,hWnd,DlgProc);
		if(nRet == 100)
		{
			MessageBox(hWnd, "successful", "Infor", MB_OK);
		}
		break;
	}
}
//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
	switch(msgID){
	case WM_COMMAND:
		OnCommand(hWnd, wParam);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
	g_hInstance = hIns;
	//注册窗口类
	WNDCLASS wc = {0};
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor = NULL;
	wc.hIcon = NULL;
	wc.hInstance = hIns;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = "Main";
	//挂载菜单资源
	wc.lpszMenuName = (char*)IDR_MENU1;
	wc.style = CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
	//在内存创建窗口
	HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg = {0};
	while(GetMessage(&nMsg,NULL,0,0))
	{
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
	}
	return 0;
}

Windows内核开发_第6张图片
Windows内核开发_第7张图片
Windows内核开发_第8张图片

03无模式对话框

  • 创建无模式对话框
HWND CreateDialog(
	HINSTANCE hInstance,//应用程序实例句柄
	LPCTSTR lpTemplate, //模板资源ID
	HWND hWndParent,//父窗口
	DLGPROC lpDialogFunc//自定义函数
); 
//非阻塞函数,创建成功返回窗口句柄,需要使用ShowWindow函数显示对话框
BOOL ShowWindow(
	HWND hWnd,
	int nCmdShow
); 

Windows内核开发_第9张图片

  • 对话框的关闭
    • 关闭时使用DestroyWindow销毁窗口哦,不能使用EndDialog关闭对话框
BOOL DestroyWindow(HWND hWnd); 

示例代码:

#include 
#include "resource.h"

HINSTANCE h_gInstance = 0;

INT CALLBACK DlgProc(HWND hWndlg,UINT msgID,WPARAM wParam,LPARAM lParam){
	switch(msgID){
	case WM_SYSCOMMAND:
		if(wParam == SC_CLOSE)
			DestroyWindow(hWndlg);
		break;
	}
	return FALSE;
}

void OnCommand(HWND hWnd,WPARAM wParam){
	switch(LOWORD(wParam)){
	case ID_UNMODEL:
		HWND hWndlg = CreateDialog(h_gInstance, (char*)IDD_DIALOG1, hWnd, DlgProc);
		ShowWindow(hWndlg, SW_SHOWNORMAL);
		break;
	}
}

//窗口处理函数(自定义,处理函数)
LRESULT CALLBACK WndProc(HWND hWnd,UINT msgID,WPARAM wParam,LPARAM lParam)
{
	switch(msgID){
	case WM_COMMAND:
		OnCommand(hWnd, wParam);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//可以使GetMessage函数返回0
		break;
	}
	return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns,LPSTR lpCmdLine,int nCmdShow)
{
	h_gInstance = hIns;
	//注册窗口类
	WNDCLASS wc = {0};
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.hCursor = NULL;
	wc.hIcon = NULL;
	wc.hInstance = hIns;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = "Main";
	wc.lpszMenuName = (char*)IDR_MENU1;
	wc.style = CS_HREDRAW|CS_VREDRAW;
	RegisterClass(&wc);//将以上所有赋值全部写入操作系统内核
	//在内存创建窗口
	HWND hWnd = CreateWindowEx(0,"Main","window",WS_OVERLAPPEDWINDOW,100,100,500,500,NULL,NULL,hIns,NULL);
	//显示窗口
	ShowWindow(hWnd,SW_SHOW);
	UpdateWindow(hWnd);
	//消息循环
	MSG nMsg = {0};
	while(GetMessage(&nMsg,NULL,0,0))
	{
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);//将消息交给窗口处理函数来处理
	}
	return 0;
}

Unit02静态库

01静态库特点

  • 运行不存在
  • 静态库源码被链接到调用程序中
  • 目标程序的归档(就是程功能已经封装好直接来调用就行)

02C语言静态库

  • C静态库的创建
    • 创建一个静态库项目
    • 添加库程序,源文件适应C文件
  • C静态库的使用
    • 库路径设置:可以使用pragma关键字设置
    • #pragma comment(lib,"../lib/clib.lib")
      Windows内核开发_第10张图片Windows内核开发_第11张图片Windows内核开发_第12张图片

Windows内核开发_第13张图片
![在这里插入图片描述](https://img-blog.csdnimg.cn/002a6bcdc7964dcaaf19f2d7ac1ed96a.png#pic_centerWindows内核开发_第14张图片
Windows内核开发_第15张图片
Windows内核开发_第16张图片Windows内核开发_第17张图片
Windows内核开发_第18张图片

Windows内核开发_第19张图片Windows内核开发_第20张图片

//通知链接器到哪抓源码
#pragma comment(lib, "../Debug/Clib.lib")

int main(void){
	int sum, sub;

	sum = Clib_add(5,3);
	sub = Clib_sub(5,3);

	printf("sum=%d, sub=%d\n", sum, sub);
	getchar();
	return 0;
}

03C++语言静态库

  • C++静态库的创建
    • 创建一个静态库项目
    • 添加程序库,源文件使用CPP文件
  • C++静态库的使用
    • 库路径设置:可以使用pragma关键字设置
    • #progma comment(lib, "../lib/cpplib.lib")
      Windows内核开发_第21张图片
      Windows内核开发_第22张图片

Windows内核开发_第23张图片
Windows内核开发_第24张图片
Windows内核开发_第25张图片
Windows内核开发_第26张图片
Windows内核开发_第27张图片
Windows内核开发_第28张图片
在这里插入图片描述
Windows内核开发_第29张图片
Windows内核开发_第30张图片
Windows内核开发_第31张图片
Windows内核开发_第32张图片

#include 

using namespace std;

//添加函数声明
int CPPlib_add(int add1, int add2);
int CPPlib_sub(int sub1, int sub2);
//给连接器看的
#pragma comment(lib, "../Debug/CPPlib.lib")

int main(){
	int sum = CPPlib_add(5, 4);
	int sub = CPPlib_sub(5, 4);
	cout << "sum=" << sum << ".sub=" << sub << endl;
	getchar();
	return 0;
}
  • 使用C++调C语言的静态库
#include 

using namespace std;

//添加函数声明
int CPPlib_add(int add1, int add2);
int CPPlib_sub(int sub1, int sub2);
//给连接器看的
#pragma comment(lib, "../Debug/CPPlib.lib")

//使用C语言的Clib.lib库函数,extern "C"防止c++编译器进行换名操作
extern "C" int Clib_add(int add1, int add2);
extern "C" int Clib_sub(int sub1, int sub2);
#pragma comment(lib, "../Debug/Clib.lib")

int main(){
	int sum = CPPlib_add(5, 4);//?CPPlib_add@@YAHHH@Z
	int sub = CPPlib_sub(5, 4);//?CPPlib_sub@@YAHHH@Z
	cout << "sum=" << sum << ".sub=" << sub << endl;

	sum = Clib_add(5,3);//Clib_add
	sub = Clib_sub(5,3);//Clib_sub
	cout << "sum=" << sum << ".sub=" << sub << endl;
	getchar();
	return 0;
}

Windows内核开发_第33张图片

Unit03动态库

01动态库的特点

  • 动态库的特点
    • 运行时独立存在
    • 源码不会链接到执行程序
    • 使用加载(使用动态库必须使动态库执行,就是让动态库进入内存)
  • 与静态库相比较
    • 由于静态库是将代码嵌入到使用程序中,多个程序使用时,会有多份代码,所以代码体积会增大。动态库的代码只需要一份,其他程序通过函数地址使用,所以代码体积小
    • 静态库发生变化后,新的代码需要重新链接嵌入到执行程序中,动态库发生变化后如果库中的函数的定义(或地址)未变化,其他使用DLL的程序不需要重新链接。

02动态库创建

  • 创建动态库项目
  • 添加库程序
  • 库程序导出:提供给使用者库中的函数信息(实际是导出的是动态库封装的函数的地址导出来,导出的地址在dll文件的文件头中)
    • 1.声明导出:使用_declspec(dllexport)导出函数
      • 注意:动态库编译链接后,也会有LIB文件,是作为动态库函数映射使用,与静态库不完全相同
    • 2.模块定义文件.def
      • 例如:LIBRARY DLLFunc//库
      • EXPORTS//库导出表
      • DLL_Mul @1//导出的函数
        Windows内核开发_第34张图片
        Windows内核开发_第35张图片
        Windows内核开发_第36张图片
        Windows内核开发_第37张图片
        Windows内核开发_第38张图片
        Windows内核开发_第39张图片
        Windows内核开发_第40张图片Windows内核开发_第41张图片

//_declspec(dllexport)加上这个是为了导出动态库函数
_declspec(dllexport) int CPPdll_add(int add1, int add2){
	return add1 + add2;
}

_declspec(dllexport) int CPPdll_sub(int sub1, int sub2){
	return sub1 + sub2;
}

_declspec(dllexport) int CPPdll_mul(int mul1, int mul2){
	return mul1 + mul2;
}

03动态库的使用

隐式链接(操作系统负责动态库执行)

  • 头文件和函数原型:可以在函数原型的声明前,增加_declspec(dllimport)
  • 导入动态库和LIB文件,#pragma comment(lib, "../Debug/CPPdll.lib")
  • 在程序中使用函数
  • 隐式链接的情况:dll文件可以存放在的路径:
    • 与执行文件同一个目录下(推荐使用这个路径下)
    • 当前工作目录(就是当前的项目目录下)
    • Windows目录(不建议放在系统目录下)
    • Windows/System32目录(不建议放在系统目录下)
    • Windows/System(不建议放在系统目录下)
    • 环境变量PATH指定目录(不建议放在系统路径下中,因为可以更改)
      Windows内核开发_第42张图片
      Windows内核开发_第43张图片Windows内核开发_第44张图片
      Windows内核开发_第45张图片
      Windows内核开发_第46张图片
      Windows内核开发_第47张图片
      Windows内核开发_第48张图片
#include 

using namespace std;
//声明函数
_declspec(dllimport) int CPPdll_add(int add1, int add2);
_declspec(dllimport) int CPPdll_sub(int sub1, int sub2);
_declspec(dllimport) int CPPdll_mul(int mul1, int mul2);

//通知链接器到哪抓函数的 编号和dll文件名("CPPdll.dll")
#pragma comment(lib, "../Debug/CPPdll.lib")

int main(){
	int sum = CPPdll_add(5,4);
	int sub = CPPdll_sub(5,4);
	int mul = CPPdll_mul(5,4);
	cout << "sum=" << sum << ",sub=" << sub << ",mul=" << mul << endl;
	system("pause");
	return 0;
}

显式链接(程序员自己负责使用动态库执行)

  • 定义函数指针类型typedef
  • 加载动态库(就是让动态进内存)
HMODULE LoadLibrary(
  LPCTSTR lpFileName//动态库文件名或全路径
);//返回DLL的实例句柄(HINSTANCE)
  • 获取函数真实地址
FARPROC GetProcAddress(
	HMODULE hModule,//DLL句柄
	LPCWSTR lpProcName//函数名称
); //成功返回函数地址
  • 使用函数
  • 卸载动态库
BOOL FreeLibrary(
	HMODULE hLibModule//DLL的实例句柄
); 

Windows内核开发_第49张图片

Windows内核开发_第50张图片

Windows内核开发_第51张图片

Windows内核开发_第52张图片

#include 
#include 

using namespace std;

typedef int(*ADD)(int m, int n);
typedef int(*SUB)(int m, int n);
typedef int(*MUL)(int m, int n);

int main(){
	HINSTANCE hDll = LoadLibrary("CPPdll.dll");
	cout << "hDll:" << hDll << endl;

	//ADD myAdd = (ADD)GetProcAddress(hDll, "CPPdll_add");
	ADD myAdd = (ADD)GetProcAddress(hDll, "?CPPdll_add@@YAHHH@Z");
	cout << "myAdd:" << myAdd << endl;
	int sum = myAdd(5,4);
	cout << "sum=" << sum << endl;
	
	//SUB mySub = (SUB)GetProcAddress(hDll, "CPPdll_sub");
	SUB mySub = (SUB)GetProcAddress(hDll, "?CPPdll_sub@@YAHHH@Z");
	cout << "mySub:" << mySub << endl;
	int sub = mySub(5,4);
	cout << "sub=" << sub << endl;

	//MUL myMul = (MUL)GetProcAddress(hDll, "CPPdll_mul");
	MUL myMul = (MUL)GetProcAddress(hDll, "?CPPdll_mul@@YAHHH@Z");
	cout << "myMul:" << myMul << endl;
	int mul = myMul(5,4);
	cout << "mul=" << mul << endl;

	FreeLibrary(hDll);
	system("pause");
	return 0;
}

为了使用不换名的函数名,重名生成导出动态库文件

Windows内核开发_第53张图片

Windows内核开发_第54张图片

Windows内核开发_第55张图片

Windows内核开发_第56张图片

Windows内核开发_第57张图片

#include 
#include 

using namespace std;

typedef int(*ADD)(int m, int n);
typedef int(*SUB)(int m, int n);
typedef int(*MUL)(int m, int n);

int main(){
	HINSTANCE hDll = LoadLibrary("CPPdll.dll");
	cout << "hDll:" << hDll << endl;

	ADD myAdd = (ADD)GetProcAddress(hDll, "CPPdll_add");
	//ADD myAdd = (ADD)GetProcAddress(hDll, "?CPPdll_add@@YAHHH@Z");
	cout << "myAdd:" << myAdd << endl;
	int sum = myAdd(5,4);
	cout << "sum=" << sum << endl;
	
	SUB mySub = (SUB)GetProcAddress(hDll, "CPPdll_sub");
	//SUB mySub = (SUB)GetProcAddress(hDll, "?CPPdll_sub@@YAHHH@Z");
	cout << "mySub:" << mySub << endl;
	int sub = mySub(5,4);
	cout << "sub=" << sub << endl;

	//MUL myMul = (MUL)GetProcAddress(hDll, "CPPdll_mul");
	MUL myMul = (MUL)GetProcAddress(hDll, "?CPPdll_mul@@YAHHH@Z");
	cout << "myMul:" << myMul << endl;
	int mul = myMul(5,4);
	cout << "mul=" << mul << endl;

	FreeLibrary(hDll);
	system("pause");
	return 0;
}

04 动态库中封装类

  • 在类名称前增加_declspec(dllexport)定义,例如:
class _declspec(dllexport) CMath{
	//...
};
  • 通常使用预编译开关切换类的导入导出定义,例如:
#ifdef DLLCLASS_EXPORTS
#define EXT_CLASS_declspec(dllexport)//DLL
#else
#define EXT_CLASS_declspec(dllimport)//使用者
#endif
class EXT_CLASS CMath{
	//...
};

注意:封装类动态库一般只要声明导出,而不用定义文件导出,因为导出类真正是导出类中封装的函数相对地址

示例:创建封装类的动态库
Windows内核开发_第58张图片Windows内核开发_第59张图片

Windows内核开发_第60张图片

#ifndef _DLLCLASS_H
#define _DLLCLASS_H

#ifdef DLLCLASS_EXPORTS
#define EXT_CLASS _declspec(dllexport)
#else
#define EXT_CLASS _declspec(dllimport)
#endif

class EXT_CLASS CMath{
public:
	int Add(int add1, int add2);
	int Sub(int sub1, int sub2);
};

#endif //_DLLCLASS_H

Windows内核开发_第61张图片

#define DLLCLASS_EXPORTS

#include "ClassDll.h"

int CMath::Add(int add1, int add2){
	return add1 + add2;
}

int CMath::Sub(int sub1, int sub2){
	return sub1 - sub2;
}

Windows内核开发_第62张图片
Windows内核开发_第63张图片

示例:调用封装好的动态库
Windows内核开发_第64张图片
Windows内核开发_第65张图片
Windows内核开发_第66张图片

#include 
#include "../ClassDll/ClassDll.h"

#pragma comment(lib, "../Debug/ClassDll.lib")

using namespace std;

int main(){
	CMath math;
	int sum = math.Add(5, 6);
	int sub = math.Sub(5, 6);
	cout << "sum=" << sum << ",sub=" << sub << endl;
	return 0;
}

Windows内核开发_第67张图片

你可能感兴趣的:(windows,c++,microsoft)