win32第十三天

一、多文档界面(MDI)
1.MDI的组成
MDI主窗口(主框架窗口MainFrame)
   MDI客户窗口(MDICLIENT)
      MDI子窗口1
      MDI子窗口2
      ...
2.创建过程
1)创建MDI主窗口
A.没有父窗口,需要注册窗口类,定义窗口过程函数
B.MDI主窗口的窗口过程函数,不再调用DefWindowProc,代之以调用DefFrameProc
这个函数多了一个参数。
LRESULT DefFrameProc (
  HWND hWnd,
  HWND hWndMDIClient, // MDI客户窗口句柄
  UINT    uMsg,
  WPARAM wParam,
  LPARAM LParam
);
2)创建MDI客户窗口
A.窗口类:MDICLIENT
B.父窗口是MDI主窗口
C.创建时需要使用CLIENTCREATESTRUCT结构,指定MDI子窗口的起始ID。
3)创建MDI子窗口
A.父窗口是MDI客户窗口
B.MDI子窗口需要注册并定义窗口过程函数
C.MDI子窗口的窗口过程函数,不再调用DefWindowProc,代之以调用DefMDIChildProc
创建出一个MDI//
工程名:WinMDI
在一个SDI的基础上改成MDI.
1.加载图标资源,应用程序IDI_WINMDI,显示文字的小窗口IDI_TEXT,显示图像的小图片IDI_GRAPH
2.添加菜单资源。文件分文本(IDM_FILE_TEXT打开文本的那个小窗口),图形(IDM_FILE_GRAPH找开显示图形的那个窗口)。退出(IDM_FILE_EXIT).复制出两个子窗口的菜单。IDR_MENU_TEXT.IDR_MENU_GRAPH
3.
#define ID_FIRST_CHILD 10001
LPCSTR g_pszTextWndClass="TEXT";
LPCSTR g_pszGraphWndClass="GRAPH";
LPCSTR g_pszTextWndTitle="文本";
LPCSTR g_pszGraphWndTitle="图形";
HWND g_hwndMain=NULL;
HWND g_hwndMDI=NULL;
HMENU g_hmenuMain=NULL;
HMENU g_hmenuText=NULL;
HMENU g_hmenuGraph=NULL;
创建客户区窗口
case WM_CREATE:
{
CLIENTCREATESTRUCT ccs;
ccs.idFirstChild=ID_FIRST_CHILD;
g_hwndMDI=CreateWindowEx(WS_EX_CLIENTEDGE,"MDICLIENT",NULL,WS_CHILD|WS_VISIBLE|WS_CLIPCHILDREN,CW_USEDFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDFAULT,hWnd,NULL,g_hInstance,&ccs);
}
return DefFrameProc(hWnd,g_hwndMDI,uMsg,wParam,lParam);
///
//文字窗口消息处理函数
LRESULT CALLBACK TextWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
case WM_PAINT:{
PAINTSTRUCT ps;
HDC hDC=BeginPaint(hWnd,&ps);
RECT rcClient;
GetClientRect(hWnd,&rcClient);
LPCSTR pszText="this is a mdi child window";
DrawText(hDc,pszText,strlen(pszText),&rcClient,DT_SINGLELINE|DT_CENTER|DT_VCENTER);
EndPaint(hWnd,&ps);
}
return DefMDIChildProc(hWnd,uMsg,wParam,lParam);
}
//图形窗口消息处理函数
LRESULT CALLBACK GraphWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam){
case WM_PAINT:
PAINTSTRUCT ps;
HDC hDC=BeginPaint(hWnd,&ps);


EndPaint(hWnd,&ps);
return DefMDIChildProc(hWnd,uMsg,wParam,lParam);
}

