Wxwidgets和C#的感悟

本来想开发一个跨平台的程序,一个跨平台的WebServer,Linux, MAC,Windows CE
用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

无论如何,这些带着百分号的编码,或者是经过Base64的编码,或者是javascript里面escape的编码,比如%u5218
我在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");

6 comments

  1. 香港 说道:

    高手,谢谢分享。。看着一点吃力

  2. Chance Gapinski 说道:

    I simply want to mention I’m beginner to blogs and certainly loved you’re blog site. Most likely I’m planning to bookmark your blog . You surely come with great article content. Thank you for revealing your web page.

  3. Karolyn Susong 说道:

    I just added this blog to my rss reader, excellent stuff. Cannot get enough!

  4. Rocky Ascher 说道:

    My brother recommended I might like this blog. He used to be entirely right. This post truly made my day. You can not imagine just how much time I had spent for this info! Thanks!

  5. Katerine Apt 说道:

    This is really fascinating, You’re an excessively professional blogger. I’ve joined your rss feed and sit up for searching for extra of your wonderful post. Additionally, I’ve shared your website in my social networks!

  6. Del Siver 说道:

    This website doesn’t render properly on my droid – you may want to try and repair that

发表评论

电子邮件地址不会被公开。