C++/SDK界面开发总结

这年代用C++/SDK开发界面的不多了,不是入门研究那绝壁是情怀,不过这东西还是有用,虽然麻烦了点,但可以使生成的exe文件非常小,对于一些对exe文件大小以及响应速度非常在乎的来说,这还是很好的选择
为避免误人子弟,这儿贴几个关键字,对于开发Windows窗体程序来说,这些都是不错的选择,1为个人最推荐使用的,2为其次,以此类推

  1. WinForm/WPF:这个就强大了,两种界面开发模式几乎可以满足在任何条件下的需要,并且C#程序可以在Linux下运行,在Windows下几乎无敌,只是响应比SDK界面稍微慢点,目测是几十毫秒的延迟
  2. wxWidgets:跨平台、强大的界面库,相对于Qt来说是优点是完全无限制,缺点是用的人并没Qt多,开发者社区人少
  3. UILib:强大的DuiLib的升级版,优点是小巧、免费,缺点是只支持Windows平台,另外由于DuiLib作者不参与维护后,建立的UiLib维护机制相当散乱,相当于一堆高手参与维护但基本是自己维护自己的
  4. MFC:对于新手入门来说,这就是麻烦C;对于用过几年MFC的来说,能用MFC就绝不用SDK;个人感觉,这库还是相当不错的,至少没SDK麻烦
  5. Qt:跨平台、强大的界面库,唯一瑕疵是使用LGPL开源协议,只可使用动态链接库,对于静态链接要收费
  6. WTL:从入门角度来说,WTL比MFC稍微简单点,效果比MFC炫酷,不过这个很久没更新咯,最新版本貌似是07年的
  7. CB++/Delphi:这个实际上就是C++ Builder自带的界面库VCL,开发环境一般为C++ Builder 6或者RAD Studio,对于新手来说开发界面相当轻松,不过有一个很大的问题,C++ Builder 6有时候会出BUG,RAD Studio与Visual Studio不兼容。另外Delphi 7开发界面还是很不错的,用的也是VCL界面库,但我不喜欢Pascal的语法,所以也没深入研究这个

继续阅读C++/SDK界面开发总结

C++11:智能指针

智能指针,顾名思义,也就是自动回收内存的指针形式,不用程序员刻意去释放,提高软件开发效率,同时也会提高软件鲁棒性。
C++11一共有4个智能指针,分别为auto_ptr、unique_ptr、shared_ptr、weak_ptr。其中auto_ptr由于存在设计问题,被标记为“已弃用”,将在未来某个C++版本中被移除。本文主要介绍其他三个指针形式。使用前首先包含 这个头文件
1、unique_ptr
这个智能指针的含义为,智能指针所管理的内存区域为独占状态,当另一个unique_ptr访问当前指针时,当前指针会失效,内存的控制权交给新指针。示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <memory>
using namespace std;
 
void test_ptr (unique_ptr<int> p) {
}
 
int main (int argc, char* argv []) {
    //构造一个unique_ptr
    unique_ptr</int><int> p = make_unique</int><int> (5);
    //打印指针内容
    cout < < *p << endl;
    //修改指针内容
    *p = 100;
    //打印指针内容
    cout << *p << endl;
    //将控制权交给函数参数
    test_ptr (move (p));
    //测试指针是否有效
    cout << p.get () << endl;
    return 0;
}

首先构造一个unique_ptr。unique_ptr构造方式以前一般为 unique_ptr p (new int); 这样的形式,构造时直接包含一个指针。后来在C++14中引入了make_unique,建议统一写成这样的格式。
构造时设置初始值为5,打印结果也为5,然后设置指针内容为100,这儿打印出来的结果也为100,然后使用移动语义,将控制权交给test_ptr函数,这时候main函数中p指针失效,然后函数什么也不做,当它返回时,实际上已经将指针指向的内存释放了。然后我们调用 get() 函数获取智能指针管理的指针地址,打印结果为00000000
可见智能指针用法上还是很简单的。
继续阅读C++11:智能指针