//主窗口类中
wcex.hIcon=LoadIcon(g_hInstance,MAKEINTRESOURCE(IDI_WINMDI));
wcex.hIconSm=LoadIcon(g_hInstance,MAKEINTRESOURCE(IDI_WINMDI));
//空刷子
wcex.hbrBackground=(HBRUSH)GetStockObject(HOLLOW_BRUSH);
if(!registerClassEx(&wcex))
return FALSE;
wcex.lpfnWndProc=TextWndProc;
wcex.hIconSm=LoadIcon(g_hInstance,MAKEINTRESOURCE(IDI_TEXT));
wcex.hbrBackground=GetSyscolorBrush(COLOR_WINDOW);
wcex.lpszClassName=g_pszTextWndClass;
if(!registerClassEx(&wcex))
return FALSE;
//注册图形窗口
wcex.lpfnWndProc=GraphWndProc;
wcex.hIconSm=LoadIcon(g_hInstance,MAKEINTRESOURCE(IDI_GRAPH));
wcex.hbrBackground=GetSyscolorBrush(COLOR_WINDOW);
wcex.lpszClassName=g_pszGraphWndClass;
if(!registerClassEx(&wcex))
return FALSE;
g_hmenuMain=LoadMenu(g_hInstance,MAKEINTRESOURCE(IDR_MENU_MAIN);
g_hmenuText=LoadMenu(g_hInstance,MAKEINTRESOURCE(IDR_MENU_Text);
g_hmenuGraph=LoadMenu(g_hInstance,MAKEINTRESOURCE(IDR_MENU_GRAPH);
///
case WM_COMMAND:
switch(LOWORD(wParam)){
case IDM_FILE_TEXT:
CreateWindowEx(WS_EX_clieNTEDGE|WS_EX_MDICHILD,g_psztextWndClass,g_psztextWndTitle,WS_CHILD|WS_VISIBLE,CW_USEDFAULT,CW_USEDFAULT,CW_USEDFAULT,CW_USEDFAULT,g_hwndMDI,NULL,g_hInstance,NULL);
return 0;
}
如法复制出图形窗口//
//当每个子窗口显示的时候菜单变成该子窗口的菜单//
文字窗口
case WM_MDIACTIVATE:
if(lParam==(LPARAM)hWnd)//激活
SendMessage(g_hwndMDI,WM_MDISETMENU,(WPARAM)g_hmenuText,0);
else
SendMessage(g_hwndMDI,WM_MDISETMENU,(WPARAM)g_hmenuMain,0);
//把菜单重刷一下
DrawMenuBar(g_hwndMain);
return 0;
///在子窗口上菜单点击关闭消息处理写在主窗口函数中
case IDM_FILE_CLOSE:
SendMessage(g_hwndMDI,WM_MDIDESTROY,SendMesage(g_hwndMDI,WM_MDIGETACTIVE,0,0),0);
return 0;
case IDM_FILE_EXIT:
PostMessage(hWnd,WM_CLOSE,0,0);
return 0;
//层叠
case IDM_WINDOW_CASCADE:
SendMessage(g_hwndMDI,WM_MDICASCADE,0,0);
return 0;
//平铺
case IDM_WINDOW_TILE:
SendMessage(g_hwndMDI,WM_MDITILE,0,0);
return 0;
//排列
case IDM_WINDOW_MDICONARRANGE:
SendMessage(g_hwndMDI,WM_MDICONARRANGE,0,0);
return 0;
//全部关闭
case IDM_WINDOW_CLOSEALL:
EnumChildWindows(g_hwndMDI,closeProc,0);
return 0;
BOOL CALLBACK closeProc(hWnd,LPARAM lParam){
SendMessage(g_hwndMDI,WM_MDIDESTROY,(WPARAM)hWnd,0);
return true;
}
所有的命令消息只会发给主窗口不会发给子窗口,如菜单命令。子窗口处理函数没办法处理。
default:
{
HWND hwndChild=(HWND)SendMessage(g_hwndMDI,WM_MDIGETACTIVATE,0,0);
if(IsWindow(hwndChild))
SendMessage(hwndChild,WM_COMMAND,wParam,lParam);
break;
}

使用MDI有些子窗口不能使用静态变量,哪些东西是不能共享的。只能使用动态分配,一个实例一份。定义一个结构体,用的时候动态分配。把指针放在窗口附加数据中。用的时候拿出来再用。MFC是用类来解决这个问题。一个子窗口类可以创建出多个子窗口,有些东西 是不能共享的。
二、库
1.分类
1)静态库:运行时不依赖,其中的代码在链接阶段被复制到可执行程序中,其本质就是目标文件(.obj)的归档,扩展名为.lib。
2)动态库:运行时依赖,其中代码在链接阶段不被复制到可执行程序中,扩展名为.dll。
如果是装的vs企业版的话,点右键会看到dll库中的内容。dependency walker。而kernel.lib,user32.lib,gdi32.lib是在VC里面,而不是在system32中。是一个导入库,不是静态库。
2.静态库
所有的Win32函数都没有静态库版本。标准C/C++函数既有静态库版本也有动态库版本,可以在工程选项中配置。
1)创建静态库
工程名(Win32 Static Library)Clib
添加CLib.c<想封装的各种函数>
int c_add(int a,int b){
return a+b;
}
int c_sub(int a,int b){
return a-b;
}
//为了使用方面 ,在提供库的时候提供头文件给别人用。可以不包含,建议包含在实现文件中,以防出错。可以在编译环境中更改dll输出文件的位置。
#ifdef _CLIB_H
#define _CLIB_H
int c_add(int a,int b);
int c_sub(int a,int b);
#endif /* _CLIB_H
创建一个使用库的工程
UseCLib
#include<stdio.h>
#include "../Clib/Clib.h"
int main(void){
int a,b;
printf("请输入两个整数:");
scanf("%d%d",&a,&b);
printf("%d+%d=%d\n",a,b,c_add(a,b));
printf("%d-%d=%d\n",a,b,c_sub(a,b));
}
上述链接会出错,一种方法在工程中把clib.lib文件加到链接库中。第二种方法如下都有。
A.创建新项目
B.添加源文件
C.编写库代码
2)链接静态库
A.#pragma comment (lib, "../Lib/CLib.lib")
B.通过Project/Settings...设置,添加../Lib/CLib.lib
C -> C
//下面试一下CPP调用CPP的
CPP -> CPP
//CPP调用C的库
CPP -> C,为了防止C++编译器对C语言库函数做换名,应该加上extern "C"
extern "C"{
#include"../Clib/Clib.h"
}
C -> CPP
让生成C++库的时候不做换名。在CPP库的头文件中加extern "C"
#ifnedf _CPPLIB_H
#define _CPPLIB_H
#ifdef __cplusplus
extern "C"{
#endlif
int cpp_add(int a,int b);
int cpp_sub(int a,int b);
#ifdef __cplusplus
}
#endif
#endif
3.动态库
1)创建动态库
A.创建新项目
B.添加源文件
C.编写库代码
Win32 Dynamic-Link Library  (cDLL)
添加cDLL.c
int c_mul(int a,intb){
return a*b;
}
itn c_div(int a,int b){
return a/b;
}
添加头文件声明一下,cDLL.h
#ifnedf _CDLL_H
#define _CDLL_H
__declspec (dllexport) int c_mul(int a,int b);
__declspec (dllexport) int c_div(int a,int b);
#endif
///更改输出文件
导入库的文件输出也更改一下。声明导出以后则会生成cDLL.lib导出库。
UserCDLL工程
UserCDLL.c
#include<stdio.h>
#include "../CDLL/CDLL.h"
#pragma comment(lib,"../Lib/CDLL.lib")
int main(void){
int a,b;
printf("请输入两个整数:");
scanf("%d%d",&a,&b);
printf("%d+%d=%d\n",a,b,c_mul(a,b));
printf("%d-%d=%d\n",a,b,c_div(a,b));
}
dll必须和exe位于同一个目录下,否则会运行出错。装一个企业版也可以查看exe文件当中的依赖关系。
写库一方用导出,用库的人用导入。为些需要用宏开关控制.h头文件中的声明。
#ifdef CDLL_EXPORTS
#define CDLL_API __declspec(dllexport)
#else
#define CDLL_API __declspec(dllimport)
CDLL_API int c_mul(int a,int b);
#endif
C++当中
#ifnedf _CPPDlL_H
#define _CPPDLL_H
#ifdef CPPDLL_EXPORTS
#define CPPDLL_API _declspec(dllexport)
#else
#define CPPDLL_API _declspec(dllimport)
#endif


4.导出
1)声明导出,在函数声明前加_declspec (dllexport)前缀,如果无声明则加在函数定义之前。
2)模块定义文件导出:.def比较早的时候使用def文件导出。
EXPORTS 
hello
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值