基于WIN32 API图形界面实现的楼盘管理系统

Smilelove

发布日期: 2018-11-05 21:37:12 浏览量: 299
评分:
star star star star star star star star star_border star_border
*转载请注明来自write-bug.com

1 绪论

1.1 课题背景

房地产产业是中国最近关注度非常高的一门产业。房地产商需要去管理整个公司的楼盘信息,而用户需要查询对应的楼盘信息,因此制作一个系统来满足双方的需求就显得尤为重要。一个方便的系统能够减少客户四处咨询的时间,同时也方便了公司对房地产的管理。因此,我们需要一个楼盘的管理系统来满足用户的需求。

1.2 课题研究的目的与意义

  • 给出了管理和查询的必要功能,可以实现基本的插入、修改、删除功能。方便客户与房地产商的使用

  • 实现了图形化界面的处理,模仿大部分Windows应用程序的设计思路,使设计更标准化,尽量使用户的体验达到更好

2 系统整体设计

本实验设计的系统为楼盘信息管理系统,功能为管理不同地区的不同楼盘、楼栋、房间的信息。主体功能模块分为五个部分,如图1.1所示。接下来将依次介绍五个主要功能模块。

2.1 文件模块

文件模块主要分为四个部分:数据文件导入、数据保存、退出系统、放弃本次修改,如图1.2所示。具体功能介绍如下:

2.1.1 保存

通过该功能将已经通过系统做的修改、增添和删除保存至磁盘文件。具体实现方法如下:
当用户单击菜单中的“保存”时,若磁盘中无对应文件则激活“另存为”,若磁盘中已有对应文件,则直接将修改写入至磁盘对应文件。

2.1.2 另存为

若为“保存”激活,则保存文件至磁盘某一位置;若为直接点击,则为该文件在磁盘上创造一个副本。具体实现方法如下:

  • 当单击菜单中的“另存为”时(或对未保存至磁盘的文件单击“保存”),将弹出一个Windows中常用的保存窗口,如图2.3所示;

  • 用户可以通过这个窗口中选择将要保存的位置,以及将要保存的文件形式(目前系统仅支持*.led格式,该格式为自定义的引导文件格式);

  • 用户若单击取消,则恢复原状。若用户单击确定,则文件保存至磁盘相应目录下。用户可到磁盘中查询到四个文件:一个引导文件Leading Files(*.led),三个数据文件(*.bin),如图2.4所示。其文件名为系统自动确定,不允许用户更改。

2.1.3 新建

新建一个空的文件,供用户进行操作(添加、修改、删除等)。实际操作中可跳过这一步,直接在空的系统中操作后保存。

2.1.4 导入

选择磁盘中的某一个文件(要求为Leading Files(*.led)文件)导入该管理系统,并将文件中的所有数据读入链表,同时在系统的窗口中显示。具体实现方法如下:

  • 点击导入之后,弹出一个类似于“保存”的窗口。可通过选择文件格式来筛选文件(默认格式为*.led),单击文件表示选择。

  • 若点击确定,则将该文件下的数据文件导入链表,并在系统中显示第一个楼盘的信息,如图2.5所示。若点击取消,则恢复原状。

2.1.5 退出

退出实现功能与点击右上角的退出按钮相同。首先确认文件是否保存和做过修改。若已修改但未保存,将会弹出窗口提示是否要保存,如图2.6所示,否则直接退出系统。

2.2 显示模块

显示模块不存在于菜单中。为了方便用户浏览信息,实现编辑、统计、添加的同步显示,做到“所见即所得”,本系统设计了显示模块。显示模块允许用户在除菜单外的客户区进行单击、双击操作,同时为其它许多功能的操作提供了便利,带来了良好的用户体验。下面具体描述显示的具体过程。

  • 当进入系统导入文件之后,显示的是第一级,楼盘与该楼盘下所属的楼栋信息,如图2.7所示;

  • 单击每一个楼盘,在右上方蓝色信息区会显示该楼盘的具体信息,同时在右下方的列表中显示该楼盘下的所有楼盘。同时信息区右下角的两个按钮“编辑”与“删除”提供的快速删除、编辑当前楼盘的有效路径;

  • 在2的基础上单击右下角列表中每一个楼栋,在右上方蓝色信息区会显示对应的楼栋信息。同时信息区右下角的两个按钮“编辑”与“删除”提供的快速删除、编辑当前楼栋的有效路径;

  • 在2的基础上双击右下列表中的楼栋,将可以进入该楼栋,即在右上角显示该楼栋的信息,在右下角显示该楼栋下的所有房间及基本信息。同时信息区右下角的两个按钮“编辑”与“删除”提供的快速删除、编辑当前楼栋的有效路径,如图2.8所示;

  • 在4的基础上单击右下角列表中的房间,将在右上角蓝色信息区中显示该房间的所有信息,如图2.9所示。同时信息区右下角的两个按钮“编辑”与“删除”提供的快速删除、编辑当前房间的有效路径;

  • 在4的基础上,单击右下方列表中的第一行楼栋基本信息,将显示该楼栋所有信息,并提供“编辑”与“删除”楼栋功能。双击右下方列表中的第一行楼栋基本信息,将返回上一级,即右下列表中显示该楼盘下所有楼栋信息,右上信息区中显示该楼栋的所有信息。同时信息区右下角的两个按钮“编辑”与“删除”提供的快速删除、编辑当前房间的有效路径;

2.3 编辑模块

编辑模块主要功能为对导入的数据进行编辑。包括更改、增添、删除三大部分,如图2.10所示。每部分的详细内容如下:

2.3.1 更改功能

