[软件]_[Windows]_[参考NSUserDefaults自定义Windows的BASUserDefaults]

场景:

1. 在Mac下Cocoa开发,可以使用NSUserDefaults很容易的存储配置信息,而且它还支持基本类型的NSDictionary,NSArray等复杂类型. 我们使用这个类来存储运行时配置,

比如多语言选项, 检查更新选项, 快捷键设置等等.这个信息自动存储在bundleid的相关位置.

参考: http://blog.csdn.net/yepeng2014/article/details/49003753

这种配置很方面, 如果是Windows的话唯一可以和它相提并论的是注册表了, 但是注册表不容易直观的通过路径查看到, 比较麻烦.

这点Windows的SDK真的可以参考Cocoa做好点,提供方便开发人员开发常规软件的API.

2. 这里模仿了NSUserDefaults的接口写了Windows版本的,目前只能简单的存储和读取字符串类型,原始类型,对象类型的话返回void*, 这是因为C++并没有id类型.

3. 这里主要是使用了rapidjson 来作为存储格式, 相对NSUserDefaults 的XML格式稍微简单些, 因为Json读写非常快.

4. 和软件无关,可以跨产品使用.

bas_user_defaults.h:

#ifndef __BAS_USER_DEFAULTS_H
#define __BAS_USER_DEFAULTS_H

#include "bas_exp.h"

#include <Windows.h>

// 使用json来表达内容.
class LIB_BASIC BASUserDefaults
{
public:
	~BASUserDefaults();
	static void InitStandardUserDefaults(const wchar_t* brand,const wchar_t* product);
	static BASUserDefaults* StandardUserDefaults();

	static void InitUserDefaults(const char* name,const wchar_t* path);
	static BASUserDefaults* GetUserDefaults(const char* name);

	void SetString(const char* key,const char* value);
	void SetInt(const char* key,int value);

	const char* GetString(const char* key);
	//1.返回rapidjson::Value对象.
	void* GetValueObject(const char* key);

	int GetInt(const char* key);
	DWORD GetRGB(const char* key);
	void WriteAll();

private:
	BASUserDefaults(const char* name,const wchar_t* path);
	void ReadAll();

	char* name_;
	wchar_t* path_;
	void* document_;

};

#endif

bas_user_defaults.cpp:

#include "basic/bas_user_defaults.h"

#include <vector>
#include <string>
#include <map>
#include <iostream>
#include <stdio.h>

#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
#include "rapidjson/filestream.h"
#include "rapidjson/stringbuffer.h"

#include "basic/bas_utility_sys.h"

static const char* gUserDefaultName = "UserDefault";
static wchar_t* gUserDefaultBrand = NULL;
static wchar_t* gUserDefaultProduct = NULL;

static std::map<std::string,BASUserDefaults*> gNameToDefault;

static rapidjson::Document* GetDocument(void* data)
{
	return (rapidjson::Document*)data;
}

BASUserDefaults::~BASUserDefaults()
{
	free(name_);
	free(path_);

}

void BASUserDefaults::InitStandardUserDefaults(const wchar_t* brand,const wchar_t* product)
{
	gUserDefaultBrand = wcsdup(brand);
	gUserDefaultProduct = wcsdup(product);

	wchar_t* appdata = BASUtilitySys::GetAppDataDir();
	wcscat(appdata,gUserDefaultBrand);
	::CreateDirectory(appdata,NULL);

	wcscat(appdata,L"\\");
	wcscat(appdata,gUserDefaultProduct);
	::CreateDirectory(appdata,NULL);
	wcscat(appdata,L"\\");

	wcscat(appdata,L"Preferences.json");
	InitUserDefaults(gUserDefaultName,appdata);

	free(appdata);
}

void BASUserDefaults::InitUserDefaults(const char* name,const wchar_t* path)
{
	gNameToDefault[name] = new BASUserDefaults(name,path);
}

void BASUserDefaults::ReadAll()
{
	rapidjson::Document* document = GetDocument(document_);

	FILE* file = _wfopen(path_,L"rb");
	if(file)
	{
		fseek(file,0,SEEK_END);
		long size = ftell(file);
		fseek(file,0,SEEK_SET);
		char* buf = (char*)malloc(size+1);
		memset(buf,0,size+1);
		fread(buf,size,1,file);
		buf[size] = 0;
		fclose(file);
		if(document->Parse<0>(buf).HasParseError())
		{
			std::cout << "parse error" << std::endl;
			document->SetObject();
		}
		free(buf);
	}
}

