• Windows程序设计5(MDI、库程序、文件)


     

    1、 多文档界面(MDI)

    1. MDI的组成

    MDI主窗口(主框架窗口MainFrame

    MDI客户窗口(MDICLIENT

    MDI 子窗口1

    MDI 子窗口2

    …….

    1. 创建过程

    1)创建MDI主窗口

        a) 没有父窗口,需要注册窗口类,定义窗口过程函数

    b) MDI主窗口的窗口过程函数,不再调用DefWindowProc。代之以调用DefFramProc

      LRESULT   DefFrameProc(

      HWND  hWnd,           // handle to MDI frame window

      HWND  hWndMDIClient,  // handle to MDI client window

      UINT  uMsg,           // message

      WPARAM  wParam,       // first message parameter

      LPARAM  lParam        // second message parameter

    );

    2) 创建MDI客户窗口

    A. 窗口类:MDI主窗口

    B.父窗口是MDI主窗口

    C.创建时需要使用CLIENTCREATRUCT结构,指定MDI子窗口的起始ID

    3)创建MDI子窗口

    A. 父窗口是MDI客户窗口

    B.所有的MDI子窗口都需要注册并定义窗口过程函数

    CMDI子窗口的窗口函数过程函数,不再调用DefWindProc。代之以调用DefMDIChildProc

    4)相关函数:

    DrawMenuBar(HWND hwnd);//重绘指定窗口菜单栏,用于切换多文档时刷新重绘相应菜单栏。

    EnumChildWindows();//枚举指定窗口的所有子窗口执行lpEnumFunc回调函数。

    BOOL  EnumChildWindows(

       HWND   hWndParent,         // handle to parent window

       WNDENUMPROC  lpEnumFunc,  // pointer to callback function

       LPARAM   lParam            // application-defined value

    );

    SetWindowLong/ GetWindowLong;

    IsWindow;等等

    5)消息相关:

    WM_MDIACTIVATE

    WM_MDIDESTROY

    WM_MDIGETACTIVE

    WM_MDICASCADE

    WM_MDITILE

    WM_MDIICONARRANGE

    2、 Windows库程序

    1. 分类:

    静态库程序 - 运行时不依赖,在链接阶段会被链接到可执行文件或者动态库中,本质是目标文件程序的归档。文件扩展名:LIB

     

    动态库程序 - 运行时依赖,在链接阶段不会被复制到可执行文件或其他动态库中。文件扩展名:DLL

     

    1. 静态库程序

    所有的win32函数都没有静态库版本,但标准C/C++函数既有静态库也有动态库版本。可以在工程选项中配置。

    C语言静态库

    1 静态库的使用

    建立一个C文件,可以在文件中直接使用C库函数,不需要头文件。C编译器只是根据库函数名称,在库中找到对应的函数代码,进行链接。

    2 静态库的创建

    1)建项目

    2)添加库程序(),编写源文件代码使用C文件

    3 链接静态库的路径设置

    1)项目的“project/ Setting”中设置库的路径

    2)可以使用pragma关键字设置#pragma comment( lib, "..\lib\clib.lib")(指定路径)

    C++语言的静态库

    1. 静态库的建立

    1)建立项目

    2)添加库程序,源文件使用CPP文件

    2. 库的导入

    1)项目的“Setting”中设置库的路径

    2)可以使用 pragma 关键字设置

    3. 注意

    CPP环境使用C静态库,库中函数原型定义要增加 extern “C”, 例如:extern "C" int Add(... ); extern “C” {#include “myc.h”}.等。防止C++编译器对C语言库函数做换名,使得采用C下的函数原型,正确调用C库函数。C中使用C++库时,需要在C++库编译时,对extern “C” {  } c++编译器宏#ifdef _ _cplusplus 来处理(由于C语言中无法识别 extern "C"  串。)。使得可对C编译器与C++编译器公用。

    如:#ifdef  __cplusplus  

    extern "C" {

    #endif

    int Add(... );

    #ifdef  __cplusplus

    }

    #endif

    1. 动态库的程序

    1. 与静态库的比较:

    1)由于静态库是将代码嵌入到使用程序中,多个程序使用时,会有多份代码,所以代码体积会增大。动态库的代码只需要存在一份,其他程序通过函数地址使用,所以代码体积小。

     2)静态库发生变化后,新的代码需要重新链接嵌入到执行程序中。动态库发生变化后,如果库中函数的定义(或地址)未变化,其他使用DLL的程序不需重新链接。

    2. 动态库的创建

    1 ) 建立项目

    2 ) 添加库程序

    3 ) 库程序导出  提供给使用者库中的函数等信息。

    3 动态库的使用

    3.1 隐式链接

    3.2 显式链接

    4 动态库的函数

    4.1 实现动态库的函数

    4.2 库函数的导出

    1C++的导出

    使用 _ _declspec(dllexport) 导出函数

    注意:动态库编译链接后,也会有LIB文件,是作为动态库函数映射使用,与静态库不完全相同,另外也要加载它。

    2C的导出方式     extern “C” _ _ declspec(dllexport)  int  Sub(...);

    3)导入: _ _declspec(dllimport) 导出函数.。一般VC6.0自动导入,无需自己做

    4)若不用dllexport导出,可定义模块定义文件(.def)来导出。

    例如:

    EXPORTS    //库导出表

    Sub //导出的函数名

    4.3 库函数的使用

         4.3.1 隐式链接

    1)头文件和函数原型

    可以在函数原型的定义前,增加declspec(dllimport) 例如

    _declspec(dllimport) int DLL_Add( ... );

    如果库函数使用C格式导出,需要在函数定义增加 extern “C”

    2)导入动态库的LIB文件

    3)在程序中使用函数

    4)隐式链接的情况,DLL可以存放的路径:

    1)与执行文件中同一个目录下  推荐使用

    2)当前工作目录     依赖开发环境,用于调试

    3Windows目录   注意版本问题

    4Windows/System32目录      注意版本问题

    5Windows/System   注意版本问题

    6)环境变量PATH指定目录 依赖与系统环境

    5)可执行程序- 启动即加载所依赖的动态库,直到程序结束才卸载 动态库。

    DLL中类的使用

    DLL中类的导出

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

    ...

    };

    4.3.2 动态加载HMODULE LoadLibrary(

    LPCTSTR lpFileName  //动态库文件名或全路径

    ); 返回DLL的实例句柄(HINSTANCE

    1)获取函数地址

    FARPROC   GetProcAddress(

    HMODULE   hModule,    //DLL句柄

    LPCSTR    lpProcName   //函数名称

    ); 成功返回函数地址,失败返回NULL

    a. 函数名需要注意C++换名问题

    b. 函数指针的类型问题,要强制转换函数指针类型,参数等,可用typedef  type  (*fun)(type  a, type b  ,…)

    2)使用函数

    3)卸载动态库

    BOOL   FreeLibrary(

    HMODULE  hModule   //DLL的实例句柄

    );//成功返回TRUE,失败返回FALSE

           注意:高版本VC的配置文件

    4.3.3 两种链接方式对比

    1)在库函数的定义不变情况下:

    隐式链接,由于库函数地址是在程序编译链接时设置,所以当动态库变化后,使用程序需要重新编译链接。

    显式链接,由于库函数地址是在程序执行时,动态的从库中查询,所以库变化后,不需要重新编译链接。

    2)动态库加载

    隐式链接,动态库是在程序启动时就被加载,当DLL不存在,程序无法启动

    显式链接,动态库只在使用LoadLibrary函数,才会被加载。

    动态库的程序入口:

    入口程序不是DLL必须的。常用于DLL内部初始化或善后处理。

    BOOL  WINAPI  DllMain(

       HINSTANCE  hinstDLL, //动态库实例句柄

       DWORD  fdwReason,    //被调用的原因

        LPVOID  lpvReserved   //保留值

    ); 返回TRUE,表示动态库加载成功。失败返回FALSE

    动态库的加载或卸载时会被调用。例如:使用LoadLibraryFreeLibrary时会被调用。

    fdwReason 参数说明:

    DLL_PROCESS_ATTACH   进程加载  主线程中调用LoadLibrary

    DLL_THREAD_ATTACH   线程链接  子线程中调用LoadLibrary

    DLL_THREAD_DETACH   线程卸载  子线程中调用FreeLibrary

    DLL_PROCESS_DETACH  进程卸载   主线程中调用FreeLibrary

    3、 Windows  文件系统

    1. Windows常见文件系统

    操作系统管理磁盘数据的方式。

    FATFAT32NTFS

    硬盘的管理

    磁道:包括若干个扇区

    扇、扇区: - 大小为512字节

    文件系统最小管理单位   - 由连续的几个扇区组成8/16/32/64

    FAT32  - 132扇区.16K字节

    NTFS   - 18扇区即4K字节

    文件存储时,是以簇为单位占用硬盘空间,

    即使文件只有1个字节,也要占用1簇的空间。故一般下,NTFSFAT32占有有效空间更多,浪费更少。

    1. Windows 目录相关API函数

    1) 获取磁盘驱动器信息

    DWORD  GetLogicalDrives(void );//返回当前可用逻辑驱动器的掩码。

    磁盘表示与掩码关系:

    L-----------------------------------------------------------------àH

    XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX

    HGFEDCBA     ……KJI

    0:表示无此驱动器

    1:表示存在此驱动器

    2) 获取系统驱动器

    DWORD GetLogicalDriveStrings(

        DWORD nBufferLength,  // 缓冲区大小(以字符为单位)

        LPTSTR lpBuffer       // 返回指向系统驱动器缓冲区字符串

    );//成功返回串长度,失败返回0.

    3) 获取当前工作目录

    DWORD   GetCurrentDirectory(

    DWORD   nBufferLength,  // 缓冲区大小(以字符为单位)

    LPTSTR   lpBuffer       // 缓冲区指针

    );//成功返回缓冲区串长度,失败返回0

    4) 设置当前工作目录

     BOOL   SetCurrentDirectory(

     LPCTSTR   lpPathName   //指定新的工作路径

    );//成功返回非0值,失败返回0.

    5) 获取Windows 目录

    UINT   GetWindowsDirectory(

    LPTSTR   lpBuffer,  //  指向缓冲区的指针

    UINT   uSize        // 目录缓冲区大小(以字符为单位)

    );//成功返回字符串长度,失败返回0

    6) 获取系统目录

    UINT    GetSystemDirectory(

        LPTSTR    lpBuffer,  //指向缓冲区的指针

       UINT   uSize        //缓冲区目录的大小

    );///成功返回字符串长度,失败返回0

    6) 获取临时文件目录

    DWORD    GetTempPath(

       DWORD    nBufferLength,  // 缓冲区大小(以字符为单位)

       LPTSTR    lpBuffer       // 缓冲区指针

    );//成功返回字符串长度,失败返回0

    7) 目录创建

    BOOL   CreateDirectory(

       LPCTSTR    lpPathName,//目录名称

       LPSECURITY_ATTRIBUTES  lpSecurityAttributes//安全属性默认为NULL

    );//成功返回非0值,失败返回0。当目录文件已存在,无法创建该文件。

    8)目录删除

    BOOL    RemoveDirectory(

    LPCTSTR    lpPathName  //目录名称

    );成功返回true,失败返回false。只能删除空目录,若内有文件则无法删除。

    9) 目录修改/ 移动

    BOOL   MoveFile(

    LPCTSTR    lpExistingFileName, //当前的名称

    LPCTSTR lpNewFileName   //新的名称

    );//成功返回true,失败返回false

    ///当新目录或文件已存在,无法移动或更改该目录或文件。

    ////注意:不能跨逻辑驱动器移动目录,但是可以跨逻辑驱动器移动文件。

    1. Windows  文件相关API

    1) 创建或打开文件

    HANDLE   CreateFile(

      LPCTSTR  lpFileName, //文件名称

      DWORD  dwDesiredAccess, //访问权限,方式

      DWORD  dwShareMode,   //共享方式

      LPSECURITY_ATTRIBUTES lpSecurityAttributes,//安全属性默认NULL

      DWORD  dwCreationDisposition,  //创建或打开方式

      DWORD  dwFlagsAndAttributes,  //文件属性

      HANDLE  hTemplateFile //文件句柄模板(磁盘文件,默认为NULL)

    ); //成功返回文件句柄,失败返回INVALID_HANDLE_VALUE(-1)

    小记:CreateFile 可以创建或打开以下文件:

    files   文件

    pipes   管道

    mailslots  邮槽

    communications resources  通信资源

    disk devices (Windows NT only)  磁盘驱动

    consoles   控制台

    directories (open only) 目录

    参数说明:

    dwDesiredAccess:

    0     咨询  (判断文件是否存在)

    GENERIC_READ   读取

    GENERIC_WRITE   写入

    dwShareMode

    FILE_SHARE_DELETE  允许其他进程删除此文件

    FILE_SHARE_READ    允许其他进程读取此文件

    FILE_SHARE_WRITE    允许其他进程写入此文件

    dwCreationDisposition

    CREATE_NEW   不存在则创建。已存在则失败

    CREATE_ALWAYS 不存在则创建,已存在则删除再创建

    OPEN_EXISTING 已存在则打开,不存在则失败

    OPEN_ALWAYS  已存在则打开,不存在则创建再打开

    TRUNCATE_EXITSTING 已存在先清空再打开,不存在则失败

    2) 关闭文件

    BOOL    CloseHandle(

      HANDLE   hObject   //句柄

    );//成功返回true,失败返回false

    小记:CloseHandle()也可以关闭其他的。

    如下:

    • Communications device
    • Console input
    • Console screen buffer
    • Event
    • File
    • File mapping
    • Job
    • Mailslot
    • Mutex
    • Named pipe
    • Process
    • Semaphore
    • Socket
    • Thread
    • Token

    3) 写入数据

    BOOL    WriteFile(

      HANDLE   hFile, //文件句柄

      LPCVOID   lpBuffer, //数据BUFF

      DWORD   nNumberOfBytesToWrite, //期望写入数据字节数

      LPDWORD   lpNumberOfBytesWritten, //返回实际写入的数据字节数

      LPOVERLAPPED  lpOverlapped  //异步传输结构,默认为NULL

    );///成功返回true,失败返回false

    4) 读出数据

    BOOL   ReadFile(

      HANDLE   hFile, //文件句柄

      LPVOID   lpBuffer,  //数据BUFF

      DWORD   nNumberOfBytesToRead,  //要读的字节数

      LPDWORD   lpNumberOfBytesRead, //实际读到字节数

      LPOVERLAPPED   lpOverlapped    //异步传输结构,默认为NULL

    );///成功返回true,失败返回false

    5) 获取文件大小(字节数)

    DWORD   GetFileSize(

      HANDLE  hFile, //文件句柄

      LPDWORD  lpFileSizeHigh  //文件字节数的高32

    ); 返回值是文件字节数的低32

    ///64位系统下,需要将高32位和低32位组合为64位的,得到实际文件大小,

    ////而在32为系统下,无需考虑高32位的。

    6) 移动文件指针

    DWORD    SetFilePointer(

      HANDLE   hFile, //文件句柄

      LONG    lDistanceToMove, //字节偏移量的低32

      PLONG    lpDistanceToMoveHigh,  //返回实际字节偏移量的高32

      DWORD    dwMoveMethod//偏移的相对位置

    ); //返回文件指针实际新的位置字节偏移量的低32位,

    ///对于高32位情况同GetFileSize()若不要高32位且若后移,则应该设置高32NULL,否则可能失败。纵使设置相应高32位为NULL指针变量也不行。其他情况下无要求。

    dwMoveMethod  参数说明:

    FILE_BEGIN     文件开始位置

    FILE_CURRENT  文件当前位置

    FILE_END       文件末尾位后一个位置

    7) 文件其他相关

    复制文件:

    BOOL    CopyFile(

      LPCTSTR   lpExistingFileName, // 源文件

      LPCTSTR   lpNewFileName,  // 复制的目标文件

      BOOL   bFailIfExists      // flag for operation if file exists

    );//

    // bFailIfExists 参数说明:

    若为true,则若复制相同位置、名文件,则返回失败。

    若为false,则若复制相同位置、名文件,则覆盖返回成功。

    删除文件:

    BOOL   DeleteFile(

      LPCTSTR    lpFileName   //删除的文件名

    );//成功返回true,失败返回false

    移动文件:同移动目录的MoveFile()

    8) 文件属性

    获取文件属性:

    DWORD   GetFileAttributes(

         LPCTSTR   lpFileName   //文件名或目录名

    );///成功返回指定文件的属性,失败则返回0xFFFFFFFF。

    获取文件属性、时间等:

    BOOL GetFileAttributesEx(

     LPCTSTR lpFileName,        // 目录或文件名

     GET_FILEEX_INFO_LEVELS  fInfoLevelId, //设置获取文件或目录属性

      LPVOID lpFileInformation   // 由fInfoLevelId指定的属性而获取的文件或目录属性信息缓冲区

    );////成功返回true,失败返回false

    //////fInfoLevelId参数说明:(枚举类型结构),

    其枚举值:GetFileExInfoStandard。

    由结构体WIN32_FILE_ATTRIBUTE_DATA返回其值。

    typedef struct _WIN32_FILE_ATTRIBUTE_DATA{

       DWORD     dwFileAttributes; //文件属性

       FILETIME  ftCreationTime; //创建时间

       FILETIME  ftLastAccessTime; //最近访问时间

       FILETIME   ftLastWriteTime; //最近写入时间

       DWORD   nFileSizeHigh; //文件高32位字节数

       DWORD   nFileSizeLow; //文件低32位字节数

    }

    WIN32_FILE_ATTRIBUTE_DATA, *LPWIN32_FILE_ATTRIBUTE_DATA;

    /// FILETIME结构体

    typedef struct _FILETIME { // ft

        DWORD dwLowDateTime; //低32位日期

        DWORD dwHighDateTime; //高32位日期

    } FILETIME;

    另外可用FileTimeToSystemTime转化为系统时间,

    BOOL FileTimeToSystemTime(

      CONST FILETIME *lpFileTime,//转变的文件时间

      LPSYSTEMTIME lpSystemTime,// 接收的系统时间

       );

    SYSTEMTIME(结构体):见MSDN

    设置文件属性:

    BOOL    SetFileAttributes(

      LPCTSTR    lpFileName,      // 文件名

      DWORD    dwFileAttributes   //设置文件属性,可组合设置

    );///成功返回true,失败返回false

    增加文件属性:获取原文件属性,与需要增加的属性做位或,再设置回去。

    删除文件属性:获取原文件属性,与需要删除的属性取反且位与,再设置回去。

    9) 文件查找

    HANDLE   FindFirstFile(

       LPCTSTR    lpFileName, //查找路径

       LPWIN32_FIND_DATA    lpFindFileData  //查找的数据

    );  //返回查找句柄,此句柄可用于findnextfile,findclose,失败返回INVALID_HANDLE_VALUE 

    参数说明:LPWIN32_FIND_DATA(结构体),保存查找文件或子目录的数据

    typedef  struct _WIN32_FIND_DATA { // wfd

        DWORD    dwFileAttributes;   //文件属性

        FILETIME   ftCreationTime;   //创建时间

        FILETIME   ftLastAccessTime; ///最后访问时间

        FILETIME   ftLastWriteTime; ///最后写入时间

        DWORD    nFileSizeHigh; //文件字节数高32

        DWORD    nFileSizeLow; ///文件字节数低32

    DWORD    dwReserved0; //

    DWORD    dwReserved1;   //保留

        TCHAR    cFileName[ MAX_PATH ]; //文件名

        TCHAR    cAlternateFileName[ 14 ]; ///可选文件名

    } WIN32_FIND_DATA;

    10) 获取下一个文件

    BOOL    FindNextFile(

      HANDLE   hFindFile, //查找句柄,

      LPWIN32_FIND_DATA   lpFindFileData //查找的数据

    ); //找到返回TRUE,失败返回FALSE。,查找基于文件名

    11) 关闭查找

    BOOL FindClose (

    HANDLE  hFindFile  // 查找句柄

    );//成功返回TRUE,失败返回FALSE

  • 相关阅读:
    QQ在线人数图表
    使LumaQQ.NET支持接收长消息
    发现有趣的东东,Live Mail能自动显示人名
    关于转换QQ消息中系统表情,自定义表情和截图的函数
    使用Autofac,提示重写成员“Autofac.Integration.Mvc.AutofacDependencyResolver.GetService(System.Type)”时违反了继承安全性规则。重写方法的安全可访问性必须与所重写方法的安全可访问性匹配。
    libvirt笔记(未完待续)
    OpenStack Grizzly版本部署(离线)
    git学习笔记
    MyEclipse 报错 Errors running builder 'JavaScript Validator' on project......
    Response 关于浏览器header的方法
  • 原文地址:https://www.cnblogs.com/haomiao/p/11646585.html
Copyright © 2020-2023  润新知