﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-简单为美</title><link>http://www.cppblog.com/len/</link><description /><language>zh-cn</language><lastBuildDate>Sun, 05 Apr 2026 16:40:27 GMT</lastBuildDate><pubDate>Sun, 05 Apr 2026 16:40:27 GMT</pubDate><ttl>60</ttl><item><title>live space和cppblog到micolog的迁移工具</title><link>http://www.cppblog.com/len/archive/2010/11/08/133029.html</link><dc:creator>len</dc:creator><author>len</author><pubDate>Mon, 08 Nov 2010 12:55:00 GMT</pubDate><guid>http://www.cppblog.com/len/archive/2010/11/08/133029.html</guid><wfw:comment>http://www.cppblog.com/len/comments/133029.html</wfw:comment><comments>http://www.cppblog.com/len/archive/2010/11/08/133029.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/len/comments/commentRss/133029.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/len/services/trackbacks/133029.html</trackback:ping><description><![CDATA[
		<div class="en_body">
				<div class="en_body">
						<p>Livespace要在明年关闭了，搭建了micolog在google app engine，方便以后自己挣腾。上次用生拙的C#写个live space到livespace的博客迁移工具，使用metaweblog接口，见 <a href="http://http//blog.lengoo.com/?p=147201&amp;code=aghsZW4taG9tZXINCxIFRW50cnkYgf4IDA">Live Spaces新旧空间迁移方法</a> 。上次使用getRecentPosts函数依次取得最近的一篇，然后存档后发表后，删除。这次通过正则表达式分析网页内容，获取到postid后，再使有getPost接口获取文章，再进行发表，而且这次使用python写成的。</p>
						<p>metaweblog的内容不再叙述，其实这个协议写得真不怎么样，没有检索文章的接口，要让人硬生生地从网页中分析出postid来。因此解析postid是这个迁移工具的重要内容。</p>
						<pre>#获取www.cppblog.com样式的postid列表<br />def getCppblogId(blog):<br />  url='http://www.cppblog.com/'+blog['user']+'/default.html?page=1&amp;OnlyTitle=1'<br />  urlfile = urllib.urlopen(url)<br />  html = urlfile.read()<br />  #获取存档页码数<br />  pattern = re.compile(r'http://www.cppblog.com/'+blog['user']+'/default.html\?page=(\d+)&amp;OnlyTitle=1')<br />  pages = [1]<br />  pages += pattern.findall(html)<br /><br />  ids=[]<br />  for p in pages:<br />    url= 'http://www.cppblog.com/'+blog['user']+'/default.html?page='+str(p)+'&amp;OnlyTitle=1'<br />    urlfile = urllib.urlopen(url)<br />    html = urlfile.read()<br />    pattern = re.compile(r'http://www.cppblog.com/'+blog['user']+'/admin/EditPosts.aspx\?postid=(\d+)')<br />    id = pattern.findall(html)<br />    ids += id<br />  return ids<br /></pre>
						<p>利用存档页面得到总共页数（或许页数多了或有问题，未验证），然后在每页解析出postid，cppblog较简单</p>
						<pre>def getLivespaceId(blog):<br />  ids=[]<br />  url=blog['user']+'.spaces.live.com/blog/'<br />  i=0<br />  while True:<br />    url='http://'+url<br />    urlfile = urllib.urlopen(url)<br />    html = urlfile.read()<br />    #print html<br />    pattern = re.compile(r'entrycns!'+'([a-zA-Z0-9!]*)')<br />    id = pattern.findall(html)<br />    ids += id<br />    pattern = re.compile(blog['user']+'.{1,50}pagedir=Next[^"]*')<br />    urls = pattern.findall(html)<br />    i=i+1<br />    if len(urls) ==0:<br />      break<br />    url = unescape(urls[0])<br />  return ids<br /></pre>
						<p>live space没有总共的页数，只能一直next下去，发现没有next按钮了就停止，在每页再解析出postid来,unescape是自定义函数，目的是将html编码转换为像！等符号。</p>
						<p>在迁移post时出现未micolog中定义的目录（category)会出错，因此迁移工具里如果碰到未定义过的类别，会自动舍弃掉。因此在使用
时需要在micolog里定义原先blog的类别，以致不会出现目录丢失的现象。此迁移工具在python2.5下完成，只要在源码中修改中开头的
srcBlog和dstBlog定义里的用户名，密码，webapi即可使用。源码中还实现BlogXML类，用于存档为xml格式，但未用于主程序中。</p>
						<a href="http://www.lengoo.com/media/aghsZW4taG9tZXINCxIFTWVkaWEY8ZcQDA/goblog.py?a=download">迁移工具源码</a>
				</div>
				<a href="http://www.lengoo.com/media/aghsZW4taG9tZXINCxIFTWVkaWEY8ZcQDA/goblog.py?a=download">
				</a>
		</div>