更改功能又称编辑,可以通过两种方式触发:单击菜单中的“更改”项或在浏览房间/楼栋/楼盘信息之时点击当时所在的房间/楼栋/楼盘信息右下角的编辑按钮。具体实现功能如下:

  • 通过以上两种方法触发弹出更改功能对话框,如图2.11所示

  • 对话框会默认将目前所在房间/楼栋/楼盘的信息输入对应的编辑框,允许用户在编辑框上更改相关的数据(有一些编辑框如电话号码不允许输入数字以外的符号)

  • 若用户点击确定,系统将检查所输入的楼栋号(或房间号、楼盘名)是否与已有数据重复,若重复,则弹出警告,如图2.12所示,要求用户更改所输入的数据。若成功编辑房间,则同时更新该楼盘、楼栋的平均价格,若成功编辑楼盘,则同时更新当前楼盘下的所有楼栋、房间的“所在楼盘”数据。若用户点击取消,则不做更改

  • 更改完成后,重绘整个客户区,将数据更新。用户可以通过系统显示判断更改是否成功

2.3.2 添加功能

添加功能有分为三大部分:添加楼盘,添加楼栋和添加房间。

2.3.2.1 添加房间

添加房间允许在系统任何的显示状态下进行。当单击菜单中“添加 – 添加房间”时,会弹出对话框。若显示当前信息区显示为楼盘,则会在对话框中自动输入默认楼盘的相关信息;若当前信息区显示为楼栋,则会在对话框中自动输入默认楼栋的相关信息,如图2.13所示。

在添加房间的对话框中使用了Edit,Static,Combo Box(下拉选择框),Check Box等许多控件。其中下拉选择框中储存了所有的房间类型信息共34条,方便用户选择。

在输入完毕后,用户若点击确定,则系统会检测是否有重复的房间号,若有则报错,要求用户重新输入信息,则添加成功,用户可在列表框中查看到新添加的房间,或点击查看具体信息;若点击取消,则放弃添加,系统恢复原状。

2.3.2.2 添加楼栋

添加楼栋允许在系统任何的显示状态下进行。当单击菜单中“添加 – 添加楼栋”时,会弹出对话框,且会在对话框中自动输入当前信息区显示楼盘的相关信息,如图2.14所示。

在输入完毕后,用户若点击确定,则系统会检测是否有重复的房间号,若有则报错,要求用户重新输入信息,若无,则添加成功,用户可在列表框中查看到新添加的楼栋,或点击查看具体信息;若点击取消,则放弃添加,系统恢复原状。

2.3.2.3 添加楼盘

添加楼盘允许在系统任何的显示状态下进行。当单击菜单中“添加 – 添加楼栋”时,会弹出对话框,用户输入需要添加的楼盘即可。

在输入完毕后,用户若点击确定,则系统会检测是否有重复的楼盘名,若有则报错,要求用户重新输入信息,若无,则添加成功,系统自动按照顺序添加楼盘号,用户可在左边列表中查看到新添加的楼盘名称,或点击查看具体信息;若点击取消,则放弃添加,系统恢复原状。

2.3.3 删除功能

删除功能提供两种操作方式:准确查找删除与快速删除。

2.3.3.1 准确查找删除

该种删除方式在菜单栏中的“删除”中,分为删除楼盘、楼栋和房间三种。

点击“删除楼盘”时,会弹出对话框,如图2.15。允许选择性地输入楼盘名称或楼盘编号,选择其中一项是,另一项的输入框会变灰色,不允许输入。若点击确定,则直接删除该楼盘;若点击取消,则放弃删除。

点击“删除楼栋”时,要求选择性地输入所在楼盘名称或楼盘编号,以及准确的楼栋编号。若点击确定,则直接删除该楼栋;若点击取消,则放弃删除。

点击“删除房间”时,要求选择性地输入所在楼盘名称或楼盘编号、所在楼栋的准确的楼栋编号,以及准确的房间号。若点击确定,则直接删除该房间;若点击取消,则放弃删除。

2.3.3.2 快速删除

考虑到用户很有可能忘记或者记不清准确的编号信息,系统提供快速删除的功能。即用户在浏览楼盘、楼栋或房间的具体信息可以直接对相关结构进行删除。

具体操作为单击信息栏的删除按钮,系统会自动判断需要删除的是楼栋、楼盘或房间,然后弹出提示框确认是否删除(防止误点),如图2.16所示,若用户点击确认,则删除该结构,若用户点击取消,则放弃删除。

2.4 查询模块

查询模块主要功能体现在菜单中单击“查询”弹出的对话框中,如图2.17所示。查询功能主要分为查询楼盘,查询楼栋,查询房间三个部分,通过对话框中的选择按钮选择将要查询的部分,后面对应的信息栏将会按照选择相应的变灰,即不允许输入。

选择好将要输入的信息后,用户可以在编辑框、选择框中输入自己所想要搜索的信息,但不要求准确。具体提供的搜索功能见图2.17。

系统将会录入用户所输入的搜索信息,并根据用户的选择,将用户所输入的信息与系统中的每一个结构进行比对。系统内部会将每一条信息的重要性分配权值,并计算每一个结构与所输入每一条信息的相似度,然后所有信息相似度的加权平均值作为这一个结构与输入信息的相似度。系统会汇总所有的相似度不为0(即至少有一条信息与所输入信息相符)的结构,并按照权值排序作为搜索结果。最终,系统将会将搜素结果按照相似度从高到低在左边列表中输出。若在搜索中输入房间号为1,楼栋号为1,点击确定,则搜索结果如图2.18所示。同时,会在列表的最后加上一条“退出搜索”的按钮。

显示搜索结果后,用户为了确认是否为自己想要搜索的项目,可以单击左边搜索栏中的每一个搜索结果,其全部信息将会在右边的蓝色信息区中显示。进入搜索状态后,右上信息区会出现一个“进入”按钮,当用户浏览信息后确认是想要的搜索结果时,可以点击“进入”按钮,直接进入当前搜索结果。以房间为例,点击进入后,将会在左边列表中显示楼盘信息,右上信息栏中显示该房间信息,右下列表中显示所在楼盘的所有房间,若点击沁苑11栋201,则显示如图2.19所示。若用户未找到对应的搜索结果,则直接点击“【退出搜索】”,则恢复搜索前的状态不做改变。