void BASUserDefaults::WriteAll()
{
	rapidjson::Document* document = GetDocument(document_);

	FILE* file = _wfopen(path_,L"wb");
	rapidjson::StringBuffer buffer;
	rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(buffer);
	document->Accept(writer);
	std::string result = buffer.GetString();
	fwrite((void*)result.data(),result.size(),1,file);
	fclose(file);

	delete document;
}

BASUserDefaults::BASUserDefaults(const char* name,const wchar_t* path)
{
	name_ = strdup(name);
	path_ = wcsdup(path);

	rapidjson::Document* document = new rapidjson::Document();
	document_ = document;
	document->SetObject();

	//读取路径下的json内容.
	ReadAll();

}

BASUserDefaults* BASUserDefaults::GetUserDefaults(const char* name)
{
	return gNameToDefault[name];
}

BASUserDefaults* BASUserDefaults::StandardUserDefaults()
{
	return GetUserDefaults(gUserDefaultName);
}

void BASUserDefaults::SetString(const char* key,const char* temp_value)
{
	rapidjson::Document* document = GetDocument(document_);
	rapidjson::Value value(rapidjson::kStringType);
	value.SetString(temp_value,strlen(temp_value),document->GetAllocator());
	document->AddMember(key,value,document->GetAllocator());
}

int BASUserDefaults::GetInt(const char* key)
{
	rapidjson::Document* document = GetDocument(document_);
	return (*document)[key].GetInt();
}

void* BASUserDefaults::GetValueObject(const char* key)
{
	rapidjson::Document* document = GetDocument(document_);
	rapidjson::Value& value = (*document)[key];
	return &value;
}

void BASUserDefaults::SetInt(const char* key,int temp_value)
{
	rapidjson::Document* document = GetDocument(document_);
	rapidjson::Value value(rapidjson::kNumberType);
	value.SetInt(temp_value);
	document->AddMember(key,value,document->GetAllocator());
}

const char* BASUserDefaults::GetString(const char* key)
{
	rapidjson::Document* document = GetDocument(document_);
	return (*document)[key].GetString();
}

DWORD BASUserDefaults::GetRGB(const char* key)
{
	rapidjson::Document* document = GetDocument(document_);
	const char* value = (*document)[key].GetString();
	char* temp = strdup(value);
	char* t = temp;

	char* p = strchr(temp,‘,‘);
	*p = 0;
	int r = atoi(temp);
	temp = p+1;
	p = strchr(temp,‘,‘);
	*p = 0;
	int g = atoi(temp);
	int b = atoi(p+1);

	free(t);
	return RGB(r,g,b);
}

使用情况1:  类似NSUserDefaults使用默认的配置, 会根据公司名和产品名来创建默认配置文件

软件启动时:

BASUserDefaults::InitStandardUserDefaults(UiUtilityProduct::GetCorporationW().c_str(),
UiUtilityProduct::GetProductAliasW().c_str());

软件关闭时:

BASUserDefaults* user = BASUserDefaults::StandardUserDefaults();
user->WriteAll();
delete user;

使用情况2: 读取随软件打包的配置文件,只读.

wchar_t* install_dir_temp = BASUtilityApp::GetProductInstallDir();
std::wstring url_path(install_dir_temp);
url_path.append(L"Option.json");
BASUserDefaults::InitUserDefaults("url",url_path.c_str());
free(install_dir_temp);

常见的配置文件:

{
    "help": "http://www.xxx.com/online-help",
    "purchase": "http://www.xxx.com/purchase/xxx.html",
    "usupport": "http://www.xxx.com/support.html",
    "color:toolbox:background":"217,250,243",
    "color:toolbar:tab:font":"0,0,0"
}

参考:

https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/index.html

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-11 11:13:44

[软件]_[Windows]_[参考NSUserDefaults自定义Windows的BASUserDefaults]的相关文章

[转] C#中如何截取Windows消息来触发自定义事件

原文 C#中如何截取Windows消息来触发自定义事件 在c#windows开发中,我们常常会遇到拦截windows消息,来触发某个特定任务的问题. 由于目前使用c#的开发人员非常多,而且大多数c#程序员都不是从Windwos c++转过来的对windows消息机制不怎么了解,遇到这类问题还是挺棘手的,我们公司有个同事问,就写这个小实例,帮助那些遇到此类问题的兄弟姐妹. 实现方式目前有两种: 1 使用Control类的虚方法WndProc来截取Windows消息 基类为Control类的所有控件