<img src ="http://www.cppblog.com/len/aggbug/133029.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/len/" target="_blank">len</a> 2010-11-08 20:55 <a href="http://www.cppblog.com/len/archive/2010/11/08/133029.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网络书签：Google bookmarks和FF插件</title><link>http://www.cppblog.com/len/archive/2008/09/25/62778.html</link><dc:creator>len</dc:creator><author>len</author><pubDate>Thu, 25 Sep 2008 12:06:00 GMT</pubDate><guid>http://www.cppblog.com/len/archive/2008/09/25/62778.html</guid><wfw:comment>http://www.cppblog.com/len/comments/62778.html</wfw:comment><comments>http://www.cppblog.com/len/archive/2008/09/25/62778.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/len/comments/commentRss/62778.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/len/services/trackbacks/62778.html</trackback:ping><description><![CDATA[<p>网络书签自从<a href="http://del.icio.us/">del.icio.us</a>推出后，各个网络巨头都推出了相应的服务，对于各个书签服务，我针对了自己的情况进行了一番小调查后，确定下用<a href="http://www.google.com/bookmarks/?hl=en">google bookmarks</a>服务。虽然del.icio.us美味书签最早推出，并有些特别的工功能，有着很大的用户群，但是我感觉它更偏向社交化的web服务，如将好的书签共享等，有着好友的功能，而我更偏向于需要一种简洁的书签存储功能。再有就是美味书签改版，对于网络安全功能过于注重，导致一种不好的用户体验，比如密码要数字字母混合，并且不能与用户名有太多重合等，还有密码最多线上保存两周。这些安全措施我都知道，但比一些公司密码管理还严，这至于吗？</p>  <p>国内的也出现了许多对应的web 2.0的网站，但是我没试用。还有一个选择就是baidu的<a href="http://cang.baidu.com">搜藏</a>，除了网页快照这个功能比较吸人外，其他并无亮点。最早看中google书签是因为它的开放性，比如搜藏都没有导出功能，而google就有导出，不怕用户流失，这一点蛮赞的。但是就其本身来说，使用并不方便，后来我使用了一直比较反感的工具条后，又开始使用它的书签，除了添加方便以外，整理和查找功能都比较薄弱。比如在线上，不能直接拖拽进行标签的分类，要手工点击编辑。google对这个服务不怎么看中，自推出以后，没有什么新的功能增加，希望以后有类似网页快照的存档功能就好了。</p>  <p>现在使用firefox3浏览器后，找到了<a href="https://addons.mozilla.org/en-US/firefox/addon/2888">GMarks</a>插件，它能直接存取google书签，包含一个边栏，工具栏，和一个书签快速查找框，可进行批量修改，删除书签，删除标签等等功能。它也可以在没有安装google工具条的情况下使用，还有定制工具栏等，最妙的是有了google工具条中没有的查找功能，不然在上千条书签找到你需要的，那是有点儿困难的。现在我将自己的收藏全都保存到google书签了，这样以后重装系统，再不用做备份了，而且在不同的机子上都可以用。</p>  <p>顺便说下，如何将FF3的书签导入到google书签服务中，那就使用google工具条，里面书签选项里有导入功能的，很简单。</p><img src ="http://www.cppblog.com/len/aggbug/62778.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/len/" target="_blank">len</a> 2008-09-25 20:06 <a href="http://www.cppblog.com/len/archive/2008/09/25/62778.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Live Spaces新旧空间迁移方法</title><link>http://www.cppblog.com/len/archive/2008/09/24/62712.html</link><dc:creator>len</dc:creator><author>len</author><pubDate>Wed, 24 Sep 2008 13:50:00 GMT</pubDate><guid>http://www.cppblog.com/len/archive/2008/09/24/62712.html</guid><wfw:comment>http://www.cppblog.com/len/comments/62712.html</wfw:comment><comments>http://www.cppblog.com/len/archive/2008/09/24/62712.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/len/comments/commentRss/62712.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/len/services/trackbacks/62712.html</trackback:ping><description><![CDATA[
		<p>微软启用了新的live域名，有许多人将hotmail之类的帐号转到新的域名，这就出现了如何将原帐号下的个人信息转移到新帐号的问题。对于live messager的联系人列表可采用其联系人选项中的导入导出功能，而最麻烦当属将live spaces的空间博客转移到新的帐号名下。最直接方法就是联系微软管理员，将你旧帐号下的空间所有权转移到新帐号名下，但是业务上是否可行不得而知。因此转而另一方法，开新的空间，将旧空间的博客转移到新空间来，本文就是采用这种思路，顺带提及下live api的简单使用。</p>
		<p>Windows Live Spaces MetaWeblog API提供了给外部程序进行文章内容设置和读取的功能。API使用了XML—RPC协议来在客户端应用程序与Weblog服务器端进行通讯。</p>
		<p>为了使用MetaWeblog API编辑空间中的博文内容，首先需要在空间启用E-mail发布功能，并设置密码字。</p>
		<ol>
				<li>到你的空间中的Options-&gt;E-mail Publishing选项进行配置</li>
				<li>打开E-mail发布功能，并选择 secred word的密码字。</li>
		</ol>
		<p>在程序中会用到用户名和密码，如果你的空间地址为： oldname.spaces.live.com，则用户名就是<strong>oldname</strong>,而不是你的live id，密码则是上面设置的<strong>secred word</strong>,而不是live id的密码。</p>
		<p>现在的MetaWeblogApi能进行发布新博文，编辑现有的博文，获取指定博文，获取类别列表，获取最近发布的博文，删除博文，获取用户博客信息，获取用户信息等功能。由这些功能，想迁移博客内容，首先需要获取到旧空间里的博文。我们自然想到用<a href="http://msdn.microsoft.com/en-us/library/aa905674.aspx">MetaWeblogAPI metaWeblog.getRecentPosts Method</a>函数，指定一个较大的值，然后获取全部的博文。很可惜，对于live spaces值只能取20,也就是说只能获取最近20篇博文。顺便提下，这里的20篇包括你己发布的，和存在空间里的草稿，这些草稿有时候并不会在空间里显示出来，但是操作时会有表示。如果用<a href="http://msdn.microsoft.com/en-us/library/aa905669.aspx">MetaWeblogAPI metaWeblog.getPost Method</a>，需要知道指定博文的id号，没有获取到全部博文id的方法作辅助，这又是一个因难。</p>
		<p>最后我采用了将metaWeblog.getRecentPosts方法的获取值设为1，每次取最近的一篇博文，然后记录id号，将这博文用<a href="http://msdn.microsoft.com/en-us/library/aa905673.aspx">MetaWeblogAPI metaWeblog.newPost Method</a>发表到新空间，然后用<a href="http://msdn.microsoft.com/en-us/library/aa905663.aspx">MetaWeblogAPI blogger.deletePost Method</a>将这id号的博文从旧空间中删去，重复进行，直到无法从旧空间里获取到博文。在程序实现借用了MSDN中的示例，为了防止网络故障之类以及做了备份，先是将获取博文内容写到本地文件，再进行删除。</p>
		<p>程序中还要说明的是，由于live spaces服务器使用非标准的时间格式，造成用<em>DateTime.Now</em>和获取到的博文的<em>dateCreated</em>都是"1/1/0001 12:00:00 AM"的格式，这需要在Invoke方法调用前加上this.NonStandard = XmlRpcNonStandard.AllowNonStandardDateTime语句。还有需要用到CookComputing.XmlRpcV2.dll，它实现了.net 2.0版本的XML-RPC协议，己包含在文末的源码中。如果是.net 1.1，需要其他相应的文件，可具体参见<a title="http://www.xmlrpc.com/metaWeblogApi" href="http://www.xmlrpc.com/metaWeblogApi">http://www.xmlrpc.com/metaWeblogApi</a>。</p>
		<p>最后要提下的是，程序只用于我自己的空间迁移，再加上不懂C#，用户名和密码之类都硬编码了，MetaWeblog之类的方法也应能用于像cppblog之类用wordpress的博客空间。这些部分加之完善，应能做个博客搬家工具的。</p>
		<p>参考：</p>
		<p>
				<a href="/Files/len/LiveSpaceMigration.zip">文中的迁移工具源码下载</a>
		</p>
		<p>
				<a href="http://msdn.microsoft.com/en-us/library/bb259702.aspx">MDSN Windows Live Spaces SDKs</a>
		</p>