按照输入的搜索结果,不存在房间号为1的房间,因此未找到,但是存在楼栋号为1的房间,因此楼栋为1的房间在最前面显示。同时,由于未勾选“已售出”选项,搜索所有未售出的楼盘,系统会将一些未售出但是楼栋号不是1的房间显示在偏后的位置,供用户查看。

2.5 统计模块

由于可视化Windows程序的特殊性,本程序未在菜单中加入专门的统计栏,而是将统计融入在程序的显示中。包括统计平均价格,统计楼栋所有房间数,楼盘所有房间数、楼栋数,统计已售出、未售出的房间,目前所有的楼盘数,统计平均面积等。

每次进行数据添加、更改、删除时,系统会自动将所有的相关数据全部更改,并在系统的界面上实时显示。由于楼栋编号为顺序,通过最后的楼盘编号即可了解所有盘数。且通过搜索功能可以达到更加实用和强大的统计功能,例如统计所有未售出的房间,统计所有价格在某一个价格段的房间等。

2.6 帮助模块

由于本系统未设置专门的参考文档,因此只在关于软件中提供版本信息、作者信息等信息。单击菜单中帮助的“关于软件”,即可得到相关信息,如图2.20所示。

以上即为“楼盘管理系统”的主体功能模块,该功能模块较大的依赖于可视化界面,同时也充分发挥了可视化操作的优势,相较控制台带给用户更好的体验。同时,搜索模块可以通过调整权值分配的计算方法,使之更加的合理,得到的结果更符合用户的需要,此模块还有着很大的发展空间。  

3 数据结构设计

3.1 整体数据结构

本系统的设计中,内存总体数据结构为十字交叉三级链表,如图3.1所示。

每一个楼盘、楼栋、房间都作为一个结构体,这些结构体在内存中形成一个三级链表。每个成员成员储存有关的信息,每个结构体的具体设计以及各成员的意义如下:

  1. //楼盘结构体
  2. //功能:储存楼盘相关信息,并可用于构造链表
  3. typedef struct _Community {
  4. int communityNum; //楼盘号
  5. TCHAR name[100]; //楼盘名
  6. TCHAR address[100]; //楼盘地址
  7. TCHAR phone[30]; //联系电话
  8. int numberOfBuildings; //所有楼栋数
  9. int numberOfRooms; //所有房间数
  10. float avgPrice; //平均价格
  11. Person host; //联系人结构*
  12. struct _Community *nextCommunity = NULL; //指向下一个楼盘
  13. struct _Building *buildings = NULL; //指向该楼盘第一个楼栋
  14. }Community;

楼盘结构的每一个成员的具体含义如上述。其中,联系人结构将在后面指出,用于储存联系人的姓名、电话等信息。每个楼盘的唯一标识为楼盘名(name),楼盘名不允许重复。

3.1.2 楼栋结构

  1. //楼栋结构体
  2. //功能:储存楼栋相关信息,并可用于构造链表
  3. typedef struct _Building {
  4. int buildingNum; //楼栋号
  5. int communityNum; //所在楼盘号
  6. int numberOfRooms; //所有房间数
  7. int numberOfFloors; //楼层数
  8. float avgPrice; //平均价格
  9. TCHAR inCom[100]; //所在楼盘名称
  10. Person host; //联系人结构
  11. struct _Building *nextBuilding; //指向下一个楼栋
  12. struct _Room *rooms; //指向该楼栋第一个房间
  13. }Building;

楼栋结构的每一个成员的具体含义如上述。其中,联系人结构将在后面指出,用于储存联系人的姓名、电话等信息。一般而言,楼栋的联系人与楼盘的联系人相同,但是系统也提供单独修改楼栋联系人信息的方法。

3.1.3 房间结构

  1. //房间结构体
  2. //功能:储存房间相关信息,并可用于构造链表
  3. typedef struct _Room {
  4. int roomNum; //房间号
  5. int buildingNum; //所在楼栋号
  6. int communityNum; //所在楼盘号
  7. int floor; //所在楼层
  8. float roomSize; //房间面积(平方米)
  9. float roomPrice; //房间价格(人民币元/平方米)
  10. long allPrice; //房间总价(人民币元)
  11. TCHAR roomType[100]; //户型:室,厅,厕,厨数量
  12. TCHAR inCom[100]; //所在楼盘名
  13. BOOL roomState; //售出状态:0代表未售出,1代表已售出
  14. TCHAR note[1000]; //备注
  15. Person host; //联系人结构
  16. struct _Room *nextRoom; //指向链表中下一个房间
  17. }Room;

房间结构的每一个成员的具体含义如上述。其中,联系人结构将在后面指出,用于储存联系人的姓名、电话等信息。一般而言,楼栋的联系人与楼盘、楼栋的联系人相同,但是系统也提供单独修改房间联系人信息的方法。