Windows API参考大全新编

书名:新编Windows API参考大全 作者:本书编写组 页数:981页 开数:16开 字数:2392千字 出版日期:2000年4月第二次印刷 出版社:电子工业出版社 书号:ISBN 7-5053-5777-8 定价:98.00元 内容简介 作为Microsoft 32位平台的应用程序编程接口,Win32 API是从事Windows应用程序开发所必备的.本书首先对Win32 API函数做完整的概述:然后收录五大类函数:窗口管理.图形设备接口.系统服务.国际特性以及网络服务:在附录部分,讲解如何

您在基于 Windows 7 的或基于 Windows Server 2008 R2 的计算机上读取器中插入智能卡时出现错误消息:&quot;设备驱动程序软件未能成功安装&quot;

http://support.microsoft.com/kb/976832/zh-cn http://support.microsoft.com/kb/976832/zh-tw 症状 当智能卡插入智能卡阅读器后时,Windows 尝试下载并安装智能卡 minidrivers 通过插服务卡.如果自定义的加密服务提供程序未在系统上安装智能卡的驱动程序在任一预配置位置,如 Windows 更新. WSUS 或 intranet 路径不可用,在通知区域中将收到以下错误消息: 未能成功安装设备驱动程序软

Windows的条形码软件开发工具包Barcode Reader Toolkit for Windows介绍

Softek Barcode Reader Toolkit是一款支持Windows的软件开发工具包(SDK),使您的应用程序可以从图像中提取条形码信息.API(应用程序接口)可用在.net, java, com, ocx 和 windows dll工具包中.标准版支持一维和二维条形码.通过条形码的位置可分离文件. 具体功能: 通常,这款SDK用在扫描包含条形码文件的应用程序中.调用工具包中的功能,可提取图像中的条形码值,然后将这个值定义为数据库类中的关键词.需要从数码相机中检测图像条形码控件的应

报表软件JS开发引用HTML DOM的windows对象

HTML DOM是W3C标准(是HTML文档对象模型的英文缩写,Document Object Model for HTML). HTML DOM定义了用于HTML的一些列标准的对象,以及访问和处理HTML文档的标准方法. 通过DOM,可以访问所有的HTML元素,连同他们所包含的文本和属性.可以对其中的内容进行修改和删除,同时也可以创建新的元素. 在JavaScript中可以访问并处理所有的HTML DOM对象(windows对象.location对象.document对象),动态地修改网页.

jdbc案例_分页_条件查询

客户信息增删改查系统 软件工程开发流程:1.瀑布模型 2.螺旋模型 RUP (Rational Unified Process,统一软件开发过程 ) 采用瀑布模型: 需求 --- 需求分析 --- 系统设计(概要.详细设计)---- 编码 --- 测试 --- 实施 --- 维护 * 瀑布模型 缺陷在编码结束之前,客户看不到最终软件产品 ,如果需求.设计出现明显错漏,导致软件后期无法维护,存在重大缺陷 * 瀑布模型对于 新型软件,需求不定软件 风险较大 敏捷开发理念:迭代开发模式 ,将系统功能分

Windows 7系统主机远程登录Windows Server 2008 R2系统服务器

实验目的 实现Windows 7系统主机成功远程登录到Windows Server 2008 R2系统服务器,并查看其E盘中的文件 实验环境 装有VMware软件的Windows 7系统实体机 实验步骤 一. 开启VMware,并打开Windows 7系统虚拟机和Windows Server 2008 R2系统虚拟服务器 二. 设置两台机器于同一网段内 1.设置服务器的IP地址 右击网络-属性-更改适配器设置-右击本地网络-属性-选择IPv4-单击属性-确定-关闭 2.将服务器置于VMnet2中

Lock锁_线程_线程域

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms; namespace Lock锁_线程_线程

白话windows server 2012 r2和windows 7创建ad域与配置(安全版)

文章的可读性非常重要,这里提供的是一键式操作指南,即使之前完全没有接触,也可以配置完成. ad域的创建是为了便于公司的集中化管理,提高公司运作效率和安全性. 我的操作环境,本机是kali linux,虚拟机virtualbox分别安装一个windows7和windows server 2012 r2. 现在iso镜像类网站很多,建议采用msdn,相对可靠,内容全面. 在虚拟机上安装windows7(用户名为pjzhang)和windows server 2012 r2,都是相对简单的,百度会出现