<img src ="http://www.cppblog.com/len/aggbug/62712.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/len/" target="_blank">len</a> 2008-09-24 21:50 <a href="http://www.cppblog.com/len/archive/2008/09/24/62712.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>披着Chrome外衣的Firefox</title><link>http://www.cppblog.com/len/archive/2008/09/07/61239.html</link><dc:creator>len</dc:creator><author>len</author><pubDate>Sun, 07 Sep 2008 10:45:00 GMT</pubDate><guid>http://www.cppblog.com/len/archive/2008/09/07/61239.html</guid><wfw:comment>http://www.cppblog.com/len/comments/61239.html</wfw:comment><comments>http://www.cppblog.com/len/archive/2008/09/07/61239.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/len/comments/commentRss/61239.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/len/services/trackbacks/61239.html</trackback:ping><description><![CDATA[
		<p>Google的chrome浏览器一出来，我就被它的简洁风格给吸引住了，试用了几天，总体上还不错。但是还有几个问题，一是扩展太少，用些地方用起来不方便，像它自家的google工具栏都还没有开始支持。二是有时候在切换tab的时候，感觉有明显的停滞感，不知是否是多进程切换的原因，三是还有些网站不支持chrome。</p>
		<p>因为这些种种原因，我切换回了firefox 3。对于ff3，我也是刚刚用，但是越用越顺手，特别是插件机制，可以把玩好长时间。正像别人说过的那样，没有插件的ff3，还不如IE呢。于是通过设置，将自己的Firefox打造成了chrome风格，先上全屏截图，初始页是快速拨号，因为隐私关系，把它们都复位了，效果跟chrome差不多的。</p>
		<p>
				<a href="/images/cppblog_com/len/WindowsLiveWriter/ChromeFirefox_EF0C/firefox-chrome_4.png">
						<img style="border: 0px none ;" alt="firefox-chrome" src="http://www.cppblog.com/images/cppblog_com/len/WindowsLiveWriter/ChromeFirefox_EF0C/firefox-chrome_thumb_1.png" border="0" height="484" width="644" />
				</a>
		</p>
		<p>下面介绍简要操作步骤：</p>
		<p>
				<strong>1、Chrome主题风格 Chromifox</strong>是仿Chrome的主题，现处于实验版本阶段，因此下载安载需要以网站注册用户的身份登陆。下载地址为：<a title="https://addons.mozilla.org/en-US/firefox/addon/8782" href="https://addons.mozilla.org/en-US/firefox/addon/8782">https://addons.mozilla.org/en-US/firefox/addon/8782</a></p>
		<p>
				<strong>2、去除菜单栏 </strong>需要安装<strong>Compact Menu 2</strong>的插件，它可以定制原来的菜单栏为单个按钮或图标。下载地址为：<a title="https://addons.mozilla.org/en-US/firefox/addon/4550" href="https://addons.mozilla.org/en-US/firefox/addon/4550">https://addons.mozilla.org/en-US/firefox/addon/4550</a></p>
		<p>
				<strong>3、去除标题栏</strong> 这工作稍微有点儿麻烦，需要一个插件和一个脚本。Custom Buttons 2扩展提供创建，维护，导入，导出工具栏按钮的基础代码，也就是你可以用javascript代码写些特定用途的按钮。下载地址为：<a title="https://addons.mozilla.org/en-US/firefox/addon/5066" href="https://addons.mozilla.org/en-US/firefox/addon/5066">https://addons.mozilla.org/en-US/firefox/addon/5066</a>。安装完成后，再使用一个为隐藏标题栏而定制的脚本，地址为：<a title="http://custombuttons2.com/forum/viewtopic.php?f=35&amp;t=523" href="http://custombuttons2.com/forum/viewtopic.php?f=35&amp;t=523">http://custombuttons2.com/forum/viewtopic.php?f=35&amp;t=523</a>，点击其中的<a href="custombutton://%3C%3Fxml%20version%3D%221.0%22%3F%3E%0A%3Ccustombutton%20xmlns%3Acb%3D%22http%3A//custombuttons2.com/%22%3E%0A%20%20%3CCb2Ver%3E2.0.7.4%3C/Cb2Ver%3E%0A%20%20%3Cname%3EToggle%20Chrome%3C/name%3E%0A%20%20%3Cimage%3E%3C%21%5BCDATA%5Bdata%3Aimage/png%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAWElEQVR4Xs3RQQqAMAxE0T+SK7bH0LPoMdpD1kVpJRJ0JfiWITBDIhqdcMbcGAoh0aARE7DwwhCFBAfeClDJxrSJae+pTxF/WjDX/JNLXt+seOneIcfvPgGTthCzF0BPtwAAAABJRU5ErkJggg%3D%3D%5D%5D%3E%3C/image%3E%0A%20%20%3Cmode%3E0%3C/mode%3E%0A%20%20%3Ccode%3E%3C%21%5BCDATA%5B/*Code*/%5D%5D%3E%3C/code%3E%0A%20%20%3Cinitcode%3E%3C%21%5BCDATA%5Bfunction%20hideChrome%28%29%20%7B%0A%20%20if%20%28navigator.platform%20%3D%3D%20%22Win32%22%29%20%7B%0A%20%20%20%20window.moveTo%280%2C0%29%3B%0A%20%20%20%20window.maximize%28%29%3B%0A%20%20%20%20document.getElementById%28%22main-window%22%29.setAttribute%28%27hidechrome%27%2C%27true%27%29%3B%0A%20%20%20%20//%20preserve%20small%20area%20for%20taskbar%20to%20appear%0A%20%20%20%20window.resizeTo%28screen.availWidth%2C%20screen.availHeight-2%29%3B%0A%20%20%7D%20else%20%7B%0A%20%20%20%20document.getElementById%28%22main-window%22%29.setAttribute%28%27hidechrome%27%2C%27true%27%29%3B%0A%20%20%20%20window.moveTo%280%2C0%29%3B%0A%20%20%20%20window.resizeTo%28screen.availWidth%2C%20screen.availHeight%29%3B%0A%20%20%20%20window.maximize%28%29%3B%0A%20%20%7D%0A%7D%0A%0A//%20COMMENT%20OUT%20THE%20NEXT%20LINE%20TO%20START%20BROWSER%20NORMALLY%0AhideChrome%28%29%3B%0A%0Athis.leftclick%20%20%20%3D%20function%28evt%29%7B%0A%0A%20%20function%20showChrome%28%29%20%7B%0A%20%20%20%20if%20%28navigator.platform%20%3D%3D%20%22Win32%22%29%20%7B%0A%20%20%20%20%20%20document.getElementById%28%22main-window%22%29.setAttribute%28%27hidechrome%27%2C%27false%27%29%3B%0A%20%20%20%20%20%20window.resizeTo%28screen.availWidth%2C%20screen.availHeight%29%3B%0A%20%20%20%20%20%20window.maximize%28%29%3B%0A%20%20%20%20%20%20window.resizeTo%28screen.availWidth%2C%20screen.availHeight%29%3B%0A%20%20%20%20%7D%20else%20%7B%20%20%20%20%20%0A%20%20%20%20%20%20document.getElementById%28%22main-window%22%29.setAttribute%28%27hidechrome%27%2C%27false%27%29%3B%0A%20%20%20%20%20%20window.maximize%28%29%3B%0A%20%20%20%20%20%20window.maximize%28%29%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20function%20toggleChrome%28%29%20%7B%0A%20%20%20%20var%20mainWindow%20%3D%20document.getElementById%28%22main-window%22%29%3B%0A%20%20%20%20var%20isFullScreen%20%3D%20mainWindow.getAttribute%28%27hidechrome%27%29%3B%0A%09%09%09%0A%20%20%20%20if%20%28isFullScreen%20%3D%3D%20%22%22%20%7C%7C%20isFullScreen%20%3D%3D%20%27false%27%29%20%7B%0A%20%20%20%20%20%20hideChrome%28%29%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20showChrome%28%29%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%0AtoggleChrome%28%29%3B%0A%7D%0A%0Athis.setAttribute%28%27onclick%27%2C%20%27gQuot%28event%2C%20this%29%27%29%3B%20//%20Calls%20the%20Global%20MouseClick%20handler%20gQuot%0A%0Athis.style.opacity%20%3D%20%27.65%27%3B%0Athis.setAttribute%28%27onmouseover%27%2C%20%27custombuttons.ButtonBrt%28event%29%3B%27%20%29%3B%0Athis.setAttribute%28%27onmouseout%27%2C%20%27custombuttons.ButtonDim%28event%29%3B%27%20%29%3B%0A%0Athis.setAttribute%28%22author%22%2C%27nicholas%27%29%3B%09%09%09%09%09%09%09%09//%20Stores%20Author.%0Athis.setAttribute%28%22version%22%2C%2720080306.00%27%29%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%09//%20Stores%20Version.%0Athis.setAttribute%28%22homepage%22%2C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%09%09%09//%20Stores%20Homepage.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22http%3A//custombuttons2.com/forum/viewtopic.php%3Ff%3D35%26t%3D%22%20+%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22523%22%29%3B%0Athis.setAttribute%28%22dependency%22%2C%27FF%202.0.*%2CCB%202.0.*%27%29%3B%09%09%09%09%09%09//%20Stores%20Dependency.%0Athis.setAttribute%28%">Toggle Chrome</a>链接和<a href="custombutton://%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%3Ccustombutton%20xmlns%3Acb%3D%22http%3A//custombuttons2.com/%22%3E%0A%20%20%3CCb2Ver%3E2.0.7.6%3C/Cb2Ver%3E%0A%20%20%3Cname%3EToggle%20Chrome/Maximized%3C/name%3E%0A%20%20%3Cimage%3E%3C%21%5BCDATA%5Bdata%3Aimage/png%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAQAAAC1+jfqAAAAWElEQVR4Xs3RQQqAMAxE0T+SK7bH0LPoMdpD1kVpJRJ0JfiWITBDIhqdcMbcGAoh0aARE7DwwhCFBAfeClDJxrSJae+pTxF/WjDX/JNLXt+seOneIcfvPgGTthCzF0BPtwAAAABJRU5ErkJggg%3D%3D%5D%5D%3E%3C/image%3E%0A%20%20%3Cmode%3E0%3C/mode%3E%0A%20%20%3Ccode%3E%3C%21%5BCDATA%5B/*Code*/%5D%5D%3E%3C/code%3E%0A%20%20%3Cinitcode%3E%3C%21%5BCDATA%5Bfunction%20hideChrome%28%29%20%7B%0A%20%20if%20%28navigator.platform%20%3D%3D%20%22Win32%22%29%20%7B%0A%20%20%20%20window.moveTo%280%2C0%29%3B%0A%20%20%20%20window.maximize%28%29%3B%0A%20%20%20%20document.getElementById%28%22main-window%22%29.setAttribute%28%27hidechrome%27%2C%27true%27%29%3B%0A%20%20%20%20//%20preserve%20small%20area%20for%20taskbar%20to%20appear%0A%20%20%20%20window.resizeTo%28screen.availWidth%2C%20screen.availHeight-2%29%3B%0A%20%20%7D%20else%20%7B%0A%20%20%20%20document.getElementById%28%22main-window%22%29.setAttribute%28%27hidechrome%27%2C%27true%27%29%3B%0A%20%20%20%20window.moveTo%280%2C0%29%3B%0A%20%20%20%20window.resizeTo%28screen.availWidth%2C%20screen.availHeight%29%3B%0A%20%20%20%20window.maximize%28%29%3B%0A%20%20%7D%0A%7D%0A%0A//%20COMMENT%20OUT%20THE%20NEXT%20LINE%20TO%20START%20BROWSER%20NORMALLY%0AhideChrome%28%29%3B%0A%0Athis.leftclick%20%20%20%3D%20function%28evt%29%7B%0A%0A%20%20function%20showChrome%28%29%20%7B%0A%20%20%20%20if%20%28navigator.platform%20%3D%3D%20%22Win32%22%29%20%7B%0A%20%20%20%20%20%20document.getElementById%28%22main-window%22%29.setAttribute%28%27hidechrome%27%2C%27false%27%29%3B%0A%20%20%20%20%20%20window.resizeTo%28screen.availWidth%2C%20screen.availHeight%29%3B%0A%20%20%20%20%20%20window.maximize%28%29%3B%0A%20%20%20%20%7D%20else%20%7B%20%20%20%20%20%0A%20%20%20%20%20%20document.getElementById%28%22main-window%22%29.setAttribute%28%27hidechrome%27%2C%27false%27%29%3B%0A%20%20%20%20%20%20window.maximize%28%29%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20function%20toggleChrome%28%29%20%7B%0A%20%20%20%20var%20mainWindow%20%3D%20document.getElementById%28%22main-window%22%29%3B%0A%20%20%20%20var%20isFullScreen%20%3D%20mainWindow.getAttribute%28%27hidechrome%27%29%3B%0A%09%09%09%0A%20%20%20%20if%20%28isFullScreen%20%3D%3D%20%22%22%20%7C%7C%20isFullScreen%20%3D%3D%20%27false%27%29%20%7B%0A%20%20%20%20%20%20hideChrome%28%29%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20showChrome%28%29%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%0AtoggleChrome%28%29%3B%0A%7D%0A%0Athis.setAttribute%28%27onclick%27%2C%20%27gQuot%28event%2C%20this%29%27%29%3B%20//%20Calls%20the%20Global%20MouseClick%20handler%20gQuot%0A%0Athis.style.opacity%20%3D%20%27.65%27%3B%0Athis.setAttribute%28%27onmouseover%27%2C%20%27custombuttons.ButtonBrt%28event%29%3B%27%20%29%3B%0Athis.setAttribute%28%27onmouseout%27%2C%20%27custombuttons.ButtonDim%28event%29%3B%27%20%29%3B%0A%0Athis.setAttribute%28%22author%22%2C%27nicholas%27%29%3B%09%09%09%09%09%09%09%09//%20Stores%20Author.%0Athis.setAttribute%28%22version%22%2C%2720080622.00%27%29%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%09//%20Stores%20Version.%0Athis.setAttribute%28%22homepage%22%2C%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%09%09%09//%20Stores%20Homepage.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22http%3A//custombuttons2.com/forum/viewtopic.php%3Ff%3D35%26t%3D%22%20+%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22523%22%29%3B%0Athis.setAttribute%28%22dependency%22%2C%27FF%202.0.*%2CCB%202.0.*%27%29%3B%09%09%09%09%09%09//%20Stores%20Dependency.%0Athis.setAttribute%28%22status%22%2C%27Complete%27%29%3B%09%09%09%09%09%09%09%09//%20Stores%20Devstatus.%0Athis.setAtt">Toggle Chrome/Maximized</a>，即可安装。</p>
		<p>
				<strong>4、隐藏状态栏 </strong>无需任何插件，只需菜单栏的“查看”中的“状态栏”不要勾选上即可。</p>
		<p>
				<strong>5、快速拨号 Speed Dial</strong>和<strong>Fast Dial</strong>这两个插件均能提供，我现使用Speed Dial，地址为<a title="https://addons.mozilla.org/en-US/firefox/addon/4810" href="https://addons.mozilla.org/en-US/firefox/addon/4810">https://addons.mozilla.org/en-US/firefox/addon/4810</a>，另Fast Dial的地址为<a title="https://addons.mozilla.org/en-US/firefox/addon/5721" href="https://addons.mozilla.org/en-US/firefox/addon/5721">https://addons.mozilla.org/en-US/firefox/addon/5721</a>。</p>
		<p>其他诸如隐身模式、下载状态栏、将网站转换为独立的应用程序都可实现，具体可参见：<a title="http://www.cnbeta.com/articles/64031.htm" href="http://www.cnbeta.com/articles/64031.htm">http://www.cnbeta.com/articles/64031.htm</a></p>
		<h3>
		</h3>
		<h3>我的扩展列表</h3>
		<p>附带我在用的一些有用的插件功能，对于一般的用户来讲，这些功能也会大大节省你的时间，提高你上网浏览的体验。这些可能是最基本的，高级的要随你自己，你的地盘，你做主。</p>
		<p>
				<a href="https://addons.mozilla.org/en-US/firefox/addon/1419">IE Tab</a> 有些网站不支持非IE内核的怎么办，先不要有抱怨，有了它让你自由切换到IE的内核，但是外部功能不会减少，必备</p>
		<p>
				<a href="https://addons.mozilla.org/en-US/firefox/addon/6366">FireGestures</a> 鼠标手势，我是从Maxthon转过来的，这个功能太好用了。这个插件更强大，可以Tab，按键，滚轮上都可应用</p>
		<p>
				<a href="https://addons.mozilla.org/en-US/firefox/addon/6639">Easy Dragtogo</a> 类似于鼠标手势，有些超链接只要一拖，就可按设置在新tab或在另一tab打开，不需要再用右键了。我对FireGestures还不熟，不知道这功能是否可用FireGestures代替,这功能现在还需要</p>
		<p>
				<a href="https://addons.mozilla.org/en-US/firefox/addon/220">Flashgot</a> 文件下载管理，我用于管理flashget工具，内置支持许多下载工具</p>
		<p>
				<a href="https://addons.mozilla.org/en-US/firefox/addon/1865">Adblock</a> 没有广告的世界真清静，虽然Firefox自身的拦截能力己经很强了，但是它提供更强大的定制能力，一切由你自己定</p>
		<p>
				<a href="https://addons.mozilla.org/en-US/firefox/addon/722">Noscript</a> 提高浏览安全，可禁止一些恶意的脚本，可用效对付一些XSS跨站攻击等</p>
		<p>
				<a href="https://addons.mozilla.org/en-US/firefox/addon/2464">FoxyProxy</a> 如果你需要时常在代理服务器上进行切换的话，这非常用帮助。如果结合像Tor之类的工具，那么爬墙也不是件困难的事了。</p>