需要说明的是,户型的储存方式为34个字符串代表34种户型,每种户型与每个字符串严格一一对应。这些户型被定义在静态区,户型的信息如下:

  1. static TCHAR *szComboBoxData[] = {
  2. TEXT("户型1:一室一厅一厨一厕"),TEXT("户型18:五室一厅一厨两厕"),
  3. TEXT("户型2:两室一厅一厨一厕"),TEXT("户型19:两室两厅两厨一厕"),
  4. TEXT("户型3:三室一厅一厨一厕"),TEXT("户型20:三室两厅两厨一厕"),
  5. TEXT("户型4:四室一厅一厨一厕"),TEXT("户型21:四室两厅两厨一厕"),
  6. TEXT("户型5:五室一厅一厨一厕"),TEXT("户型22:五室两厅两厨一厕"),
  7. TEXT("户型6:一室两厅一厨一厕"),TEXT("户型23:两室两厅一厨两厕"),
  8. TEXT("户型7:两室两厅一厨一厕"),TEXT("户型24:三室两厅一厨两厕"),
  9. TEXT("户型8:三室两厅一厨一厕"),TEXT("户型25:四室两厅一厨两厕"),
  10. TEXT("户型9:四室两厅一厨一厕"),TEXT("户型26:五室两厅一厨两厕"),
  11. TEXT("户型10:五室两厅一厨一厕"),TEXT("户型27:两室一厅两厨两厕"),
  12. TEXT("户型11:两室一厅两厨一厕"),TEXT("户型28:三室一厅两厨两厕"),
  13. TEXT("户型12:三室一厅两厨一厕"),TEXT("户型29:四室一厅两厨两厕"),
  14. TEXT("户型13:四室一厅两厨一厕"),TEXT("户型30:五室一厅两厨两厕"),
  15. TEXT("户型14:五室一厅两厨一厕"),TEXT("户型31:两室两厅两厨两厕"),
  16. TEXT("户型15:两室一厅一厨两厕"),TEXT("户型32:三室两厅两厨两厕"),
  17. TEXT("户型16:三室一厅一厨两厕"),TEXT("户型33:四室两厅两厨两厕"),
  18. TEXT("户型17:四室一厅一厨两厕"),TEXT("户型34:五室两厅两厨两厕"),
  19. };

3.1.4 联系人结构

  1. //联系人结构体
  2. //功能:用于存储个人信息
  3. typedef struct _Person {
  4. TCHAR name[100]; //姓名
  5. TCHAR phone[50]; //电话
  6. TCHAR idNumber[50]; //证件ID号
  7. }Person;

联系人结构储存一个人的相关信息,具体成员的含义见注释。

3.2 辅助链表

在搜索功能中,为了搜索的便捷。每找到一个有相关性的结构体,就将其接入一个新的链表,称为搜索链表。该链表为单向先进先出的链表,搜索链表有三类,分为楼盘搜索、楼栋搜索、房间搜索,对应三种不同的链表。将相关数据接入链表中后,将链表排序后输出,即可得到搜索结果。

3.3 其他结构体

3.3.1 引导文件结构体

创建引导文件的目的是方便用户导入数据,同时储存相关的信,以供读入内存时使用。因此在引导文件中存储的是一个结构体,储存了其他数据文件的基本信息。引导文件结构如下:

  1. //*.led文件中的结构体
  2. //储存com,bui,room三个文件里面所包含的数据数
  3. typedef struct _LenData {
  4. int iCom;
  5. int iBui;
  6. int iRoom;
  7. }LenData;

该文件中存储的为每一种结构体的数量。便于在读取文件重新构建链表的时候顺利的构建与原来相同的链表,结构见表3.2。

3.3.2 搜索结构体

在搜索设计中,系统将读取用户输入的所有数据并将其与每一个结构进行比对。因此,为了方便比对,特意将所有的输入数据读入同一个结构体,该结构具体内容如下:

  1. //SearchData搜索中使用的结构体,容纳搜索的所有数据
  2. typedef struct _SearchData {
  3. int mask; //确定搜索的对象
  4. //值为SD_COM,SD_BUI,SD_ROOM中的一个
  5. //Community
  6. TCHAR comName[100];
  7. int comNum;
  8. TCHAR comPerson[100];
  9. TCHAR comPhone[100];
  10. //Building
  11. int buiNum;
  12. TCHAR buiPhone[100];
  13. TCHAR buiPerson[100];
  14. //Room
  15. int roomNum;
  16. int roomFloor;
  17. float roomSize;
  18. long allPrice;
  19. float roomLoPrice;
  20. float roomHiPrice;
  21. BOOL roomSold;
  22. TCHAR roomType[100];
  23. }SearchData;

该结构体分为三个部分,楼盘、楼栋和房间,未输入的信息即为0或\0。第一个成员mask储存搜索的目标,其三个值在头文件“managerSys.h”头文件中定义。使用时,将每一个成员与对应结构比对即可。

4 系统模块设计与实现

4.1 文件模块

4.1.1 文件格式

4.1.1.1 引导文件

引导文件只包含一个引导结构体,包含了所需要的相关信息。

4.1.1.2 楼盘数据文件

楼盘数据文件以楼盘结构为单位储存了所有楼盘的信息。该结构为许多楼盘无间隔相邻顺序储存,每一个单位大小为sizeof(Community)。

4.1.1.3 楼栋数据文件

每一个楼盘中,属于该楼盘的楼栋无间隔相邻顺序储存。不同楼盘的楼栋按照楼盘存储顺序储存,并且每两个楼盘的楼栋之间相隔一个分隔楼栋,该分隔楼栋的楼栋号为-1,其与数据均为空。

4.1.1.4 房间数据文件

每一个楼栋中,属于该楼栋的房间无间隔相邻顺序储存。不同楼栋的房间按照楼盘存储顺序储存,并且每两个楼栋的房间之间相隔一个分隔房间,该分隔房间的房间号为-1,其与数据均为空。

4.1.2 文件读取

文件读取使用的函数为ReadFile函数【1】,这些函数比fread更加功能全面。通过每次在文件中读取一个结构的数据到缓冲区,确定数据全部读取然后将缓冲区写入链表,之后调用SetFilePointer函数【2】移动文件指针到下一个结构,在调用下一个结构写入链表。若遇到文件中的分隔结构,则跳过该结构,将接下来读取的数据写入下一个楼盘(楼栋)。

整个读取由一个函数来执行,该函数原型如下:

  1. //FileReadWnd
  2. //功能:读取文件
  3. //参数:窗口句柄hwnd,路径名
  4. //返回:若成功则返回TRUE,失败则返回FALSE
  5. BOOL FileReadWnd(HWND hwnd, PTSTR pstrLeadFileName);

