当前位置: 首页 > news >正文

Win32之菜单和库

 

    • 菜单

1.1 概念

  • 分类

1、静态菜单:在菜单资源编辑器预先编辑好

2、动态菜单:在程序运行的过程中通过代码生成

3、快捷菜单:是前两种菜单的组合,在菜单资源编辑器中预先编辑好,然后在程序运行的过程中动态显

  • 菜单项

菜单里面的每一个元素都是一个菜单项

菜单项包含两个最基本的要素:1、菜单项名字,2、该菜单项唯一的标识ID

每一个菜单项还可以是嵌套的子菜单数组

1.2 操作

c3926945b802ff2f82ea7070f9ae77d0.png

@1 点击资源文件中的”菜单和库.rc*"

c7914766a96791b623b8dd5edf31d004.png

@2 鼠标右击Menu->选择添加资源或者直接插入

92e95b78f580f3987d456b59be9d9120.png

然后就可以直接编辑了

 

01fcf349422dc0ddad462589735e40ed.png

这是vs的菜单栏 ,我们发现在菜单名后面有字母 起始这是快捷键

如果我们也要添加菜单快捷键 只要在编辑的时候在菜单名之后加上(&按键)即可 -----注意:括号为英文格式的括号,若要加载进窗口只需要在系统命令下 加入对应的条件就行了 先找到对应菜单项的ID

a22564fc95080a0c0a974614104ba311.png

 

2a109e25716dea3f29ab598dbf051b8a.png
bab4e86acf34879922eb881862fa4c90.png

在一个菜单项之后还可以编辑它的子菜单(但是实际开发中一般不超过三级菜单)

40453e461c68c3b3edb83d53a929e509.png
0e9cc6d3205c7dfd80facb64166187a2.png

我们发现在不同的菜单项中有分割线

一般是为了区分不同的功能类

我们想要实现只要在添加菜单项的时候输入‘-’(减号)即可

cf63911f3bc558970973817f35f86db8.png

 

 

 

在资源文件中编辑好了之后,我们还要把它加载到窗口中

有两种方式:

1、窗口类中加载菜单

8517ee53619ecccd13fa9ebec0a47ff6.png

 

在上图位置将默认的菜单名改为自己的菜单名

2、创建窗口时加载

在创建主窗口的函数中我们先获得一个菜单的句柄,然后再在CreateWindow函数的倒数第三的参数传入菜单句柄就行了

0c703eb7048e008e932cf2077bd0444a.png

不能把这条注释掉,为了验证第二种方法,把值改为nullptr就行了

a36e0101547d42bad68ed6600040ddc6.png

 

动态加载

学习怎么实现动态加载之前,我先给大家介绍几个函数

  1. CreateMenu()

参数

此函数无参数。

返回值

如果函数成功,则返回值是新建菜单的句柄。

如果函数失败,返回值为NULL。

  1. AppendMenu()

将一个新项目附加到指定的菜单栏,下拉菜单,子菜单或快捷菜单的末尾。您可以使用此函数指定菜单项的内容,外观和行为。

InsertMenuItem功能已被InsertMenuItem功能取代。但是,如果您不需要InsertMenuItem的任何扩展功能,您仍然可以使用AppendMenu.

BOOL AppendMenu(

HMENU 【HMENU】,

//处理要更改的菜单

UINT 【uFlags】,

//菜单项标志

UINT 【uIDNewItem】,

//菜单项标识符或下拉菜单或子菜单的句柄

LPCTSTR 【lpNewItem】

//菜单项内容即菜单项得名字

);

 

  1. InsertMenu()

将一个新的菜单项插入菜单,将其他项目向下移动到菜单中。

InsertMenuItem功能已被InsertMenuItem功能取代。但是,如果您不需要InsertMenuItem的任何扩展功能,您仍然可以使用InsertMenu.

BOOL InsertMenu(

HMENU 【HMENU】,

//菜单的句柄

UINT 【uPositionbs】,

//新菜单项前面的菜单项

UINT 【uFlags】,

//菜单项标志

UINT 【uIDNewItem】,

//菜单项标识符或下拉菜单或子菜单的句柄

LPCTSTR 【lpNewItem】

//菜单项内容

);

 

  1. EnableMenuItem

禁用或灰化指定的菜单项。

BOOL EnableMenuItem(

HMENU 【HMENU】,

//处理菜单的句柄

UINT 【uIDEnableItem】,

//菜单项启用,禁用或灰色

UINT 【uEnable】

//菜单项标志

);

 