<img src ="http://www.cppblog.com/len/aggbug/61239.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/len/" target="_blank">len</a> 2008-09-07 18:45 <a href="http://www.cppblog.com/len/archive/2008/09/07/61239.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简简单单用py2exe打包python脚本</title><link>http://www.cppblog.com/len/archive/2008/08/11/58547.html</link><dc:creator>len</dc:creator><author>len</author><pubDate>Mon, 11 Aug 2008 11:19:00 GMT</pubDate><guid>http://www.cppblog.com/len/archive/2008/08/11/58547.html</guid><wfw:comment>http://www.cppblog.com/len/comments/58547.html</wfw:comment><comments>http://www.cppblog.com/len/archive/2008/08/11/58547.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/len/comments/commentRss/58547.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/len/services/trackbacks/58547.html</trackback:ping><description><![CDATA[<p>py2exe是实用的python脚本工具，可以将python脚本程序转换为exe执行文件。这样你的python程序就可以没有安装python运行时环境的电脑里运行了。py2exe方便地提取出python运行时所需要的文件档案，你需要做的就是写一个两三行的安装脚本文件。</p>  <p>py2exe可以从<a title="http://sourceforge.net/projects/py2exe/" href="http://sourceforge.net/projects/py2exe/">http://sourceforge.net/projects/py2exe/</a>下载，唯一需要注意的是下载与你python版本号对应的版本，简单的英文教程<a title="http://www.py2exe.org/index.cgi/Tutorial" href="http://www.py2exe.org/index.cgi/Tutorial">http://www.py2exe.org/index.cgi/Tutorial</a>非常容易入门。</p>  <p>对早先写的一个<a href="http://www.cppblog.com/len/archive/2008/07/02/55174.html">代理验证脚本</a>进行exe文件封装作为示例，这测试脚本名为HttpProxyTester.py。</p>  <p>首先，最好测试运行一下待封装的脚本以确定没有问题，然后在HttpProxyTester.py脚本的同级目录新建一setup.py文件。</p>  <pre class="code"># setup.py

