4.3 配置对话框窗口实现
4.3.1 创建属性表对话框
属性表是一个系统定义的对话框,它管理页及为他们提供一个公共的容器。一个属性表可以包含一页或者多页。一页可以包含设置项目的字体类型风格,大小,颜色等属性的控制。每一页可以有一个标签,用户根据标签来选择每一页。在创建属性表对话框时。过填充一双PROPSHEETPAGE结构定义了页(pages),在PROPSHEETHEADER函数中指定了它的地址,并调用了PropertySheet函数。对话框模板,图标和页的标签(label)被从应用程序的可执行文件中的资源装入。属性表的图标也同样被从应用程序的资源中装入(引用MSDN关于属性表的相关介绍)
typedef struct _PROPSHEETPAGE {
DWORD dwSize;
DWORD dwFlags;
HINSTANCE hInstance;
union {
LPCSTR pszTemplate;
LPCDLGTEMPLATE pResource;
};
union {
HICON hIcon;
LPCSTR pszIcon;
};
LPCSTR pszTitle;
DLGPROC pfnDlgProc;
LPARAM lParam;
LPFNPSPCALLBACK pfnCallback;
UINT FAR* pcRefParent;
} PROPSHEETPAGE, FAR* LPPROPSHEETPAGE;
实现的思想:
为了实现多页有效联系在一起。我们需要填充PROPSHEETPAGE结构的相关数据,
如图标,模板,函数过程,标题栏等。在创建一个属性表,我们必须定义一页或者多页。例如我们想创建四页,那么就需要定义一个数组,每一项就代表一页。
PROPSHEETPAGE psp[2];//创建两个属性页
PROPSHEETHEADER psh;//定义个对象
其次,在PROPSHEETHEADER函数中指定了它的地址,最后并调用了PropertySheet函如:PropertySheet(&psh);
通过获取这个地址,创建一个属性表对话框,并将创建的属性页链接在一起作为一个整体。
4.3.2 添加属性页
属性表可以嵌入多个页面,在规划好的后台设置的布局后,如果想增加几属性页,那么只需要我们再填充PROPSHEETPAGE 这个结构体相关的信息。
图4-3属性表与对话框关系图
PROPSHEETPAGE psp[2];//设置两页属性页
将其改变为我们所需要的页面数,如需要4页就改变其数组。
PROPSHEETPAGE psp[4];//设置四页属性页
其后,我们在创建两页的属性页里面的提示下,
psp[0].dwSize = sizeof(PROPSHEETPAGE);
psp[0].dwFlags = PSP_USEICONID | PSP_USETITLE;
psp[0].hInstance =hInst;
psp[0].pszTemplate =MAKEINTRESOURCE(IDD_Setusual);//应用某个模板
psp[0].pszIcon = NULL;//是否使用图标
psp[0].pfnDlgProc = (DLGPROC)Config_setusual;//窗口函数过程
psp[0].pszTitle = "常规";//标签
psp[0].lParam = 0;
psp[0].pfnCallback = NULL;
主要我们所要改变的其中包括模板pszTemplate,标题psTitle,函数过程pfnDlgProc,图标pszIcon等。而主要我们做的事情,就是在资源文件里面新建多几个对话框,然后把这些对话框作为属性页嵌入到属性表里面去。这样就可以完成添加属性页。
4.3.3 为属性页添加函数过程
配置对话框窗口的实现,当中还有一件事情要我们去完成的事情。我们增加了几个属性页面,这些页面是不具备功能。为此我们需要对每一个属性页面增加一个函数的过程,这些函数过程的作用是帮手我们完成后台设置的功能。在代码实现的过程中,我们应该注意到一个地方如:
psp[1].pfnDlgProc = (DLGPROC)Config_setkey;
Config_setkey这个就是我们所添加的一个函数名称。
下面为我们创建的一个函数过程:
BOOL WINAPI Config_setkey(HWND hWnd,UINT message, WPARAM wParam,LPARAM lParam)
{
//这里就是我们要添加的代码
}
这个就是其中一个属性页的函数过程,当中的代码就是要我们完成的功能。
4.4 后台配置文件
4.4.1 后台配置文件用途
讲到配置文件,应该先知道什么是用户配置文件,以及它的作用。
概念:什么是用户配置文件?
用户配置文件就是在用户登录时定义系统加载所需环境的设置和文件的集合。它包括所有用户专用的配置设置,如程序项目、屏幕颜色、网络连接、打印机连接、鼠标设置及窗口的大小和位置。
问: 用户配置文件的作用?
用户配置文件有利于帮助用户保存一些用户定义系统设置,起到备份的作用。
应用: 输入法的后台配置文件用途?
话说回头,输入法后台配置文件其实和用户配置文件是一样的,只是在说法上不同而已。我们主要利用配置文件所做的事情就是保存用户对输入法程序的一些基本设置,它的用途就是保存用户的设置。
因此,当我们了解了相关的配置文件,我们的后台设置的工具就可以开展了。
4.4.2 结构体设计
后台布局分析和规划完成后,我们要为整个设置的后台建立一个或者多个数据结构体,这些数据结构体作用在于保存用户设置的信息。这个数据结构体起到重要的作用。
其中,下面是在程序中,定义的一个结构体
typedef struct tagSETCONFIG
{
DWORD Set_shift; //设置shift
DWORD Set_ctrl; //设置ctrol键
DWORD Set_IDC_dot; //设置翻页控件(,. 句话与逗号)
DWORD Set_IDC_add; //设置翻页控件(+- 加号与减号)
DWORD Set_IDC_LeftAndRight; //设置翻页控件(左右控制键)
DWORD Set_IDC_Zkuohao; //设置翻页控件([] 中括号)
DWORD Set_ChineseorEnglist; //初始化英语还是中文状态
DWORD Set_QuanjiaoAndbanjiao;//初始化全角和半角
DWORD Set_ChinesedotAndEnglishdot;// 初始化英语和中文标点符号
DWORD Set_IDC_IsMouseFollow; //是否开启光标跟随事件
int Set_IDC_IDC_nCandNum; //设置候选字数
…………………………………
………………………………………
………………………………………
(省略)
} SETCONFIG;
4.4.3 写入配置文件
当用户在后台设置了所选的功能,每次应用的时候,都会保存在一份配置文件中,在这份配置文件,主要格式如下:左边为变量名,右边为保存设定的数据
[IME]
LEFTSHIFT=0
CTRL=0
LRkey=0
Zkuohao=0
……………
………………..
……………………
(省略)
将信息写入配置ini的函数有,
1.所用的WINAPI函数原型为:
BOOL WritePrivateProfileString( LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName );
其中各参数的意义
LPCTSTR lpAppName 是ini文件中的一个字段名.
LPCTSTR lpKeyName 是lpAppName下的一个键名,通俗讲就是变量名.
LPCTSTR lpString 是键值,也就是变量的值,不过必须为LPCTSTR型或CString型的.
LPCTSTR lpFileName 是完整的ini文件名
其中,第三个参数很多时候是其他类型的时候,可以通过sprintf来格式转换。
在头文件 #include<stdio.h>中 语法: string sprintf(string format, mixed [args]...);传回值: 字串
4.4.4 读取配置文件
问题:读取配置文件主要解决些什么?
配置文件的作用是保存用户的设置,读取配置文件实现是读取用户自己定义的设置。
解决办法:
保存了自定义的配置,同样还需要进行读取文件中的变量值,因为需要为它编写一个函数作为读取配置的函数。
Void Load_config()
{
//读取配置文件
}
为了实现这样的功能,我们只要设计一个读取配置文件的函数,通过利用如GetPrivateProfileString或者GetPrivateProfileInt 函数实现读取配置文件中的变量值,然后将这个变量值赋值给一个结构体当中一个全局变量,这个变量就会根据值来判断用户对程序上的设置。
、
4.4.5 调用配置文件
什么时候调用配置文件?根据我们的程序开始,就需要进行对配置文件进行加载。也就是说,当我们打开程序的时候,我们的程序就要把我们的加载我们的配置文件,这些配置文件,能够开启用户自选定功能,如皮肤切换,鼠标跟随,初始化状态窗口的状态贴图等等。
4.5 右键弹出菜单实现
4.5.1 设置菜单数据变量
菜单是属于系统上一种资源。在规划好功能之后,我们需要对其设置一些标识作为区分这些菜单子项目的每一个项目,方便日后调用。下图为主要的设置图。
图4-5 菜单对应变量图
名称说明:
为了方便读懂菜单的标识,菜单设置需要作一些处理。“IDM_”意思是菜单的标识,ID:为标识,M:解析为菜单英语MENU 的M大写开头。
主要变量说明:
菜单子项名称 |
菜单标识 |
功能作用 |
基本设置 |
IDM_SETTING |
调用后台设置对话框 |
更换皮肤 |
IDM_CHOOSESKIN |
选择皮肤更换 |
软键盘 |
IDM_SOFT |
软键盘设置 |
帮助 |
IDM_HELP |
关于输入法的帮助文档 |
关于输入法 |
IDM_ABOUT |
关于输入法的介绍 |
皮肤一 |
IDM_SKIN1 |
选择第一套皮肤 |
4.5.2 实现弹出菜单
通过鼠标的右键可以弹出浮动式的菜单,为了实现这一效果,首先要了解一个函数。
函数原型:BOOL TrackPopupMenu(HMENU hMenu,UINT uFlags,int x,int y,int nReserved,HWND hWnd,CONST RECT prcRect);
HMENU hMenu; // 菜单句柄
UINT uFlags;//屏幕位置和鼠标键的标志
int x;//屏幕水平坐标
int y;// 屏幕的垂直坐标
int nReserved;//reserved
HWND hWnd;//窗口句柄
CONST RECT prcRect;//矩形结构的地址
下图为鼠标右键弹出的图:
图4-5 菜单
函数功能:该函数在指定位置显示快捷菜单,并跟踪菜单项的选择。快捷菜单可出现在屏幕上的任何位置。
下面为创建浮动菜单的过程:
第一步:创建一个Menu资源,为菜单添加几个子项。
第二步:使用LoadMenu 获取菜单句柄,
第三步:使用GetSubMenu 激活下来菜单
第四步:使用TrackPopupMenu函数弹出浮动菜单
通过以上的步骤可以实现简单的弹出菜单,通过菜单设置的标识,可以实现一些类似按钮的触发事件。为了能够实现到鼠标右键弹出菜单,我们同样需要一点知道Windows消息WM_RBUTTONUP。这个消息的作用是当我们鼠标右键点击后产生的事件。
case WM_RBUTTONUP:
{
// 调用的函数
break;