//动态菜单:
HMENU hMenu1 = nullptr;
hMenu1 = CreateMenu();//创建了一个新菜单(空菜单)
HMENU h_1 = CreateMenu();
AppendMenu(h_1, //菜单句柄,指明在哪一个菜单的尾部进行追加
0, //菜单风格
10087, //菜单项id
_T("新建(&N)\t Ctrl+N"));//菜单项名
AppendMenu(h_1, MF_SEPARATOR, 0, _T("-"));
AppendMenu(h_1, 0, 10088, _T("打开(&O)\t Ctrl+O"));
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)h_1, _T("更多(&F)"));
HMENU h_2 = CreateMenu();
//第2个参数为坐标,该参数会受到第3个参数(MF_BYCOMMAND or MF_BYPOSITION)的影响
InsertMenu(h_2, 0, MF_BYPOSITION, 10089, _T("a"));
InsertMenu(h_2, 0, MF_BYPOSITION, 10090, _T("b"));
InsertMenu(h_2, 10089, MF_BYCOMMAND, 10091,_T("c"));
AppendMenu(hMenu, MF_POPUP, (UINT_PTR)h_2, _T("abc"));
//使菜单项是否变灰或是否激活
EnableMenuItem(h_1, 10087, MF_GRAYED);
EnableMenuItem(hMenu, 10087, MF_ENABLED);
EnableMenuItem(h_1, 0, MF_DISABLED | MF_BYPOSITION);
SetMenu(hWnd, hMenu1);//更新菜单,在窗口显示更新后修改要加
a6c19c72ccbd14857353f1ffbd7aee28.png

当我把上面这段代码加入之前的代码中之后效果如上图

注意到:多了两个菜单项 即h_1 h_2, abc菜单项项有三个子项 顺序为bca a是最先插入的但是在最下面 所以说明了使用InsertMenu()时上面的后插入,下面的先插入(当然这是默认的插入,没有指定下面的菜单项是谁,比如上面的c就指定了下面是a)

但是使用AppendMenu()时默认是先插入的在上面

 

运行效果如下

d90558db8ae5342f07344bdc83fbe355.png

 

 

 

右键菜单

1、在资源编辑器中编辑好新的右键菜单

2、初始化加载,可以在WM_CREATE内或者在主消息循环之前加载。(下面的演示代码是在窗口创建的时候加载的)

  1. 在WM_RBUTTONDOWN内可以响应



case WM_CREATE:g_hRMemu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU2));break;case WM_RBUTTONUP://鼠标右键抬起{
POINT pt;pt.x = LOWORD(lParam);pt.y = HIWORD(lParam);//把客户区坐标转为屏幕坐标ClientToScreen(hWnd, &pt);//从菜单中获取要弹出的分级菜单HMENU tempMenu = GetSubMenu(g_hRMemu, 0);//把g_hRMenu里面的0列表示的菜单给到tempMenu//弹出右键菜单TrackPopupMenu(tempMenu,//哪一个菜单TPM_LEFTALIGN | TPM_TOPALIGN,//菜单风格,对齐方式pt.x, pt.y,//鼠标坐标,菜单在哪个坐标开始显示0,hWnd,nullptr);}break;

客户区坐标:就是相对于我们打开的窗口的左上角的坐标

屏幕坐标:相对于电脑屏幕左上角的坐标

我们直接用lParam获取的是客户区坐标 但是TrackPopupMenu这个弹出菜单的函数里的参数是屏幕坐标所以我们要用 ClientToScreen转换一下

a967e0b33e1163c309e45f944cdd34fd.png

 

以上源文件的所有代码如下:


// 菜单和库.cpp : 定义应用程序的入口点。
//#include "stdafx.h"
#include "菜单和库.h"#define MAX_LOADSTRING 100// 全局变量: 
HINSTANCE hInst;                                // 当前实例
TCHAR szTitle[MAX_LOADSTRING];                    // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名
HMENU g_hRMemu = nullptr;                       //右键菜单
// 此代码模块中包含的函数的前向声明: 
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInstance,_In_ LPTSTR    lpCmdLine,_In_ int       nCmdShow)
{UNREFERENCED_PARAMETER(hPrevInstance);UNREFERENCED_PARAMETER(lpCmdLine);// TODO:  在此放置代码。MSG msg;HACCEL hAccelTable;// 初始化全局字符串LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);LoadString(hInstance, IDC_MY, szWindowClass, MAX_LOADSTRING);MyRegisterClass(hInstance);// 执行应用程序初始化: if (!InitInstance (hInstance, nCmdShow)){return FALSE;}hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_MY));// 主消息循环: while (GetMessage(&msg, NULL, 0, 0)){if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)){TranslateMessage(&msg);DispatchMessage(&msg);}}return (int) msg.wParam;
}//
//  函数:  MyRegisterClass()
//
//  目的:  注册窗口类。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{WNDCLASSEX wcex;wcex.cbSize = sizeof(WNDCLASSEX);wcex.style            = CS_HREDRAW | CS_VREDRAW;wcex.lpfnWndProc    = WndProc;wcex.cbClsExtra        = 0;wcex.cbWndExtra        = 0;wcex.hInstance        = hInstance;wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MY));wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);wcex.lpszMenuName = nullptr;wcex.lpszClassName    = szWindowClass;wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));return RegisterClassEx(&wcex);
}//
//   函数:  InitInstance(HINSTANCE, int)
//
//   目的:  保存实例句柄并创建主窗口
//
//   注释: 
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{HWND hWnd;hInst = hInstance; // 将实例句柄存储在全局变量中HMENU hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, hMenu, hInstance, NULL);//动态菜单:HMENU hMenu1 = nullptr;hMenu1 = CreateMenu();//创建了一个新菜单(空菜单)HMENU h_1 = CreateMenu();AppendMenu(h_1, //菜单句柄,指明在哪一个菜单的尾部进行追加0, //菜单风格10087, //菜单项id_T("新建(&N)\t Ctrl+N"));//菜单项名AppendMenu(h_1, MF_SEPARATOR, 0, _T("-"));AppendMenu(h_1, 0, 10088, _T("打开(&O)\t Ctrl+O"));AppendMenu(hMenu, MF_POPUP, (UINT_PTR)h_1, _T("更多(&F)"));HMENU h_2 = CreateMenu();//第2个参数为坐标,该参数会受到第3个参数(MF_BYCOMMAND or MF_BYPOSITION)的影响InsertMenu(h_2, 0, MF_BYPOSITION, 10089, _T("a"));InsertMenu(h_2, 0, MF_BYPOSITION, 10090, _T("b"));InsertMenu(h_2, 10089, MF_BYCOMMAND, 10091, _T("c"));AppendMenu(hMenu, MF_POPUP, (UINT_PTR)h_2, _T("abc"));HMENU h_3 = CreateMenu();HMENU h_4 = CreateMenu();AppendMenu(h_3, MF_POPUP, (UINT)h_4, _T("菜单选项一"));AppendMenu(h_3, 0, 1001, _T("菜单选项二"));AppendMenu(h_3, 0, 1002, _T("菜单选项三"));AppendMenu(h_3, 0, 1003, _T("菜单选项四"));AppendMenu(hMenu, MF_POPUP, (UINT)h_3, _T("选项"));//    MF_POPUP指定菜单项打开下拉菜单或子菜单   第三个参数就是子菜单项的菜单句柄AppendMenu(h_4, 0, 2000, _T("小黑子"));AppendMenu(h_4, 0, 2001, _T("IKUN"));//使菜单项是否变灰或是否激活EnableMenuItem(h_1, 10087, MF_GRAYED);// EnableMenuItem(hMenu, 10087, MF_ENABLED);//  EnableMenuItem(h_1, 0, MF_DISABLED | MF_BYPOSITION);// SetMenu(hWnd, hMenu1);//更新菜单,在窗口显示更新后修改要加if (!hWnd){return FALSE;}ShowWindow(hWnd, nCmdShow);UpdateWindow(hWnd);return TRUE;
}//
//  函数:  WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的:    处理主窗口的消息。
//
//  WM_COMMAND    - 处理应用程序菜单
//  WM_PAINT    - 绘制主窗口
//  WM_DESTROY    - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{int wmId, wmEvent;PAINTSTRUCT ps;HDC hdc;switch (message){case WM_CREATE:g_hRMemu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU2));break;case WM_RBUTTONUP:{
POINT pt;pt.x = LOWORD(lParam);pt.y = HIWORD(lParam);//把客户区坐标转为屏幕坐标ClientToScreen(hWnd, &pt);//从菜单中获取要弹出的分级菜单HMENU tempMenu = GetSubMenu(g_hRMemu, 0);//把g_hRMenu里面的0列表示的菜单给到tempMenu//弹出右键菜单TrackPopupMenu(tempMenu,//哪一个菜单TPM_LEFTALIGN | TPM_TOPALIGN,//菜单风格,对齐方式pt.x, pt.y,//鼠标坐标,菜单在哪个坐标开始显示0,hWnd,nullptr);}break;case WM_COMMAND:wmId    = LOWORD(wParam);wmEvent = HIWORD(wParam);// 分析菜单选择: switch (wmId){case 1234:MessageBox(hWnd,_T("你干嘛~"), _T("帮助"), MB_OK);case IDM_ABOUT:DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);break;case IDM_EXIT:DestroyWindow(hWnd);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}break;case WM_PAINT:hdc = BeginPaint(hWnd, &ps);// TODO:  在此添加任意绘图代码...EndPaint(hWnd, &ps);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hWnd, message, wParam, lParam);}return 0;
}// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{UNREFERENCED_PARAMETER(lParam);switch (message){case WM_INITDIALOG:return (INT_PTR)TRUE;case WM_COMMAND:if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL){EndDialog(hDlg, LOWORD(wParam));return (INT_PTR)TRUE;}break;}return (INT_PTR)FALSE;
}

