Windows编程05_对话框,静态库,动态库

01 对话框

普通窗口和对话框窗口:
在这里插入图片描述

  • 对话框的分类
    模式对话框 - 当对话框显示时,会禁止其他窗口和用户交互操作。
    无模式对话框 -在对画框显示后,其他窗口仍然可以和用户交互操作。
  • 对话框基本使用
    1.对话框窗口处理函数
    2.注册窗口类(不使用)
    3.创建对话框
    4.对话框的关闭
  • 对话框窗口处理函数(并非真正的对话框窗口处理函数)
    INT CALLBACK DialogProc(
    HWND hwndDlg, //窗口句柄
    UINT uMsg, //消息ID
    WPARAM wParam, //消息参数
    LPARAM lParam, //消息参数
    );
    返回TRUE -缺省处理函数不需要处理。
    返回FALSE -交给缺省处理函数处理。
    不需要调用缺省对话框处理函数。(系统自带)
    在这里插入图片描述

1.模式对话框

  • 创建对话框
    INT DialogBox(
    HINSTANCE hInstance, //应用程序实例句柄
    LPCTSTR lpTemplate, //对话框资源ID
    HWND hWndParent, //对话框父窗口
    DLGPROC lpDialogFunc //自定义函数
    );
    DialogBox是一个阻塞函数,只有当对话框关闭后,才会返回,继续执行后续代码。
    返回值是通过EndDialog设置。

  • 对话框的关闭
    BOOL EndDialog(
    HWND hDlg, //关闭的对话框窗口句柄
    INT_PTR nResult //关闭的返回值
    );
    关闭模式对话框,只能使用EndDialog,不能使用DestroyWindow等函数(只完成了EndDialog函数第一步关闭,第二部解除阻塞没做)。nResult是DialogBox函数退出时的返回值。

  • 对话框的消息
    WM_INITDIALOG -对话框创建之后显示之前,通过对户口窗口处理函数,可以完成自己的初始化相关的操作。

步骤1:
创建menu
在这里插入图片描述
步骤2:
创建对话框
在这里插入图片描述

#include<Windows.h>
#include<stdio.h>
#include"resource.h"

HINSTANCE g_hIns = 0;

INT CALLBACK DlgProc(HWND hhWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
	switch (msgID)
	{
	case WM_INITDIALOG:
		MessageBox(hhWnd, "WM_INITDIALOG", "Info", MB_OK);
		break;
	case WM_SYSCOMMAND:
		if (wParam == SC_CLOSE)
		{
			//销毁模式对话框
			EndDialog(hhWnd, 100);
		}
	}
	return FALSE;//将消息交给真正的对话框窗口处理函数的后续代码帮我们处理

}
void OnCommand(HWND hWnd, WPARAM wParam)
{
	switch (LOWORD(wParam))
	{
	case ID_MODEL:
		DialogBox(g_hIns, (char*)IDD_DIALOG1, hWnd, DlgProc);
	}
}

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_hIns = 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;
}

在这里插入图片描述

2.无模式对话框

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

  • 对话框的关闭
    关闭时使用DestroyWindow销毁窗口,不能使用EndDialog关闭对话框。

02 静态库

1.静态库特点

  • 运行不存在。
  • 静态库源码被链接到调用程序中。
  • 目标程序的归档。

2.C语言静态库

  • C静态库的使用
    1)创建一个静态库项目。
    2)添加库程序,源文件使用C文件。

步骤1:
在这里插入图片描述
步骤2:
在这里插入图片描述
步骤3:
Clib.c:

int Clib_add(int add1, int add2)
{
	return add1 + add2;
}

int Clib_sub(int sub1, int sub2)
{
	return sub1 - sub2;
}

步骤4:
编译:右键->生成
在这里插入图片描述

  • C静态库的使用
    库路径设置:可以使用pragma关键字设置
    #pragma comment(lib,“/lib/clib.lib”)

步骤5:
新建主函数
UseClib.c:

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

int main()
{
	int sum, sub;

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

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

在这里插入图片描述在这里插入图片描述

3.C++语言静态库

  • C++静态库的创建
    1)创建一个静态库项目
    2)添加库程序,源文件使用CPP文件。

CPPlib.cpp:

int CPPlib_add(int add1, int add2)
{
	return add1 + add2;
}

int CPPlib_sub(int sub1, int sub2)
{
	return sub1 - sub2;
}
  • C++静态库的使用
    库路径设置:可以使用pragma关键字设置
    #pragma comment(lib,“…/lib/cpplib.lib”)

UseCPPlib.cpp:

#include<iostream>
using namespace std;
int CPPlib_add(int add1, int add2);
int CPPlib_sub(int sub1, int sub2);
//以上代码给编译器看的
#pragma comment(lib,"../x64/Debug/CPPClib.lib")//?Clib_add@@YAHHH@Z
//给链接器看的
extern "C" int Clib_add(int add1, int add2);
extern "C" int Clib_sub(int sub1, int sub2);
#pragma comment(lib,"../x64/Debug/Clib.lib")//Clib_add /Clib_sub
int main()
{
	int sum = CPPlib_add(5, 4);//?Clib_add@@YAHHH@Z
	int stub = CPPlib_sub(5, 4);//?Clib_sub@@YAHHH@Z
	cout << "sum=" << sum << ",sub=" << stub << endl;
	sum = Clib_add(5, 3);//Clib_add
	stub = Clib_sub(5, 3);//Clib_sub
	cout << "sum=" << sum << ",sub=" << stub << endl;
}

在这里插入图片描述

03 动态库

1.动态库特点

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

2.动态库创建

  • 创建动态库项目
  • 添加库程序
  • 库程序导出 -提供给使用者库中的函数等信息。
    1)声明导出:使用_declspec(dllexport)导出函数。(会更改函数名称)
    注意:动态库编译链接后,也会有LIB文件,是作为动态库函数映射使用,与静态库不完全相同。
    2)模块定义文件.def (不会更改函数名称)
    例如:LIBRARY DLLFunc //库
    EXPORTS //库导出表
    DLL_MUL @1 //导出的函数

步骤1:
在这里插入图片描述
步骤2:
在这里插入图片描述
步骤2:
CPPdll.cpp

int CPPdll_add(int add1, int add2)
{
	return add1 + add2;
}

int CPPdll_sub(int sub1, int sub2)
{
	return sub1 - sub2;
}
int CPPdll_mul(int mul1, int mul2)
{
	return mul1 * mul2;
}

步骤3:
声明导出:

_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;
}

同步会生成lib
在这里插入图片描述
在这里插入图片描述

3.动态库的使用

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

1)头文件和函数原型
可以在函数原型的声明前,增加_declspec(dllimport)
2)导入动态库的LIB文件
3)在程序中使用函数
4)隐式链接的情况,dll文件可以存放的路径:
(1)与执行文件中同一个目录下
(2)当前工作目录
(3)Windows目录
(4)Windows/System32目录
(5)Windows/System
(6) 环境变量PATH指定目录

UseCPPdll.cpp:

#include<iostream>
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);
#pragma comment(lib,"../x64/Debug/CPPdll.lib")
//通知链接器到哪抓编号和dll文件名("CPPdll.lib")
int main()
{
	int sum = CPPdll_add(5, 4);//0 "CPPdll.lib"
	int sub = CPPdll_sub(5, 4);//1 "CPPdll.lib"
	int mul = CPPdll_mul(5, 4);//2 "CPPdll.lib"
	cout << "sum=" << sum << ",sub=" << sub << ",mul" << mul << endl;
}

在这里插入图片描述

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

1)定义函数指针类型 typedef
2)加载动态库
HMODULE LoadLibrary(
LPCTSTR lpFileName //动态库文件名或全路径
);返回DLL的实例句柄(HINSTANCE)
3)获取函数地址
FARPROC GetProcAddress(
HMODULE hModule, //DLL句柄
LPCSTR lpProcName //函数名称
);成功返回函数地址
4)使用函数
5)卸载动态库
BOOL FreeLibrary(
HMODULE hModule //DLL的实例句柄
);

CPPdll.cpp:

int CPPdll_add(int add1, int add2)
{
	return add1 + add2;
}

int CPPdll_sub(int sub1, int sub2)
{
	return sub1 - sub2;
}
_declspec(dllexport)int CPPdll_mul(int mul1, int mul2)
{
	return mul1 * mul2;
}

CPPdll.def:

LIBRARY	CPPDll
EXPORTS
	CPPdll_add @1
	CPPdll_sub @2

UseShow.cpp:

#include<Windows.h>
#include<iostream>
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(L"CPPDll.dll");
	cout << "hDll" << hDll << endl;

	//hDLL:获取首地址,第二个参数:相对地址
	ADD myAdd = (ADD)GetProcAddress(hDll, "CPPdll_add");
	cout << "myAdd:" << myAdd << endl;
	int sum = myAdd(5, 4);
	cout << "sum=" << sum << endl;

	SUB mySub = (SUB)GetProcAddress(hDll, "CPPdll_sub");
	cout << "mySub:" << mySub << endl;
	int sub = mySub(5, 4);
	cout << "sub=" << sub << endl;

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

	return 0;
}

4.动态库中封装类

  • 在类名称前增加_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{

    };
    注意:DLL中使用导入dllexport,使用者使用导入dllimport,使用此开关,便于在导入时导入,使用时导出。

ClassDll.h:


#ifndef _DLLCLASS_H
#define _DLLCLASS_H

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

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

#endif

ClassDll.cpp:


#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;
}

UseClassDll.cpp:

#include<iostream>
using namespace std;
#include "../ClassDll/ClassDll.h"
#pragma comment(lib,"../x64/Debug/ClassDll.lib")

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

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值