该函数的主要结构为:

  • 获取文件名;

  • 编辑数据文件名

  • 调用CreateFile函数【3】打开引导文件和数据文件,获取文件句柄;

  • 检查读取是否完整,并拷贝引导文件中的数据;

  • 将三个文件中的数据写入链表;

  • 检查数据是否全部读取;

  • 设置主窗口标题和回收指针、句柄;

函数参数以及返回值见注释,函数实现代码见附录。

4.1.3 文件写入

文件写入的函数为WriteFile函数【4】,通过按照4.1.1所述的文件结构将链表中的数据写入链表,同时在适当的地方加入分隔结构,便于读取。每次写入文件后,调用SetFilePointer函数将文件指针后移一个结构体,写入新的数据(注意不可简单的将指针移到文件尾)。
整个写入过程由一个函数来执行,该函数原型如下:

  1. ///////////////////////////////////////////////////////
  2. //FileWriteWnd
  3. //功能:写入文件
  4. //参数:窗口句柄hwnd,引导文件路径
  5. //返回:若成功则返回TRUE,失败则返回FALSE
  6. BOOL FileWriteWnd(HWND hwnd, PTSTR pstrLeadFileName);

该函数的主要结构为:

  • 获取文件名;

  • 编辑数据文件名

  • 调用CreateFile函数【3】打开引导文件和数据文件,获取文件句柄;

  • 编辑好文件中的分隔结构,并将其与链表中的数据一同按照4.1.1中的文件结构写入相应文件中;

  • 检查数据是否完全读取并制作引导结构,将其写入引导文件;

  • 设置主窗口标题和回收指针、句柄;

函数参数以及返回值见注释,函数实现代码见附录。

4.1.4 其它文件处理函数【5】

其它的文件处理函数用于初始化以及完成一些附属功能,例如FileInitWnd函数、FileImportDlg函数、FileSaveDlg函数等,它们的函数原型如下:

  1. ///////////////////////////////////////////////////////
  2. //FileInitWnd
  3. //功能:初始化弹出文件窗口的数据
  4. //参数:父窗口句柄hwnd
  5. //返回:无返回值
  6. void FileInitWnd(HWND hwnd);
  7. ///////////////////////////////////////////////////////
  8. //FileImportDlg
  9. //功能:创建导入文件对话框
  10. //参数:父窗口句柄hwnd,文件名,路径名
  11. //返回:若成功则返回TRUE,失败则返回FALSE
  12. BOOL FileImportDlg(HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName);
  13. ///////////////////////////////////////////////////////
  14. //FileSaveDlg
  15. //功能:创建保存文件对话框
  16. //参数:窗口句柄hwnd,文件名,路径名
  17. //返回:若成功则返回TRUE,失败则返回FALSE
  18. BOOL FileSaveDlg(HWND hwnd, PTSTR pstrFileName, PTSTR pstrTitleName);

这些函数的参数以及返回值见注释,函数实现代码见附录。

4.1.5 主窗口过程中有关文件的消息响应

主窗口过程中有关文件的消息主要有WM_COMMAND消息中的消息码为IDM_FILE_SAVE,IDM_FILE_SAVE_AS,IDM_FILE_CREATE,IDM_FILE_IMPORT,IDM_FILE_EXIT五种。不同的消息码对应菜单中的不同项目的ID。在WndProc主窗口过程中,对各个消息码有着分别的处理:

4.1.5.1 保存(IDM_FILE_SAVE)

调用FileWriteWnd函数将现有链表写入文件,若写入失败,则弹出警告。之后修改保存情况。具体操作见2.1.1文件模块功能。

4.1.5.2 另存为(IDM_FILE_SAVE_AS)

调用FileWriteWnd函数,弹出对话框,显示地址。将现有链表写入到一个备份的文件中,若写入失败,则弹出警告。之后修改保存情况具体操作见2.1.2文件模块功能。

4.1.5.3 新建(IDM_FILE_CREATE)

更改主窗口显示的文件名。具体操作见2.1.3文件模块功能。

4.1.5.4 导入(IDM_FILE_IMPORT)

若未保存,提示用户是否需要保存。调用FileImportDlg和FileReadWnd函数,弹出导入对话框,选择导入的文件(具体操作见2.1.4文件模块功能)。之后将所有数据导入链表,并调用InvalidateRect函数【6】无效化整个窗口,重绘相关信息,将信息区显示为第一个楼盘的数据。

4.1.5.5 退出(IDM_FILE_EXIT)

向主窗口发送WM_CLOSE消息。若未保存,则提示用户保存。若已经保存,向主窗口发送WM_DESTROY消息请求关闭。【7】

4.2 显示模块

在头文件“managerSys”显示过程中定义四种显示状态:

  1. #define PA_FIRSTEPCOM 500 //第一级,显示楼盘信息
  2. #define PA_SECSTEPBUI 501 //第二级,显示楼栋信息
  3. #define PA_FIRSTEPBUI 502 //第一级,显示楼栋信息
  4. #define PA_SECSTEPROOM 503 //第二级,显示房间信息

4.2.1 显示第一级

显示第一级为在左边ListBox【11】中显示楼盘,在右上信息区中显示楼盘或楼栋的具体信息,在右下角ListView【12】中显示相应楼盘下的所有楼栋基本信息。

此时根据全局变量iPaintState的取值,判断显示的级别。若为显示楼盘信息,则在WM_PAINT消息处理中调用函数Draw1Step与DrawComInf;若显示为楼栋信息,则在WM_PAINT消息处理中调用函数Draw1Step与DrawBuiInf。

单击左边的ListBox中的项目,则通过LB_SELCHANGE中获取选择项的文本(即为楼盘名),将楼盘名作为信息在整个链表内检索,获取该楼盘的具体信息以及其下的所有楼栋信息。使用TextOut函数在右上信息区中输出相关信息,通过向右下角发送LVS_SETITEMTEXT(或调用函数ListView_SetItemText)将楼栋信息发送到ListView中,从而显示楼盘信息(即为Draw1Step的工作方式)。