2.库

 

静态库

静态库是指我们的应用中,有一些公共代码是需要反复使用,就把这些代码编译为“库”,理解为“仓库”,

在“仓库”中存储了很多东西,每次再要使用时只需要去“仓库”拿就可以了。

程序有“预处理”->“编译”->“链接”这几个步骤。静态库就不需要再次编译,只需要在“链接”步骤中,链接器

将从“仓库”的文件中取得所需的代码,复制到生成的可执行文件中即可。

动态库

动态库又称动态链接库。英文“dll”,是“Dynamic Link Library”的缩写形式。

DLL是一个包含可由多个程序同时使用的代码和数据的库。

DLL不是可执行文件。

动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。

函数的可执行代码位于一个DLL中,该DLL包含一个或多个已被编译、链接并与使用它们的进程分开存储

的函数。

DLL还有助于共享数据和资源。多个应用程序可同时访问内存中单 个DLL副本的内容。

windows下动态库为.dll后缀。

linux下为.so后缀。

静态库和动态库的区别

1、静态库在程序的链接阶段被复制到了程序中,和程序运行的时候没有关系。

2、动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。

优点

使用静态库的优点:

1、代码装载速度快,执行速度略比动态链接库快

2、发布程序时不需考虑在用户的计算机上.LIB文件是否存在及版本问题

使用动态库的优点:

1、更加节省内存并减少页面交换

2、dll文件和exe文件独立,只要输出接口不变(即名称、参数、返回值类型和调用约定不变),更换

DLL文件不会对EXE文件造成任何影响,因而极大地提高了可维护性和可扩展性

3、不同编程语言编写的程序只要按照函数调用约定就可以调用同一个DLL函数

4、适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和

测试。不足之处

1、使用静态链接生成的可执行文件体积较大,包含相同的公共代码,造成浪费

2、使用动态链接库的应用程序不是自完备的,它依赖的DLL模块也要存在,如果使用载入时动态链接,

程序启动时发现DLL不存在,系统将终止程序并给出错误信息。而使用运行时动态链接,系统不会终

止,但由于DLL中的导出函数不可用,程序会加载失败;速度比静态链接慢。当某个模块更新后,如果

新模块与旧的模块不兼容,那么那些需要该模块才能运行的软件,统统撕掉。这在早期Windows中很常

注意:不管是静态库还是动态库,都能实现共享代码。只不过是有没有被包含到exe文件中而已。

静态库、动态库文件关系

静态库和动态库中会需要 一些文件。主要用到以下3类中的文件。

1、.h文件。编译时必须的,声明函数接口用

2、.lib文件。链接时需要的,当我们在程序中引用了一个.h文件里面的函数,链接器怎么知道要调用哪

个dll文件呢,这就是lib文件的作用。它告诉链接器调用的函数在哪个dll中,函数执行代码在dll中的什么

位置。

注意:如果是生成静态库文件,没有dll文件,这个时候函数的可执行代码部分也在lib文件中。所以在链

接时就能直接链接进exe文件。

3、.dll文件。运行时需要的,函数的可执行代码

静态库只用到前两种,动态库用到了所有的三种。

注意:附加依赖项添加的是.lib而不是.dll,若生成了dll,则肯定也生成了lib文件 。

静态库示例

1、创建一个”WIN32“项目,”win32控制台“或”win32项目“。

2、选择”静态库“。

3、新建一个.h文件。

然后在这个.h文件中进行如下代码编写:

4、添加cpp文件。

