用WxWidgets写了很久,用了WxSqlite来连接数据库,一切看上去都那么顺利。
我用的是Unicode的编译方式,开始没有预料到编码是个问题,但是慢慢编码问题开始显露
我发现,WxWidgets处理编码问题远没有C#牛逼。
举个例子,在C#里面我们可以这么写
string x = System.Web.HttpUtility.UrlEncode("刘", Encoding.GetEncoding(936));
%C1%F5
string x = System.Web.HttpUtility.UrlEncode("刘", Encoding.UTF8);
%E5%88%98
string x = System.Web.HttpUtility.UrlEncode("刘", Encoding.Unicode);
%18R
我在Wxwidgets的Unicode模式下尝试了很多的方法,但是没有一种方法能够正确进行URLdecode展现出“刘”这个字。
然而,在ANSI方式下的Wxwidgets就可以轻松URLdecode展现“刘”字。
我承认不是widgets不好,只是我的技术水平不够,还不知道怎么转换。
在这里附上我尝试的一些代码段,纪念一下我使用过可爱的wxwidgets。以后慢慢研究怎么在unicode模式下正确urldecode好了。
#define SPC_BASE16_TO_10(x) (((x) >= '0' && (x) <= '9') ? ((x) - '0') : /
(toupper((x)) - 'A' + 10))
wxString UrlDecode(wxString &url) {
size_t i=0;
wxString dest;
for (i = 0; i<url.length(); i++) {
if (url[i] == '+') dest += ' ';
else if (url[i] != '%' || !isxdigit(url[i + 1]) || !isxdigit(url [i + 2])) dest += url[i];
else {
dest += (SPC_BASE16_TO_10(url[i + 1]) * 16) + (SPC_BASE16_TO_10(url [i + 2]));
i += 2;
}
}
return dest;
}
wxString URLEncode(const wxString &str)
{
wxString ret;
wxString t;
for(unsigned int i = 0; i < str.length(); ++i)
{
wxChar c = str[i];
if( (c >= _T('A') && c <= _T('Z'))
|| (c >= _T('a') && c <= _T('z'))
|| (c >= _T('0') && c <= _T('9'))
|| c == _T('.') || c == _T('-') || c == _T('_') )
ret.Append(c);
else if(c == _T(' '))
ret.Append(_T('+'));
else
{
t.sprintf(_T("%%%02X"), (unsigned int) c);
ret.Append(t);
}
}
return ret;
}
static byte base16Chars[17] = "0123456789ABCDEF";
wxString URLEncode2(wxString sIn)
{
wxString sOut;
unsigned char curChar;
for ( unsigned int i = 0; i < sIn.Length(); i ++ ) {
curChar = sIn.GetChar( i );
if ( isalnum( curChar ) ) {
sOut += curChar;
} else if( isspace ( curChar ) ) {
sOut += wxT("+");
} else {
sOut += wxT("%");
sOut += base16Chars[ curChar >> 4];
sOut += base16Chars[ curChar & 0xf];
}
}
return sOut;
}
inline bool shouldEncode(char c){
if(c>='0' && c<='9') return false;
if(c>='a' && c<='z') return false;
if(c>='A' && c<='Z') return false;
if(c=='(' || c==')' || c=='$' || c=='!' || c=='*' || c==',' || c=='-' || c=='.' || c=='/' || c=='=' || c==':' || c=='?' || c=='@') return false;
return true;
}
wxString UrlEncode3(wxString source){
static const char *hex = "0123456789abcdef";
unsigned char ch;
wxString dest;
size_t source_index = 0;
while(source.length()>source_index)
{
ch = (unsigned char)source[source_index];
if(source[source_index] == ' ')
dest += '+';
else if( !shouldEncode(source[source_index])/* || source[source_index] == '/' || source[source_index] == '.'*/)
dest += source[source_index];
else
{
dest += '%';
dest += hex[(ch >> 4)&0xF];
dest += hex[ch % 16];
}
source_index++;
}
return dest;
}
wxString UrlDecode3(wxString &url) {
size_t i=0;
wxString dest;
for (i = 0; i<url.length(); i++) {
if (url[i] == '+') dest += ' ';
else if (url[i] != '%' || !isxdigit(url[i + 1]) || !isxdigit(url [i + 2])) dest += url[i];
else {
dest += (SPC_BASE16_TO_10(url[i + 1]) * 16) + (SPC_BASE16_TO_10(url [i + 2]));
i += 2;
}
}
return dest;
}
void URLEncode6(char*& data)
{
static char* hdig = ("0123456789abcdef");
char* obuf = new char[strlen(data) * 3 + 1];
char* optr = obuf;
char* dptr = data;
while (*dptr)
{
if (((*dptr >= 'a') && (*dptr <= 'z')) ||
((*dptr >= 'A') && (*dptr <= 'Z')) ||
((*dptr >= '0') && (*dptr <= '9')) ||
(*dptr == '/') || (*dptr == '-') || (*dptr == ':') || (*dptr == '#'))
{
*optr++ = *dptr++;
}
else
{
*optr++ = '%';
*optr++ = hdig[(*dptr >> 4) & 15];
*optr++ = hdig[*dptr & 15];
dptr++;
}
}
*optr++ = '/0';
delete[] data;
data = obuf;
}
/*
wxString xe= wxT("%C1%F5");
wxString x= wxT("%E5%88%98");
char* x3="%E5%88%98";
wxString x2=UrlDecode(x);
//wxString x4=wxHTTPBuilder::Base64Encode(wxT("刘"));
//wxString x5=wxHTTPBuilder::Base64Decode(x4);
wxString s=wxHTTPBuilder::URLDecode(xe);
const wxCharBuffer xs=s.mb_str(wxConvUTF8);
//const wxCharBuffer x7=wxConvUTF8.cMB2WX(((const wchar_t *)(s).c_str()));
//wxString xx43=wxString(s, wxConvLocal);
//const char* x21=x7.data();
//wxConvUTF8.cMB2WX(x3);
*/
//char * sc="刘";
//URLEncode6(sc);
wxString s=URLEncode(wxT("%R18"));
// s=UrlDecode3(s);
wxString tt=s;
最后,我想说的是,C#的功劳就是把人们从繁重的基础工作中解脱出来,使人们专注于最关键的架构以及功能。
于是在这个意义上说,C#有着一定的优势,尤其是你很在乎你的开发时间的情况下。
顺便说一些心得,用vs2008生成的代码要比code::blocks生成的代码小。
还有就是wxPack真的很好用
还有就是,自己编译wxwidgets不用wxpack也是可以的,你想好了你用什么模式unicode static debug,你就编译那一种就好了,挺快的,5分钟!wiki上说什么要3个小时,那个是吓唬人的,他说的只是全部都编译了才那么多时间呢。不过确实很耗硬盘空间,即使你之编译一点。恩
wxsqlite3这个很好用,但是sqlite3.lib不好弄,要手动生成,生成方法是copy mspdb80.dll到lib.exe和link.exe的目录下,然后写一个bat,LIB /MACHINE:IX86 /DEF:sqlite.def
其实也很简单的,但是还是很麻烦!
另外不建议用mingw里面的编译器去编译wx,这个会很大,还是建议你用vs的,但是 vs的编译器在codeblock里面经常出问题,于是你直接用vs好了。
说实话,我讨厌unicode,更喜欢utf8
哦,还有,wxformbuilder在vs下好用,在codeblocks下不好用,建议你在codeblocks下面用wxsmith做GUI
另外wxformbuilder在vs下面生成的代码是不能改的,要继承,然后重写方法,这个好麻烦。也许有插件?不知道。
我讨厌wxConvUTF8,一点不人性化。
做服务器的一些心得:
如果你想返回404,你不能光写一个什么404 not found,你还要加上Headder和相关数据,才行。要不然IE就在那里不动了。
hr.SetRC(wxT("404 Not Found"));
hr.AddHeader(wxT("Content-Type: text/html; charset=UTF8") );
hr.AddDataLine( wxT( "Not Found") );
还有content_type也是很有意思的。
if (url_ext==wxT(".htm"))
return wxT("text/html");
if (url_ext==wxT(".html"))
return wxT("text/html");
if (url_ext==wxT(".gif"))
return wxT("image/gif");
if (url_ext==wxT(".jpg")||url_ext==wxT(".jpeg"))
return wxT("image/jpeg");
if (url_ext==wxT(".bmp"))
return wxT("image/bitmap");
if (url_ext==wxT(".png"))
return wxT("image/png");
if (url_ext==wxT(".gz") || url_ext==wxT(".zip") || url_ext==wxT(".rar") || url_ext==wxT(".bz2") )
return wxT("application/binary");
if (url_ext==wxT(".css"))
return wxT("text/css");
if (url_ext==wxT(".js"))
return wxT("application/x-javascript");
if (url_ext==wxT(".xml"))
return wxT("text/xml");
if (url_ext==wxT(".pdf"))
return wxT("application/pdf");
return wxT("text/plain");