单击右边的楼栋项目,将会将状态设置为PA_FIRSTEPBUI,然后无效化窗口并发送WM_PAINT消息。此时调用函数Draw1Step与DrawBuiInf,此时显示对应楼栋信息。

双击右边的楼栋项目,将会将状态设置为PA_SECSTEPBUI,然后无效化窗口并发送WM_PAINT消息。此时调用函数Draw2Step与DrawBuiInf,在右边显示楼栋信息以及在列表中列出该楼栋下所有楼盘。

4.2.2 显示第二级

显示第一级为在左边ListBox【11】中显示楼盘,在右上信息区中显示楼栋或房间的具体信息,在右下角ListView【12】中显示相应楼盘下的所有楼栋基本信息。

此时根据全局变量iPaintState的取值,判断显示的级别。若为显示楼盘信息,则在WM_PAINT消息处理中调用函数Draw1Step与DrawComInf;若显示为楼栋信息,则在WM_PAINT消息处理中调用函数Draw1Step与DrawBuiInf。

单击左边的ListBox中的项目,则通过LB_SELCHANGE中获取选择项的文本(即为楼盘名),将楼盘名作为信息在整个链表内检索,获取该楼盘的具体信息以及其下的所有楼栋信息。使用TextOut函数在右上信息区中输出相关信息,通过向右下角发送LVS_SETITEMTEXT(或调用函数ListView_SetItemText)将楼栋信息发送到ListView中,从而显示楼盘信息(即为Draw1Step的工作方式)。

单击右边的房间或楼栋项目,将会将状态设置为PA_SECSTEPBUI或PA_SECSTEPROOM,然后无效化窗口并发送WM_PAINT消息。此时调用函数Draw2Step与DrawBuiInf或DrawRoomInf,此时显示对应楼栋信息或对应房间信息。

双击右边的列表中第一行楼栋项目,通过读取WM_NOTIFY中的消息获取选中项目,同时将会将状态设置为PA_SECSTEPBUI,然后无效化窗口并发送WM_PAINT消息。此时调用函数Draw1Step与DrawBuiInf,在右边显示楼栋信息以及在列表中列出所在楼盘下的所有楼栋。即实现返回上一级的目的。

在这两种显示中使用的函数声明如下:

  1. ///////////////////////////////////////////////////////
  2. //Draw1Step
  3. //功能:WM_PAINT消息中绘制第一级(包含Com与Bui),不显示数据
  4. //参数:设备环境hdc,显示数据的com指针
  5. //返回:无返回
  6. void Draw1Step(HDC hdc, Community *pChosenCom);
  7. ///////////////////////////////////////////////////////
  8. //Draw2Step
  9. //功能:WM_PAINT消息中绘制第二级,不显示数据
  10. //参数:设备环境hdc,指向所选楼栋的指针
  11. //返回:无返回
  12. void Draw2Step(HDC hdc, Building *pBui);
  13. ///////////////////////////////////////////////////////
  14. //DrawComInf
  15. //功能:绘制楼盘信息窗口
  16. //参数:编辑框句柄hwnd,设备环境hdc,Community结构
  17. //返回:成功返回TRUE,失败返回FALSE
  18. BOOL DrawComInf(HWND hwnd, HDC hdc, Community com);
  19. ///////////////////////////////////////////////////////
  20. //DrawBuiInf
  21. //功能:绘制楼栋信息窗口
  22. //参数:编辑框句柄hwnd,设备环境hdc,Building结构
  23. //返回:成功返回TRUE,失败返回FALSE
  24. BOOL DrawBuiInf(HWND hwnd, HDC hdc, Building bui);
  25. ///////////////////////////////////////////////////////
  26. //DrawRoomInf
  27. //功能:绘制楼栋信息窗口
  28. //参数:编辑框句柄hwnd,设备环境hdc,Room结构
  29. //返回:成功返回TRUE,失败返回FALSE
  30. BOOL DrawRoomInf(HWND hwnd, HDC hdc, Room room);
  31. ///////////////////////////////////////////////////////
  32. //RenewData
  33. //功能:将数据区恢复为背景色
  34. //参数:设备环境hdc,Building结构
  35. //返回:无返回
  36. void RenewData(HDC hdc, RECT rectData);

4.2.3 显示搜索结果

显示搜索结果时,不同于以上的两种显示方式。当搜索点击确定时,整个系统的一个全局变量iSearch将会更改为搜索过程,对该变量取值范围在“managerSys.h”中做出了相关规定:

  1. #define SEARCHCOM 701
  2. #define NOSEARCH 702
  3. #define SEARCHBUI 703
  4. #define SEARCHROOM 704

同时,定义处于搜索状态如下:

  1. #define SEARCHING (iSearch==SEARCHCOM||iSearch==SEARCHBUI||iSearch==SEARCHROOM)

当处于搜索状态时,WM_PAINT消息中在左边ListBox显示为辅助链表(3.2)pComSearch(或pBuiSearch、pRoomSearch)中的数据,通过不停发送LB_ADDSTRING消息,添加项目,并在最后添加一条【退出搜索】。将左边上放的标题通过SetWindowText设置为“搜索结果”。同时响应其中的单击消息,只调用Draw*Inf函数显示对应信息。

显示搜索结果未应用特殊的函数,基本通过调用之前的函数即可实现功能。

4.3 编辑模块

4.3.1更改数据

更改数据分为两种情况:点击菜单中的更改、点击信息栏的“编辑”。

在点击菜单中的“更改”时,将会直接发送一条BM_CLICK消息给编辑按钮,相当于制造了一次点击。