C++11:多线程与锁

多线程是小型软件开发必然的趋势。C++11将多线程相关操作全部集成到标准库中了,省去了某些坑库的编译,真是大大的方便了软件开发。多线程这个库简单方便实用,下面给出简单的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
 
volatile int val;
mutex mut;
 
void icrement () {
    for (int i = 0; i < 100000000; i++) {
        mut.lock ();
        val++;
        mut.unlock ();
    }
}
 
int main (int argc, char* argv []) {
    //创建两个线程
    thread t1 (icrement);
    thread t2 (icrement);
    //等待两个线程执行完
    t1.join ();
    t2.join ();
    cout << val << endl;
    return 0;
}

概念有点多。首先得引入thread与mutex这两个头文件,其中thread与线程有关,mutex与锁有关。然后是两个全局变量,由于两个线程都会访问,所以加上volatile关键字,代表不要对这变量进行优化,然后是mutex,这个就是锁咯。
然后,下面的main函数中,首先创建两个线程,然后等待两个线程执行完,然后输出结果。最后是increment函数,这函数循环一亿次,不停的加锁解锁,控制着val变量的访问。锁还提供一个函数,比如这样调用 mut.try_lock (); ,立即返回bool类型,true代表加锁成功,false代表加锁失败。
继续阅读C++11:多线程与锁

C++11:原子操作

在多线程开发中,为了确保数据安全性,经常需要对数据进行加锁、解锁处理。C++11中引入了原子的概念,简而言之就是访问它时它自动加锁解锁,从而使软件开发更为简便。
原子可谓一个既简单又复杂的概念。简单到访问它时就跟单线程访问一块内存一样简单,复杂的地方在于它的实现涉及到各种内存模型,在优化中经常会遇到。
下面给出一个简单的原子示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <thread>
#include <atomic>
using namespace std;
atomic_int val = { 0 };//这个类型也可以写作 atomic<int> 用于表示整型数据的原子
 
void icrement () {
    for (int i = 0; i < 100000000; i++) {
        val++;
    }
}
 
int main (int argc, char* argv []) {
    //创建两个线程
    thread t1 (icrement);
    thread t2 (icrement);
    //等待两个线程执行完
    t1.join ();
    t2.join ();
    cout << val << endl;
    return 0;
}

经过十几秒左右的等待后,代码执行完毕,结果不出所料,200000000。简单的原子操作差不多就是这样,atomic模板可以包括任何类型,另外原子的操作也与它本身的操作方式基本相同,因为原子模板重载了所有的运算符。
继续阅读C++11:原子操作

C++11:lambda表达式

这个实现的效果类似于匿名函数,不像C++98/03那样一个函数所有人都能调用,不公开不必要的接口,提高程序安全性。
首先来写个最简单的lambda表达式。

1
[]{};

对,5个字符就成为了一个lambda表达式了,虽然并没卵用,不过至少跨出了一步。这个lambda表达式实际上是精简后的表达式。不加以精简的话,原表达式应该像这样:

1
[](){};

看起来挺简单的,我也这么觉得:)
解释下,首先一对方括号代表捕获列表,含义后面再解释。然后是一对圆括号,代表lambda函数的参数列表,当参数为空可省略这对圆括号,就像上面5个字符的lambda表达式这样。接下来是一对大括号,这个和函数的大括号没什么区别了,里面可以加代码,可以加return。
继续阅读C++11:lambda表达式

C++11:变长模板的迭代与递归扩展

迭代的运行效率始终强于递归,递归始终比迭代方便开发。
变长模板属于C++11中比较复杂的技术,在此简单介绍下。在此贴出一个变长模板代码,为方便起见,参数类型全为int。如果需要不同的参数类型,只需要重载模板代码即可:

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;
 
template<class ... Args>
int Sum (Args... args) {
    return sizeof...(args);
}
 
int main (int argc, char* argv []) {
    cout < < Sum (1,2,23,124,4,23,43,24,32,4,23) << endl;
    return 0;
}