from distutils.core import setup
import py2exe

setup(console=['HttpProxyTester.py'])</pre>

<p>上面的文件首先引入了distutils模块，这模块随python安装分发的，也就是说内置的。接着导入py3exe模块，它其实对distutils做了一些功能扩展。接下来的语句说明是控制台运行。对于windows的GUI模式运行，而不出控制台窗口，则需要setup(windows=['xxx'])之类指令，这对于pyWidget程序将很有用。</p>

<p>在完成安装脚本后，接下来就是在控制台下运行这脚本。</p>

<pre class="console">&gt;python setup.py py2exe</pre>

<p>这时会打印出许多log信息，并在同级目录下出现两个新的文件夹：build和dist。build文件夹下是py2exe生成的一些临时文件，dist就是需要分发的文件内容，可以这文件夹打包，然后在别的机子上运行了。</p>

<p>总之，py2exe非常简单实用，三分钟就可以搞定。</p><img src ="http://www.cppblog.com/len/aggbug/58547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/len/" target="_blank">len</a> 2008-08-11 19:19 <a href="http://www.cppblog.com/len/archive/2008/08/11/58547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Python类、模块、包</title><link>http://www.cppblog.com/len/archive/2008/07/24/57078.html</link><dc:creator>len</dc:creator><author>len</author><pubDate>Thu, 24 Jul 2008 11:42:00 GMT</pubDate><guid>http://www.cppblog.com/len/archive/2008/07/24/57078.html</guid><wfw:comment>http://www.cppblog.com/len/comments/57078.html</wfw:comment><comments>http://www.cppblog.com/len/archive/2008/07/24/57078.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/len/comments/commentRss/57078.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/len/services/trackbacks/57078.html</trackback:ping><description><![CDATA[<p>Python在处理功能复用和功能颗粒度划分时采用了类、模块、包的结构。这种处理跟C++中的类和名字空间类似，但更接近于Java所采用的概念。</p>  <h3>类</h3>  <p>类的概念在许多语言中出现，很容易理解。它将数据和操作进行封装，以便将来的复用。</p>  <h3>模块</h3>  <p>模块，在Python可理解为对应于一个文件。在创建了一个脚本文件后，定义了某些函数和变量。你在其他需要这些功能的文件中，导入这模块，就可重用这些函数和变量。一般用<em>module_name.fun_name</em>，和<em>module_name.var_name</em>进行使用。这样的语义用法使模块看起来很像类或者名字空间，可将<em>module_name</em> 理解为名字限定符。模块名就是文件名去掉.py后缀。下面演示了一个简单的例子：</p>  <pre class="code">#moduel1.py
def say(word):
    print word

#caller.py
import module1

print __name__
print module1.__name__
module1.say('hello')</pre>

<pre class="console">$ python caller.py
__main__
module1
hello</pre>

<p>例子中演示了从文件中调用模块的方法。这里还展示了一个有趣的模块属性<em>__name__</em>，它的值由Python解释器设定。如果脚本文件是作为主程序调用，其值就设为__main__，如果是作为模块被其他文件导入，它的值就是其文件名。这个属性非常有用，常可用来进行模块内置测试使用，你会经常在一些地方看到类似于下面的写法，这些语句只在作为主程序调用时才被执行。</p>

<pre class="code">if __name__ == '__main__':
    app = wxapp(0)
    app.MainLoop()</pre>

<h4>模块搜索路径</h4>

<p>上面的例子中，当<em>module1</em>被导入后，python解释器就在当前目录下寻找module1.py的文件，然后再从环境变量<a>PYTHONPATH</a>寻找，如果这环境变量没有设定，也不要紧，解释器还会在安装预先设定的的一些目录寻找。这就是在导入下面这些标准模块，一切美好事情能发生的原因。</p>

<pre class="code">import os
import sys
import threading
...</pre>

<p>这些搜索目录可在运行时动态改变，比如将module1.py不放在当前目录，而放在一个冷僻的角落里。这里你就需要通过某种途径，如sys.path，来告知Python了。sys.path返回的是模块搜索列表，通过前后的输出对比和代码，应能理悟到如何增加新路径的方法了吧。非常简单，就是使用list的append()或insert()增加新的目录。</p>

<pre class="code">#module2.py
import sys
import os

print sys.path
workpath = os.path.dirname(os.path.abspath(sys.argv[0]))
sys.path.insert(0, os.path.join(workpath, 'modules'))
print sys.path</pre>

<pre class="console">$ python module2.py
['e:\\Project\\Python', 'C:\\WINDOWS\\system32\\python25.zip', ...]
['e:\\Project\\Python\\modules', 'e:\\Project\\Python', 'C:\\WINDOWS\\system32\\python25.zip', ...]</pre>

<h4>其他的要点</h4>

<p>模块能像包含函数定义一样，可包含一些可执行语句。这些可执行语句通常用来进行模块的初始化工作。这些语句只在模块第一次被导入时被执行。这非常重要，有些人以为这些语句会多次导入多次执行，其实不然。</p>

<p>模块在被导入执行时，python解释器为加快程序的启动速度，会在与模块文件同一目录下生成.pyc文件。我们知道python是解释性的脚本语言，而.pyc是经过编译后的字节码，这一工作会自动完成，而无需程序员手动执行。</p>

<h3>包</h3>

<p>在创建许许多多模块后，我们可能希望将某些功能相近的文件组织在同一文件夹下，这里就需要运用包的概念了。包对应于文件夹，使用包的方式跟模块也类似，唯一需要注意的是，当文件夹当作包使用时，文件夹需要包含__init__.py文件，主要是为了避免将文件夹名当作普通的字符串。__init__.py的内容可以为空，一般用来进行包的某些初始化工作或者设置__all__值，__all__是在<em>from package-name import *</em>这语句使用的，全部导出定义过的模块。</p><img src ="http://www.cppblog.com/len/aggbug/57078.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/len/" target="_blank">len</a> 2008-07-24 19:42 <a href="http://www.cppblog.com/len/archive/2008/07/24/57078.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>wxPython和XRC文件实现i18n</title><link>http://www.cppblog.com/len/archive/2008/07/15/56229.html</link><dc:creator>len</dc:creator><author>len</author><pubDate>Tue, 15 Jul 2008 12:21:00 GMT</pubDate><guid>http://www.cppblog.com/len/archive/2008/07/15/56229.html</guid><wfw:comment>http://www.cppblog.com/len/comments/56229.html</wfw:comment><comments>http://www.cppblog.com/len/archive/2008/07/15/56229.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/len/comments/commentRss/56229.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/len/services/trackbacks/56229.html</trackback:ping><description><![CDATA[
		<p>应用程序国际化，在开源世界里常以i18n被提及，i18n是Internationalization的简写，正好18个字母。在wxPython程序进行i18n，如果字符串是编码在源文件中时，完全可按照python程序的i18n的方法，即使用gexttext和locale模块。而wxPython程序在使用XRC文件做为界面资源时，则应使用wx.Locale模块，它封装了区域化相关的操作。i18n，或者国际化实际上涉及到语言习惯，数字格式等等类别的内容。这里只介绍语言多国化，将一个简单的英文程序转换为中文，涉及到源文件，可从<a href="/Files/len/wx.zip">这里</a>下载。</p>
		<h3>创建PO文件</h3>
		<p>PO文件是Portable Object文件的简称，它包含需要翻译的字符串。我们需要从源文件进行提取。首先，对源文件test.py编辑，标识代码里需要翻译的字符串内容。我们使用_("xx")的方法，这种形式可能在许多开源源代码中见识过。</p>
		<pre class="code">#加载菜单栏