在点击了信息栏中的“编辑”按钮时,保存状态转为False。首先判断当前信息区的状态,即被楼盘、楼栋或是房间占用。根据情况将会弹出相应的对话框,同时,读取信息区的楼栋号(或楼盘名、房间号),遍历链表检索该楼栋(或是楼盘、房间),之后将搜索到楼盘的相关信息通过SetWindowText函数【8】设置为对应信息编辑框的默认值。在用户对信息做出更改后,将检验是否与已在楼盘、楼栋、房间冲突,若不冲突,则将修改的信息录入链表,同时调用UpdateData函数,将链表的所有数据更新,并将其下的所有结构的inCom或buildingNum成员对应修改。无效化窗口,信息区规定显示编辑的信息更新版。

UpdateData函数为自定义函数,其声明如下:

  1. ///////////////////////////////////////////////////////
  2. //UpdataData
  3. //功能:更新整个链表的数据,包括房间数,均价等
  4. //参数:将要更新的链表的头指针的地址
  5. //返回:若完成所有更新则返回TRUE,否则返回FALSE
  6. BOOL UpdateData(Community **ppHead);

4.3.2 添加数据

添加数据分为三种情况,添加楼盘、楼栋和房间。

以添加房间为例。点击添加房间时,WndProc收到WM_COMMAND消息(其wParam为IDM_EDIT_ADD_ROOM),于是会调用DialogBox函数【10】,创建一个对话框。在对话框窗口过程AddRoomDlgProc来获取此时所在的楼栋和楼盘信息,将默认的信息通过SetWindowText函数发送到对话框中。当用户添加完所有数据之后,通过向编辑框发送EM_GETLINE消息,对Combo Box进行GetWindowText函数获取文本,以及选择框发送BM_GETCHECK消息获取选择状态来获取对话框中的所有信息。利用_ttoi,_ttof等函数【9】将所有的信息转化为对应的数据类型,然后储存在一个新建的房间结构体中。判断这个房间的房间号是否与同一楼栋中的房间号冲突,若不冲突,将这个结构体接入链表,否则弹出警告报错。

接入链表后,无效化整个客户区,并调用UpdateData函数后重绘整个客户区,信息区的为房间的信息。楼盘、楼栋的添加过程与此基本相似,具体流程如图4.1所示。

参与添加数据的函数共有三个窗口过程,同时有三个辅助函数用于将数据写入链表。具体的函数声明如下:

  1. ///////////////////////////////////////////////////////
  2. //“添加新楼盘”(AddCommunity)对话框窗口过程
  3. BOOL CALLBACK AddComDlgProc(HWND hDlg, UINT message,
  4. WPARAM wParam, LPARAM lParam);
  5. ///////////////////////////////////////////////////////
  6. //“添加新楼栋”(AddBuilding)对话框窗口过程
  7. BOOL CALLBACK AddBuiDlgProc(HWND hDlg, UINT message,
  8. WPARAM wParam, LPARAM lParam);

  1. ///////////////////////////////////////////////////////
  2. //“添加新房间”(AddRoom)对话框窗口过程
  3. BOOL CALLBACK AddRoomDlgProc(HWND hDlg, UINT message,
  4. WPARAM wParam, LPARAM lParam);
  5. ///////////////////////////////////////////////////////
  6. //AddComToList
  7. //功能:向链表中添加一个community节点
  8. //参数:将要添加的Community结构体(添加对象链表的头指针.全局变量提供)
  9. //返回:返回更新后链表头指针
  10. BOOL AddComToList(Community newCom, Community **head);
  11. ///////////////////////////////////////////////////////
  12. //AddBuiToList
  13. //功能:向链表中添加一个building节点
  14. //参数:将要添加的Building结构体,添加对象链表的头指针,所属楼盘号
  15. //返回:成功则返回TRUE,失败返回FALSE
  16. BOOL AddBuiToList(Building newBui, Community **head, int comNum);
  17. ///////////////////////////////////////////////////////
  18. //AddRoomToList
  19. //功能:向链表中添加一个Room节点
  20. //参数:将要添加的Room结构体,添加对象链表的头指针,所属楼盘号,所属楼栋号
  21. //返回:成功则返回TRUE,失败返回FALSE
  22. BOOL AddRoomToList(Room newRoom, Community **head,
  23. int comNum, int buiNum);

4.3.1 删除数据

删除数据分为三种情况:删除楼盘、楼栋和房间。同时系统提供两种删除方式:准确删除与快速删除。下面以以添加房间为例。

准确删除。点击添加房间时,WndProc收到WM_COMMAND消息(其wParam为IDM_EDIT_DEL_ROOM),于是会调用DialogBox函数【10】,创建一个对话框,要求用户输入对应的准确信息。其中楼盘允许在楼盘号与楼盘名中间进行选择。即在对话框窗口过程DelRoomDlgProc中处理复选框消息时,若用户选择第一个选项,则通过调用EnableWindow函数【10】将第一个窗口有效,第二个窗口无效。当用户添加完所有数据之后,通过判断复选框的选项和向编辑框发送EM_GETLINE消息来获取所有的数据。利用_ttoi,_ttof等函数【9】将所有的信息转化为对应的数据类型,然后遍历链表寻找知否有符合要求的房间。若找到,则直接从链表中删除该房间,若未找到,则弹出MessageBox提示该房间不存在。

删除链表后,无效化整个客户区,并调用UpdateData函数后重绘整个客户区,信息区的为删除的房间所在的楼栋信息。楼盘、楼栋的添加过程与此基本相似,具体流程如图4.2所示。

快速删除。快速删除主要体现在在浏览信息时,可以点击信息区右下角的“删除”按钮。此时读取目前所在的房间(或楼栋、楼盘)信息,之后遍历链表搜索该房间。搜索到该房间之后,弹出MessageBox询问用户是否确定删除该房间。若用户点击是,则调用删除函数将该房间从链表中删除。无效化整个窗口并发送WM_PAINT消息重绘窗口。若用户点击否,则不做删除,重绘窗口。