这是一个最简单的变长模板,首先是template定义,class后面加三个点就代表不固定长度。
接下来是Sum函数,在main函数的调用中实例化,被扩展为如下形式:

1
int Sum(int,int,int,int,int,int,int,int,int,int,int);

传了11个参数,就被实例化为11个参数形式。然后是sizeof...,这个宏是用来获取变长模板中元素的个数用的。我们调用时传了11个参数,它就返回11。程序运行的结果也相应为11。变长模板对于变长参数的优势之一为第一个参数不用定义参数个数(关于变长参数的访问详见深度研究C语言变长函数),但相应的劣势为无法直接访问参数。文章后面将简要介绍如何调用参数。
继续阅读C++11:变长模板的迭代与递归扩展

js前台获取URL参数

对于网页前台,有时候是需要获取网页参数的,比如https://www.fawdlstty.com/?p=57,js如何获取参数呢?这一个参数还好,如果参数多了那么解析就费事了。下面提供一种方法实现最便捷的方式获取网页参数。实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
function getRequest() {
	var url = location.search;
	var obj = {};
	if (url.indexOf('?') != -1) {
		url = url.substring(url.indexOf('?') + 1).split('&');
		for (var i = 0; i < url.length; i++) {
			var strs = url[i].split('=');
			obj[strs[0]] = unescape(strs[1]);
		}
	}
	return obj;
}

代码量很小,使用方式如下,比如,获取参数名为p的值:

1
2
var param = getRequest();
alert(param['p']);

调用也是相当方便呢

ASP.Net前台提交Post后,后台Session为空的解决

ASP.Net会在WebForm中加入一两个隐藏的参数(有时候是一个有时候是两个),用于提交form表单时识别Session,如下图所示:
vierstate
然而直接通过$.post()向后台提交信息,后台是得不到这两个参数的,故而无法识别Session,从而导致Session为空。除此之外,前台提交new FormData()生成的表单,后台也无法识别。解决方法是直接在Post参数中加入这两个临时变量即可。
继续阅读ASP.Net前台提交Post后,后台Session为空的解决

让jQuery.css()方法支持important属性

jQuery的css()方法支持直接设置元素的element,真是方便了你我他,美中不足的是不支持important属性。网上的一些高手就出了对策,下面转载一个个人认为相当不错的实现。
来源:http://stackoverflow.com/questions/2655925/how-to-apply-important-using-css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
(function($) {    
	if ($.fn.style) {
		return;
	}
 
	// Escape regex chars with \
	var escape = function(text) {
		return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
	};
 
	// For those who need them (< IE 9), add support for CSS functions
	var isStyleFuncSupported = !!CSSStyleDeclaration.prototype.getPropertyValue;
	if (!isStyleFuncSupported) {
		CSSStyleDeclaration.prototype.getPropertyValue = function(a) {
			return this.getAttribute(a);
		};
		CSSStyleDeclaration.prototype.setProperty = function(styleName, value, priority) {
			this.setAttribute(styleName, value);
			var priority = typeof priority != 'undefined' ? priority : '';
			if (priority != '') {
				// Add priority manually
				var rule = new RegExp(escape(styleName) + '\\s*:\\s*' + escape(value) + '(\\s*;)?', 'gmi');
				this.cssText = this.cssText.replace(rule, styleName + ': ' + value + ' !' + priority + ';');
			}
		};
		CSSStyleDeclaration.prototype.removeProperty = function(a) {
			return this.removeAttribute(a);
		};
		CSSStyleDeclaration.prototype.getPropertyPriority = function(styleName) {
			var rule = new RegExp(escape(styleName) + '\\s*:\\s*[^\\s]*\\s*!important(\\s*;)?', 'gmi');
			return rule.test(this.cssText) ? 'important' : '';
		}
	}
 
	// The style function
	$.fn.style = function(styleName, value, priority) {
		// DOM node
		var node = this.get(0);
		// Ensure we have a DOM node
		if (typeof node == 'undefined') {
			return this;
		}
		// CSSStyleDeclaration
		var style = this.get(0).style;
		// Getter/Setter
		if (typeof styleName != 'undefined') {
			if (typeof value != 'undefined') {
				// Set style property
				priority = typeof priority != 'undefined' ? priority : '';
				style.setProperty(styleName, value, priority);
				return this;
			} else {
				// Get style property
				return style.getPropertyValue(styleName);
			}
		} else {
			// Get CSSStyleDeclaration
			return style;
		}
	};
})(jQuery);