menubar = rc.LoadMenuBar('IDR_MENU')</pre>
		<p>这里的IDR_MENU是资源标识ID，不需要翻译，因此不做改变，而下面的代码：</p>
		<pre class="code">info.SetVersion('1.0')
info.SetDescription('XRC i18n Demo')</pre>
		<p>'XRC i18n Demo'是描述性的文本，需要进行翻译，将需要处理为</p>
		<pre class="code">info.SetVersion('1.0')
info.SetDescription(_('XRC i18n Demo'))</pre>
		<p>接着需要生成.pot(Portable Object Template)，这是po的模板文件。在将来程序可能配置成其他语种，其他语言的po文件都从它而来。为了创建这文件，需要用到GNU gettext工具集中的xgettext。向xgettext传入些必要的信息，来创建.pot文件。</p>
		<pre class="console">&gt;xgetttext --output=test.pot test.py</pre>
		<p>我们将wxPython界面以XRC文件保存了，那里同样有要翻译的字符串需要提取。用XRCed工具将XRC生成python代码，勾选上'Generate gettext strings'项即可。将源文件和XRC生成的test_xrc.py文件一起处理，生成一个test.pot。</p>
		<pre class="console">&gt;xgettext --output=test.pot test.py test_xrc.py</pre>
		<p>将得到的test.pot另存为test.po文件，然后进行翻译编辑，在这过程中文件需要使用utf-8编码。将对应的英文翻译成中文，将charset更改为utf-8。</p>
		<pre class="code">"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: test.py:19
msgid "XRC i18n Demo"
msgstr "XRC 国际化示例"
...</pre>
		<p>.pot和.po这些文件都是文本文件，主要供翻译者使用。为了使程序在运行时能获取相关的翻译的内容，要进行所谓的编译过程，将文本文件转换为二进制文件.mo。这里用了gettext工具集中的另一程序msgfmt。</p>
		<pre class="console">&gt; msgfmt --output=test.mo test.po</pre>
		<p>因为windows下没有像linux像有公共存储.mo文件的目录，保持平台的迁移性，在应用程序本地目录下新建locale目录，用来存放编译过的.mo文件，然后将test.mo移动至locale目录。在完成这些步骤后，就转入代码方面的更改了。</p>
		<h3>wxPython代码更改</h3>
		<p>原先的代码只需要做小改动：</p>
		<pre class="code">def OnInit(self):
    wx.Locale.AddCatalogLookupPathPrefix('locale')
    self.locale = wx.Locale(wx.LANGUAGE_CHINESE_SIMPLIFIED)
    self.locale.AddCatalog('test')
    import __builtin__
    __builtin__.__dict__['_'] = wx.GetTranslation</pre>
		<p>首先，增加了新的目录文件路径，这将使wxPython搜索这个目录，寻找匹配的.mo文件。接着创建wx.Locale对象，将其初始化为简体中文，这将对应于zh_CN。最后将wx.GetTranslation做了一全局映射，这样你在其他类中，比如示例中TestFrame也能使用_('xx')调用。这样wxPython的i18n工作就完成了，下面是翻译前后的界面截图。</p>
		<p>
				<a href="/images/cppblog_com/len/WindowsLiveWriter/wxPythonXRCi18n_10874/wxpython_2.png">
						<img style="border-width: 0px;" alt="wxpython" src="http://www.cppblog.com/images/cppblog_com/len/WindowsLiveWriter/wxPythonXRCi18n_10874/wxpython_thumb.png" border="0" height="400" width="644" />
				</a>
		</p>
		<h3>一些有益的讨论</h3>
		<h4>.mo文件的查找目录</h4>
		<p>如果你将locale目录下的test.mo文件删除掉，然后将test.py中的wx.LANGUAGE_CHINESE_SIMPLIFIED改为wx.LANGUAGE_CHINESE，重新运行程序看看。发现界面变成了如下的繁体中文，但是菜单'档案'下的Exit还是英文。</p>
		<p>
				<a href="/images/cppblog_com/len/WindowsLiveWriter/wxPythonXRCi18n_10874/wxzh_2.png">
						<img style="border-width: 0px;" alt="wxzh" src="http://www.cppblog.com/images/cppblog_com/len/WindowsLiveWriter/wxPythonXRCi18n_10874/wxzh_thumb.png" border="0" height="77" width="404" />
				</a>
		</p>
		<p>因为缺失.mo文件，但又指定wx.LANGUAGE_CHINESE，wxPython运行时使用了wxstd.mo文件。wxstd.mo有许多预编译好的常见字符串的对应关系，它随wxPython发布，在wx/locale下有许多语言版本的wxstd.mo。</p>
		<p>对于wxPython会对待查目录"DIR"来搜索.mo文件，查找它下面的这些目录,(DIR/LANG/LC_MESSAGES;DIR/LANG;DIR),对于哪些是待查目录，各个系统下又有不同，在所有的平台上,LC_PATH环境变量指定的目录将成为待查目录，在Linux下/share/locale, /usr/share/locale, /usr/lib/locale, /usr/locale /share/locale以及当前目录将是待查目录。在上面我们已经用过AddCatalogLookupPathPrefix()函数，其作用就是增加自己的待查目录。</p>
		<p>在示例程序中，将test.mo放在locale\zh_CN\LC_MESSAGES或者locale\zh\LC_MESSAGES同样是可行的。但是如果使用wx.LANGUAGE_CHINESE指定，则zh_CN目录将不可行，因为它只是特化目录，指简体中文，而zh目录同样适用。</p>
		<h4>工具链再讨论</h4>
		<p>gettext进行国际化是开源社区的主流方案，它也提供了许多实用工具供使用。上面提到了xgettext,msgfmt，还有msginit.exe，它将根据.pot文件创建新的.po文件，然后初始化一些元信息，像作者信息，项目，以及编码等，当然也可像上面的手工编辑。msgmerge.exe将两个.po文件进行合并。除了使用GNU Gettext工具集，也可使用随python发布的tool\i18n目录下pygettext.py和msgfmt.py，它们等同于上述的两个工具。</p>
		<p>对于编辑.po文件，可以尝试一下<a href="http://www.poedit.net/index.php">Poedit</a>,它提供了图形化的编辑环境，其他功能我就不清楚了。</p>