#ifndef __MYTOOLS_H__ //如果没有定义宏名

#define __MYTOOLS_H__ //定义宏名

extern "C" int MyAdd(int num1, int num2);//实现两个数相加

extern "C" int MySub(int num1, int num2);//实现两个数相减

#endif //结束预处理5、编译生成解决方案。

导入lib文件

动态库示例

1、创建”WIN32“项目,”win32控制台“或”win32项目“。

2、选择”DLL“。

3、添加头文件”MyDll.h“:

4、添加源文件”MyDll.cpp“:

  1. 编译生成解决方案。


#include "stdafx.h"
#include "MyTools.h"
int MyAdd(int num1, int num2)
{
return num1 + num2;
}
int MySub(int num1, int num2)
{
return num1 - num2;
}#pragma comment(lib,"某某.lib")//第二个参数为拷贝到这个新工程中的.lib文件的全称
#ifndef __MYDLL_H__
#define __MYDLL_H__
extern "C" _declspec(dllexport) void MyFun(int op1,int op2);
#endif
#include "stdafx.h"
#include <stdio.h>
#include "MyDll.h"
void MyFun(int op1, int op2)
{
for (int i = 1; i <= op1; ++i)
{
for (int j = i; j <= op2; ++j)
{
printf("%d * %d = %d\t",j,i,j * i);
}
printf("\n");
}
}

6、在”dll项目“中有它的入口函数的。有一个dllmain.cpp。这里面有一个动态库的入口函数。DllMain函

数,一般这个函数不用。它只是一个可选的入口函数。里面第二个参数的switch分支用来表示”系统何时

调用了DllMain

 

静态库

静态库是指我们的应用中,有一些公共代码是需要反复使用,就把这些代码编译为“库”,理解为“仓库”,

在“仓库”中存储了很多东西,每次再要使用时只需要去“仓库”拿就可以了。

程序有“预处理”->“编译”->“链接”这几个步骤。静态库就不需要再次编译,只需要在“链接”步骤中,链接器

将从“仓库”的文件中取得所需的代码,复制到生成的可执行文件中即可。

动态库

动态库又称动态链接库。英文“dll”,是“Dynamic Link Library”的缩写形式。

DLL是一个包含可由多个程序同时使用的代码和数据的库。

DLL不是可执行文件。

动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。

函数的可执行代码位于一个DLL中,该DLL包含一个或多个已被编译、链接并与使用它们的进程分开存储

的函数。

DLL还有助于共享数据和资源。多个应用程序可同时访问内存中单 个DLL副本的内容。

windows下动态库为.dll后缀。

linux下为.so后缀。

静态库和动态库的区别

1、静态库在程序的链接阶段被复制到了程序中,和程序运行的时候没有关系。

2、动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。

优点

使用静态库的优点:

1、代码装载速度快,执行速度略比动态链接库快

2、发布程序时不需考虑在用户的计算机上.LIB文件是否存在及版本问题

使用动态库的优点:

1、更加节省内存并减少页面交换

2、dll文件和exe文件独立,只要输出接口不变(即名称、参数、返回值类型和调用约定不变),更换

DLL文件不会对EXE文件造成任何影响,因而极大地提高了可维护性和可扩展性

3、不同编程语言编写的程序只要按照函数调用约定就可以调用同一个DLL函数

4、适用于大规模的软件开发,使开发过程独立、耦合度小,便于不同开发者和开发组织之间进行开发和

测试。不足之处

1、使用静态链接生成的可执行文件体积较大,包含相同的公共代码,造成浪费

2、使用动态链接库的应用程序不是自完备的,它依赖的DLL模块也要存在,如果使用载入时动态链接,

程序启动时发现DLL不存在,系统将终止程序并给出错误信息。而使用运行时动态链接,系统不会终

止,但由于DLL中的导出函数不可用,程序会加载失败;速度比静态链接慢。当某个模块更新后,如果

新模块与旧的模块不兼容,那么那些需要该模块才能运行的软件,统统撕掉。这在早期Windows中很常

注意:不管是静态库还是动态库,都能实现共享代码。只不过是有没有被包含到exe文件中而已。

静态库、动态库文件关系

静态库和动态库中会需要 一些文件。主要用到以下3类中的文件。

1、.h文件。编译时必须的,声明函数接口用

2、.lib文件。链接时需要的,当我们在程序中引用了一个.h文件里面的函数,链接器怎么知道要调用哪

个dll文件呢,这就是lib文件的作用。它告诉链接器调用的函数在哪个dll中,函数执行代码在dll中的什么