调用方式:

1
2
3
4
5
6
7
8
9
$('#id').style('display', 'block !important');
//上面是我认为最好理解的调用方式,下面是作者给出的调用方式
var div = $('someDiv');
console.log(div.style('color'));
div.style('color', 'red');
console.log(div.style('color'));
div.style('color', 'blue', 'important');
console.log(div.style('color'));
console.log(div.style().getPropertyPriority('color'));

js Array扩展方法

js的Array对象的处理能力比较强大,下面几个函数是给它再新增几个扩展方法使其更方便使用
部分方法在最新版Webkit已经实现,但由于IE8等低端浏览器还占有大批用户,所以还得实现一遍,另外splice不是很方便使用,个人感觉用insert、remove方法更直观

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//数组处理程序
if (!Array.prototype.forEach) {
	Array.prototype.forEach = function (callback, thisArg) {
		var T, k;
		if (this == null) {
			throw new TypeError(" this is null or not defined");
		}
		var O = Object(this);
		var len = O.length >>> 0; // Hack to convert O.length to a UInt32  
		if ({}.toString.call(callback) != "[object Function]") {
			throw new TypeError(callback + " is not a function");
		}
		if (thisArg) {
			T = thisArg;
		}
		k = 0;
		while (k < len) {
			var kValue;
			if (k in O) {
				kValue = O[k];
				callback.call(T, kValue, k, O);
			}
			k++;
		}
	};
}
 
//查询数组中是否存在元素
if (!Array.prototype.in_array) {
	Array.prototype.in_array = function (e) {
		for (i = 0; i < this.length; i++) {
			if (this[i] == e)
				return true;
		}
		return false;
	}
}
 
//插入元素
if (!Array.prototype.insert) {
	Array.prototype.insert = function (index, elem) {
		return this.splice(index, 0, elem);
	}
}
 
//删除元素
if (!Array.prototype.remove) {
	Array.prototype.remove = function (index) {
		return this.splice(index, 1);
	}
}

js日期格式化的实现

功能比较简单,一个函数实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if (!Date.prototype.Format) {
	Date.prototype.Format = function (formatStr) {
		var str = formatStr;
		var Week = ['日', '一', '二', '三', '四', '五', '六'];
		str = str.replace(/yyyy|YYYY/, this.getFullYear());
		str = str.replace(/yy|YY/, (this.getYear() % 100) > 9 ? (this.getYear() % 100).toString() : '0' + (this.getYear() % 100));
		str = str.replace(/MM/, this.getMonth() > 9 ? this.getMonth().toString() : '0' + this.getMonth());
		str = str.replace(/M/g, this.getMonth());
		str = str.replace(/w|W/g, Week[this.getDay()]);
		str = str.replace(/dd|DD/, this.getDate() > 9 ? this.getDate().toString() : '0' + this.getDate());
		str = str.replace(/d|D/g, this.getDate());
		str = str.replace(/hh|HH/, this.getHours() > 9 ? this.getHours().toString() : '0' + this.getHours());
		str = str.replace(/h|H/g, this.getHours());
		str = str.replace(/mm/, this.getMinutes() > 9 ? this.getMinutes().toString() : '0' + this.getMinutes());
		str = str.replace(/m/g, this.getMinutes());
		str = str.replace(/ss|SS/, this.getSeconds() > 9 ? this.getSeconds().toString() : '0' + this.getSeconds());
		str = str.replace(/s|S/g, this.getSeconds());
		return str;
	}
}

这里给Date对象增加一个Format属性,调用方法示例:date.Format('yyyy-MM-dd');