<img src ="http://www.cppblog.com/len/aggbug/56229.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/len/" target="_blank">len</a> 2008-07-15 20:21 <a href="http://www.cppblog.com/len/archive/2008/07/15/56229.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IE代理依赖</title><link>http://www.cppblog.com/len/archive/2008/07/08/55621.html</link><dc:creator>len</dc:creator><author>len</author><pubDate>Tue, 08 Jul 2008 05:27:00 GMT</pubDate><guid>http://www.cppblog.com/len/archive/2008/07/08/55621.html</guid><wfw:comment>http://www.cppblog.com/len/comments/55621.html</wfw:comment><comments>http://www.cppblog.com/len/archive/2008/07/08/55621.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/len/comments/commentRss/55621.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/len/services/trackbacks/55621.html</trackback:ping><description><![CDATA[
		<p>在Windows下，许多网络程序的连接依赖于IE浏览器中的代理服务器的设置，IE浏览器的代理设置很可能设定了注册表中的全局网络连接配置。</p>
		<p>我在IE浏览器中设置了代理，而使用Maxthon浏览网页。在写Python时，用了urllib2库，后来出现了下面的错误：</p>
		<pre class="console">urllib2.URLError: &lt;urlopen error (10061, 'Connection refused')&gt;</pre>
		<p>先前这个程序是运行正确的，又直接用浏览器访问需要的网址，正常。通过排查，发现IE浏览器中设置了代理，而代理无效，而urllib2库使用其网络配置，因此无法连接。通过取消代理，程序连接正常。</p>
		<p>还有一例是，刚才用Windows Live Writer检索日志,和发布日志时出错，分别显示如下的错误：</p>
		<p>
				<a href="/images/cppblog_com/len/WindowsLiveWriter/IE_BAE5/error_2.png">
						<img style="border: 0px none ;" alt="error" src="http://www.cppblog.com/images/cppblog_com/len/WindowsLiveWriter/IE_BAE5/error_thumb.png" border="0" height="144" width="244" />
				</a> <a href="/images/cppblog_com/len/WindowsLiveWriter/IE_BAE5/err_2.png"><img style="border: 0px none ;" alt="err" src="http://www.cppblog.com/images/cppblog_com/len/WindowsLiveWriter/IE_BAE5/err_thumb.png" border="0" height="170" width="244" /></a></p>
		<p>这也是因为WLW使用IE的网络设置，造成的网络错误而显示的错误提示。</p>
		<p>因此在设置了IE代理，并使用其他与网络相关的程序，要特别注意其是否对IE代理设置有依赖。像Maxthon等就可选择不使用IE代理配置的选项。</p>
<img src ="http://www.cppblog.com/len/aggbug/55621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/len/" target="_blank">len</a> 2008-07-08 13:27 <a href="http://www.cppblog.com/len/archive/2008/07/08/55621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开发Windows Live Writer插件小记</title><link>http://www.cppblog.com/len/archive/2008/07/05/55423.html</link><dc:creator>len</dc:creator><author>len</author><pubDate>Sat, 05 Jul 2008 13:43:00 GMT</pubDate><guid>http://www.cppblog.com/len/archive/2008/07/05/55423.html</guid><wfw:comment>http://www.cppblog.com/len/comments/55423.html</wfw:comment><comments>http://www.cppblog.com/len/archive/2008/07/05/55423.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/len/comments/commentRss/55423.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/len/services/trackbacks/55423.html</trackback:ping><description><![CDATA[
		<p>Windows Live Writer是写博客的利器,非常好用。只是对一些常见的html标签支持不足，比如没有预排文本标签&lt;pre&gt;之类的。在插入示例代码时，我不喜欢使用网上的那些高亮插件，它们增加了一些我感觉不友好的标签元素。我在写文章时，代码放在&lt;pre&gt;标签，然后使用自定义的code类，如果是一些屏幕输入输入文本，会用一个console类来进行说明。如果直接从源代码拷贝文本至html源文件时，xml文件的的&lt;&gt;"之类标签需要进行转义才可以。在这之前，我都需要手工将WLW切换到HTML模式进行创作，然后修改这些标签，非常麻烦。这样干了几次后，昨天决定自己写个WLW插件用。在搜索引擎的帮助下，找到Dflying Chen的 <a href="http://www.cnblogs.com/dflying/archive/2006/12/03/580602.html">为Windows Live Writer开发插件——InsertSearchPageLink</a>这篇文章，并在其参照完成了插件编写。</p>
		<p>但在找到这篇文章之前，和编写插件的过程中，还是费了很多功夫。最早我认为写插件是需要下载SDK之类的软件，所以在<a href="http://dev.live.com/writer/">Live Writer官方开发网站</a>，Live Writer网，MSDN之类的找了个遍，看见是有SDK之类字样的下载，但弄不下来只有文档，根本不见其什么头文件，DLL之类的。在这花费了很多时间，最后才发现WLW插件的SDK是随WLW一起分发了，也就是WindowsLive.Writer.Api.dll之类的，这些dll 都随WLW主程序在一个目录中。还有一点是，现在WLW在中国是随Live套件一起发布的，因此路径由原来的C:\Program Files\Windows Live Writer变成了C:\Program Files\Windows Live\Writer，插件目录为Plugin。如果在网上发现有好用的插件，只需要将其发布的插件dll扔到这个目录就行了。</p>
		<p>在开发中碰到图标资源不能成功加载，在Dflying Chen的文章中特意提到了图标资源需要是嵌入形式，我也按照其操作的，总以为是这里出现问题。后来花了一些时间，才找到总是的根源：自己在开发中更改了工程名，导致最后生成的程序集的名称与后来的命名空间名称不一致，图标路径就出错了。C#也只是这次用一下，这些都没有接触到。</p>
		<p>昨天弄完自己的“插入Pre标记”插件后，想到自己写博客常需要截图，遂想再开发一个截图工具的。最早搜到了别人调用SnagIt搜件，不好用，因为SnagIt是商业软件，需要注册的。后来找到了<a href="http://eng.wiziple.net/">picpick</a>，小巧免费，非常实用。我想调用picpick的，但是在参照Insert SnagIt Screen Capture发现是用COM接口，而无奈picpick没有这样供开发使用的接口考虑，最终不可行。后来经过一些其他的尝试，都告失败。最后还是搜索帮了忙，找到了<a href="http://livesino.net/archives/879.live">Screen Capture</a>这个插件，原来有别人已完工了。</p>
		<p>最后附上，我用这个新插件截的图，非常好用，只需一步：</p>
		<p>
				<a href="/images/cppblog_com/len/WindowsLiveWriter/WindowsLiveWriter_124A7/tmp196_2.png">
						<img style="border: 0px none ;" alt="tmp196" src="http://www.cppblog.com/images/cppblog_com/len/WindowsLiveWriter/WindowsLiveWriter_124A7/tmp196_thumb.png" border="0" height="238" width="202" />
				</a>
		</p>
<img src ="http://www.cppblog.com/len/aggbug/55423.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/len/" target="_blank">len</a> 2008-07-05 21:43 <a href="http://www.cppblog.com/len/archive/2008/07/05/55423.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Cygwin，以及远程登陆Linux桌面</title><link>http://www.cppblog.com/len/archive/2008/07/03/55234.html</link><dc:creator>len</dc:creator><author>len</author><pubDate>Thu, 03 Jul 2008 13:55:00 GMT</pubDate><guid>http://www.cppblog.com/len/archive/2008/07/03/55234.html</guid><wfw:comment>http://www.cppblog.com/len/comments/55234.html</wfw:comment><comments>http://www.cppblog.com/len/archive/2008/07/03/55234.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/len/comments/commentRss/55234.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/len/services/trackbacks/55234.html</trackback:ping><description><![CDATA[
		<h3>安装Cygwin</h3>
		<p>在<a href="http://www.cygwin.com/">cgywin官方主页</a>下载安装文件<a href="http://www.cygwin.com/setup.exe">setup.exe</a>,这只是一个网络安装包，体积很小。cgywin包含了许多GNU下的应用程序，真正安装时会根据你选择的组件，会自动去网上下载安装的。在国内最好使用镜像服务，这样速度会提高很多，建议去<a title="http://www.cygwin.net.cn/" href="http://www.cygwin.net.cn/">http://www.cygwin.net.cn/</a>或<a title="http://www.cygwin.cn/" href="http://www.cygwin.cn/">http://www.cygwin.cn/</a>下载上述的安装包，并在安装进行到Choose A Download Site这个步骤时，选择合理的镜像。由于中国南北网速的差异，上述两个地址都尝试一下，看看哪个对你而言速度更快一些。</p>
		<p>在进行到Select Packages这个步骤时，选择你需要包，建议如下：</p>
		<ul>
				<li>Shells -&gt; rxvt-unicode-x  强大的X终端，可用它替换windows下的cmd.exe </li>
				<li>Net-&gt; openssh  ssh客户端，可作putty的替换 </li>
				<li>Net-&gt; inetutils  可选，包含一些基本的网络工具，如telnet，否则在cygwin下无法使用windows的telnet </li>
		</ul>
		<p>cygwin安装时会自动进行包关联，在安装rxvt时，已自动将X server安装上了。</p>
		<h3>配置调整</h3>
		<p>启动cygwin,实际上是运行cgywin.bat批处理，它又调用了cmd.exe。我们将安装的rxvt作为默认终端，需要修改cygwin.bat。下面是我机子上的配置修改，请对应修改相应的路径。</p>
		<pre class="code">@echo off