位置。

注意:如果是生成静态库文件,没有dll文件,这个时候函数的可执行代码部分也在lib文件中。所以在链

接时就能直接链接进exe文件。

3、.dll文件。运行时需要的,函数的可执行代码

静态库只用到前两种,动态库用到了所有的三种。

注意:附加依赖项添加的是.lib而不是.dll,若生成了dll,则肯定也生成了lib文件 。

静态库示例

1、创建一个”WIN32“项目,”win32控制台“或”win32项目“。

2、选择”静态库“。

3、新建一个.h文件。

然后在这个.h文件中进行如下代码编写:

  1. 添加cpp文件。


#ifndef __MYTOOLS_H__ //如果没有定义宏名
#define __MYTOOLS_H__ //定义宏名
extern "C" int MyAdd(int num1, int num2);//实现两个数相加
extern "C" int MySub(int num1, int num2);//实现两个数相减
#endif //结束预处理5、编译生成解决方案。
导入lib文件

动态库示例

1、创建”WIN32“项目,”win32控制台“或”win32项目“。

2、选择”DLL“。

3、添加头文件”MyDll.h“:

4、添加源文件”MyDll.cpp“:

  1. 编译生成解决方案。


#include "stdafx.h"
#include "MyTools.h"
int MyAdd(int num1, int num2)
{
return num1 + num2;
}
int MySub(int num1, int num2)
{
return num1 - num2;
}#pragma comment(lib,"某某.lib")//第二个参数为拷贝到这个新工程中的.lib文件的全称
#ifndef __MYDLL_H__
#define __MYDLL_H__
extern "C" _declspec(dllexport) void MyFun(int op1,int op2);
#endif
#include "stdafx.h"
#include <stdio.h>
#include "MyDll.h"
void MyFun(int op1, int op2)
{
for (int i = 1; i <= op1; ++i)
{
for (int j = i; j <= op2; ++j)
{
printf("%d * %d = %d\t",j,i,j * i);
}
printf("\n");
}
}

6、在”dll项目“中有它的入口函数的。有一个dllmain.cpp。这里面有一个动态库的入口函数。DllMain函

数,一般这个函数不用。它只是一个可选的入口函数。里面第二个参数的switch分支用来表示”系统何时

调用了DllMain

 

 

http://www.lryc.cn/news/571004.html

相关文章:

  • Windows编程 DirectSound DirectMusic 音效和音乐
  • 基础RAG实现,最佳入门选择(一)
  • 学计算机高中应选什么科目,新高考选哪些科目可以报计算机?高中生如何进步?...
  • 搭建游戏用什么类型的服务器更好
  • 分享一键群发各大博客社区平台的工具
  • 存储器的分类(RAM,ROM等)及其性能指标
  • HTC Incredible S G11如何刷recovery,如何获得root权限,如何删除预装的系统应用
  • 李开复给中国学生的第四封信
  • 深圳学区房地图
  • DAY 54 Inception网络及其思考
  • 人物点评: 马云的野心(zz)
  • 狱搜导航-个性化导航自定义导航网站,搜索导航,简洁清晰大气,支持各种自定义
  • 中国第二大传感器企业宝座易主!14家公司新上市!国产传感器风起云涌!(附最新市值排名榜单)
  • Codeigniter 4基础教程(1)-- Wamp+CodeIgniter 4以及helloworld
  • 计算机主机漏电,电脑主机箱漏电六大原因和解决方法
  • Windows安装与配置Git cz (commitizen)
  • 包含15个APP客户端UI界面的psd适用于餐厅咖啡店面包店快餐店
  • d3dx9_42.dll丢失的解决方法-d3dx9_42.dll缺失下载方法
  • InstallShield 2010打包安装程序,安装完成后执行某个程序
  • 送两本《ECharts数据可视化:入门、实战与进阶》
  • 蓝屏错误代码0x0000007E的解决方法及编程示例
  • linux内核(二)内核移植(DM365-DM368开发攻略——linux-2.6.32的移植)
  • Internet Explorer 已不再尝试还原此网站。该网站看上去仍有问题。
  • 关于部分网页打不开的解决方法详解
  • 学生学籍管理系统页面源代码html_110.188.251:8088四川大学锦江学院教务管理系统...
  • 盗版xp成功验证成正版,享受正版增值服务!—— 完美解决XP被黑和盗版提示
  • 英语学习漫谈
  • 导航条——flash导航条
  • 音频毒品
  • 002微信小程序模板与配置