参与删除数据的函数共有三个窗口过程,同时有三个辅助函数用于将数据从链表中删除。具体的函数声明如下:

  1. ///////////////////////////////////////////////////////
  2. //“删除楼盘”(DeleteCommunity)对话框窗口过程
  3. BOOL CALLBACK DelComDlgProc(HWND hDlg, UINT message,
  4. WPARAM wParam, LPARAM lParam);
  5. ///////////////////////////////////////////////////////
  6. //“删除楼盘”(DeleteBui)对话框窗口过程
  7. BOOL CALLBACK DelBuiDlgProc(HWND hDlg, UINT message,
  8. WPARAM wParam, LPARAM lParam);
  9. ///////////////////////////////////////////////////////
  10. //“删除楼盘”(DeleteRoom)对话框窗口过程
  11. BOOL CALLBACK DelRoomDlgProc(HWND hDlg, UINT message,
  12. WPARAM wParam, LPARAM lParam);
  13. ///////////////////////////////////////////////////////
  14. //DelComInList
  15. //功能:删除链表中的一个Community节点
  16. //参数:将要删除的Community编号,添加对象链表的头指针的地址
  17. //返回:返回更新后链表头指针
  18. BOOL DelComInList(int comNum, Community **head);
  19. ///////////////////////////////////////////////////////
  20. //DelBuiInList
  21. //功能:删除链表中的一个Building节点
  22. //参数:将要删除的Building编号,添加对象链表的头指针的地址
  23. //返回:返回更新后链表头指针
  24. BOOL DelBuiInList(int comNum,int buiNum, Community **head);
  25. ///////////////////////////////////////////////////////
  26. //DelRoomInList
  27. //功能:删除链表中的一个Room节点
  28. //参数:将要删除的Room编号,添加对象链表的头指针的地址
  29. //返回:返回更新后链表头指针
  30. BOOL DelRoomInList(int comNum, int buiNum, int roomNum, Community **head);

4.4 查询模块

查询模块为弹出对话框,之后读取用户输入的信息,通过相关搜索函数将每一项的相似度与对应结构进行比较。(详见2.2显示模块)具体的实现过程如图4.3所示。

搜索结构所显示的排序方式以及原理在2.2显示模块中都有详细的介绍,搜索过程中显示的函数原型如下:

  1. ///////////////////////////////////////////////////////
  2. //计算出每一个楼栋的相似度
  3. //参数:标准SearchData结构,对比的楼栋,该楼栋所在楼盘
  4. //返回:这个输入信息与该楼栋的相似度
  5. int GetBuiSim(SearchData data, Community com, Building bui);
  6. ///////////////////////////////////////////////////////
  7. //计算出每一个房间的相似度
  8. //参数:标准SearchData结构,对比的房间,该房间所在楼栋、楼盘
  9. //返回:这个输入信息与该房间的相似度
  10. int GetRoomSim(SearchData data, Community com, Building bui, Room room);
  11. ///////////////////////////////////////////////////////
  12. //“搜索功能”(Search)对话框窗口过程
  13. BOOL CALLBACK SearchDlgProc(HWND hDlg, UINT message,
  14. WPARAM wParam, LPARAM lParam);
  15. ///////////////////////////////////////////////////////
  16. //对Com链表按照权重进行排序
  17. //参数:标准比较输入数据,排序的链表头指针
  18. //返回:返回为排完序的链表的头指针
  19. Community *RankCom(SearchData sData, Community *pComSearch);
  20. ///////////////////////////////////////////////////////
  21. //对Bui链表按照权重进行排序
  22. //参数:标准比较输入数据,排序的链表头指针
  23. //返回:返回为排完序的链表的头指针
  24. Building *RankBui(SearchData sData, Building *pBuiSearch);
  25. ///////////////////////////////////////////////////////
  26. //AddBuiToSearch
  27. //功能:创建一个只由bui组成的search
  28. //参数:将要添加的Building结构体,添加对象链表的头指针
  29. //返回:成功则返回TRUE,失败返回FALSE
  30. BOOL AddBuiToSearch(Building newCom, Building **head);
  31. ///////////////////////////////////////////////////////
  32. //对Room链表按照权重进行排序
  33. //参数:标准比较输入数据,排序的链表头指针
  34. //返回:返回为排完序的链表的头指针
  35. Room *RankRoom(SearchData sData, Room *pBuiSearch);
  36. ///////////////////////////////////////////////////////
  37. //计算出每一个楼盘的相似度
  38. //参数:标准SearchData结构,对比的楼盘
  39. //返回:这个输入信息与该楼盘的相似度
  40. int GetComSim(SearchData data, Community com);

5.5 统计模块

统计模块的主要体现在数据的更新与实现上,由于统计模块并无专门的菜单项,因此统计功能融入其它的模块中。

统计中最重要的函数为更新数据,功能为遍历链表,将楼栋数、房间数、平均价格计算并写入对应的结构体。函数原型如下:

  1. ///////////////////////////////////////////////////////
  2. //UpdataData
  3. //功能:更新整个链表的数据,包括房间数,均价等
  4. //参数:将要更新的链表的头指针的地址
  5. //返回:若完成所有更新则返回TRUE,否则返回FALSE
  6. BOOL UpdateData(Community **ppHead);

5.6 帮助模块

由于本软件界面较为简单,操作简洁,无需准备无帮助文档,帮助功能仅提供关于软件功能。即弹出对话框显示软件的基本信息,该对话框在资源中定义一些Static控件即可。

上传的附件 cloud_download 基于WIN32 API图形界面实现的楼盘管理系统.7z ( 804.68kb, 13次下载 )
error_outline 下载需要5点积分

发送私信

即使是不成熟的尝试,也胜于胎死腹中的策略

7
文章数
9
评论数
最近文章
eject