d:
chdir d:\Cygwin\bin
rxvt -e bash --login -i</pre>
		<p>调整rxvt观感，需要修改你用户主目录下的.Xdefaults文件，此文件在你选择的安装目录下的home\usrname下，在我的机子上是<tt>D:\Cgywin\home\len。若不存在，可在此目录下新建一个，修改内容如下：</tt></p>
		<pre class="code">Rxvt*background:        black
Rxvt*foreground:        #E2E6C7 
Rxvt*font:              9x16 
Rxvt*boldFont:          9x16 
Rxvt*scrollBar_right:   True
Rxvt*saveLines:         1024
Rxvt*geometry:          80x30
Rxvt*color0:            black
Rxvt*color1:            red
Rxvt*color2:            green   
Rxvt*color3:            yellow
Rxvt*color4:            blue
Rxvt*color5:            magenta
Rxvt*color6:            cyan    
Rxvt*color7:            white   
Rxvt*color8:            burlywood1
Rxvt*color9:            sienna1 
Rxvt*color10:           PaleVioletRed1  
Rxvt*color11:           LightSkyBlue    
Rxvt*color12:           white   
Rxvt*color13:           white
Rxvt*color14:           white   
Rxvt*color15:           white </pre>
		<p>在cygwin下也是可以访问Windows下其他盘符的,如<tt>cd /cygdrive/c/windows</tt>，就转到了C盘windows目录下。这样对于在linux下工作的人说有点儿别扭，更希望是以<tt>cd /mnt/c/windows</tt>的mount方式来访问其他盘符。这需要修改注册表的选项，将<tt>HKLM\software\Cygnus Solutions\Cgywin\mounts v2</tt>下的子项<tt>cygdrive prefix</tt>更改为<tt>/mnt</tt>即可。</p>
		<h3>远程登陆Linux桌面</h3>
		<p>其实这里介绍的不仅仅适用于Linux，而是针对X Window的。X Widonw的介绍不进行赘述，但需要明确其中的服务器端和客户端的区别，在X Window的概念中服务器端是指你进行显示，输入输出的机器，也是接下来示例中的本机len-computer,IP为10.3.164.70，而客户端指的是进行远程登陆的机器auto-desktop,IP为10.3.164.74。</p>
		<p>在局域网内最简单的方法是使用XDMCP连接，这时远程的机器启用xdmcp。那台机器运行着ubuntu-8.04，用gdm进行窗口管理，编辑/etc/gdm/gdm.conf-custom如下，其他版本的linux需找到对应的窗口管理的配置文件。</p>
		<pre class="code">[security]
DisallowTCP=false

[xdmcp]
Enale=true</pre>
		<p>修改完后，在远程机器上重启服务，<tt>$sudo /etc/init.d/gdm restart。</tt>接下来本机启动cgywin，转到X目录下，运行Xwin.exe，使用 -query指定远程的linux机器的ip即可。</p>
		<pre class="console">Len@len-computer /usr/X11R6/bin
$ cd /usr/X11R6/bin

Len@len-computer /usr/X11R6/bin
$ Xwin -query 10.3.164.74</pre>
		<p>这里会出现如下面图示的窗口，提示输入用户名和密码。另再附一张在登陆成功后，我在本地执行远程操作的截图。</p>
		<p>
				<a href="/images/cppblog_com/len/WindowsLiveWriter/CygwinLinux_127B5/login_4.png">
						<img style="border: 0px none ;" alt="login" src="http://www.cppblog.com/images/cppblog_com/len/WindowsLiveWriter/CygwinLinux_127B5/login_thumb_1.png" border="0" height="465" width="644" />
				</a>
		</p>
		<p>
				<a href="/images/cppblog_com/len/WindowsLiveWriter/CygwinLinux_127B5/cygwinX_2.png">
						<img style="border: 0px none ;" alt="cygwinX" src="http://www.cppblog.com/images/cppblog_com/len/WindowsLiveWriter/CygwinLinux_127B5/cygwinX_thumb.png" border="0" height="484" width="644" />
				</a>
		</p>
		<p>如果你需要连接的远程机器比较固定，可以修改本地机器<tt>d:\cgygin\usrX11R6\bin\startxdmcp.bat</tt>中的<tt>REMOTE_HOST</tt>值为你需要连接机器的IP，这个批处理设置了一些有用的环境变量值。或许你需要创建一个桌面的快键方式，这样每次点击，就直接连接到远程机器了。</p>
		<h3>不引入桌面环境</h3>
		<p>可能有时候只需要将某个需要X服务的远程应用程序引入到本地桌面显示，而不需要启动像上面的GNOME或者KDE等庞大的桌面环境。这样做比较适合喜欢终端操作的人，我就常常终端敲命令，然后将gvim,openoffice这些从远程导入到本地操作。</p>
		<p>找到d:\cgywin\usr\X11R6\bin\startwin.bat，将<tt>%RUN% xterm -e /usr/bin/bash -l</tt>注释掉，因为我们己经有了rxvt,不需要一个新的xterm终端了，执行该批处理文件，就会在本机运行X server。启动cgywin，用ssh登陆到远程机器上，执行如下命令，导出DISPLAY环境变量和运行你感兴趣的程序。</p>
		<pre class="console">auto@Auto-desktop:~$ export DISPLAY=10.3.164.70:0.0
auto@Auto-desktop:~$ gvim&amp;
[1] 22652
auto@Auto-desktop:~$ oowriter&amp;</pre>
		<p>其中环境变量DISPLAY中的:0.0部分表示X server的display和screen。display指运行着X server实例。如果使用TCP/IP连接，表示的是端口6000+display号做为连接。screen代表X server上的不同输出设备。我在例子中执行gvim和openoffice.org-writer，运行的效果可看下面的截图。在ubuntu上运行着的gvim和openoffice都在我本机10.3.164.70上显示了，并且可操作。</p>
		<p>
				<a href="/images/cppblog_com/len/WindowsLiveWriter/CygwinLinux_127B5/screen_2.png">
						<img style="border: 0px none ;" alt="screen" src="http://www.cppblog.com/images/cppblog_com/len/WindowsLiveWriter/CygwinLinux_127B5/screen_thumb.png" border="0" height="484" width="644" />
				</a>
		</p>
		<h3>有用的链接</h3>
		<p>
				<a href="http://x.cygwin.com/docs/faq/cygwin-x-faq.html">Cgywin/X FAQ</a> 在碰到一些操作问题时，不妨先看看这份FAQ</p>
		<p>
				<a href="http://blog.csdn.net/easwy/archive/2007/09/30/1807725.aspx">使用cygwin X server实现Linux远程桌面</a> easwy介绍了KDE环境下的配置，部分受此启发</p>
		<p>
				<a href="http://blog.csdn.net/easwy/archive/2007/10/05/1812242.aspx">使用rxvt做为cygwin终端</a> 碰到rxvt中文显示问题时，或许有帮助</p>
<img src ="http://www.cppblog.com/len/aggbug/55234.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/len/" target="_blank">len</a> 2008-07-03 21:55 <a href="http://www.cppblog.com/len/archive/2008/07/03/55234.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>