2008-12-31

替換Windows的Desktop時,如何獲取應用程序注冊的圖標?

今天整理硬盤的時候發現這個,放上來算了,希望對需要的人有幫助。
是以前寫的一個東西——曾經覺得 Windows 的 Desktop 太難看了,所以打算自己寫一個。其它的沒啥子主要是些 GDI+ 的操作。
中間遇到的最大問題是如何獲得應用程序對 TrayNotifyIcon 的注冊。關于這個問題曾經 debug 了 explorer.exe ,才得出以下方法:(Windows XP)

1、如何接收應用程序的注冊圖標通知:
自己實現一個Window注冊Class為"Shell_TrayWnd"(Windows界面中的控件元素都可看作Window——所以叫做 Windows 嘛~~),其下一個子窗口(控件)注冊Class為"TrayNotifyWnd"。
在注冊Class為"Shell_TrayWnd"的窗口中可處理 WM_COPYDATA 消息:
此時 lParam 為 PCOPYDATASTRUCT pcds
(pcds->dwData == 1) 時表示是一個通知消息
此時的 pcds->lpData 結構如下:
(這是我自己定義的一個結構,不知道MSDN是否有這樣的結構,反正我是沒找到,所以自定義了個)

// the struct for WM_COPYDATA to "Shell_TrayWnd"
typedef struct _NOTIFY_MSG_DATA {
 DWORD dwUnknow;  // ??? I don't know what's this ?
 DWORD dwNotifyCode; // NIM_ADD, NIM_DELETE, NIM_MODIFY, ...
 NOTIFYICONDATA nid; // 這里就是應用程序注冊圖標時的數據了
 bool operator== (const _NOTIFY_MSG_DATA& nmd) const
 {
  return nid.hWnd == nmd.nid.hWnd;
 };
} NOTIFY_MSG_DATA, *PNOTIFY_MSG_DATA;
子窗口注冊Class為"TrayNotifyWnd"主要是想和 explorer.exe 保持一致罷了,接收消息的實質上是"Shell_TrayWnd"。

另外,要注意的是:
if (pnid->uFlags & NIF_ICON) // pnid為上面的NOTIFYICONDATA的指針
{
 // Some applications destroy the icon immediately after completing the
 // NIM_ADD/MODIFY message, so we have to make a copy of it.
 if (hIcon)
  ::DestroyIcon(hIcon);
 hIcon = (HICON) ::CopyIcon(pnid->hIcon);

 bChanged = true;
}
某些程序在注冊圖標后會 destory 這個 hIcon ,所以最好是自己拷貝一份——要不然也會出現某些得到的圖標莫名其妙不見了的情況。

2、explorer.exe 出異常中途結束后重啟,得到被終結之前的圖標。
(在XP之前的Win版本中是會丟失的——失去之前注冊的程序圖標)
XP 中主要在以下注冊表項目中,以二進制方式存儲:
[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\TrayNotify]
IconStreams 当前项目
PastIconsStream 过去的项目
存儲的數據格式如何,自己dump一下就知道了 :)


嗯……其它的就沒有什么好多說的了,基本上就是一些 GDI+ 操作了。

哦!還有就是 explorer.exe 除了桌面外,還充當文件管理器等其它的作用,所以要替換它的話除了繪制桌面還要做其它方面的準備,或者那些方面的替代品。

差不多就是這些了,以上!

//EOF Read More...

2008-12-13

DOM 还是 SAX

选择 DOM 还是选择 SAX,这取决于下面几个因素:

  • 应用程序的目的:如果打算对数据作出更改并将它输出为 XML,那么在大多数情况下,DOM 是适当的选择。并不是说使用 SAX 就不能更改数据,但是该过程要复杂得多,因为您必须对数据的一份拷贝而不是对数据本身作出更改。
  • 数据容量: 对于大型文件,SAX 是更好的选择。
  • 数据将如何使用:如果只有数据中的少量部分会被使用,那么使用 SAX 来将该部分数据提取到应用程序中可能更好。 另一方面,如果您知道自己以后会回头引用已处理过的大量信息,那么 SAX 也许不是恰当的选择。
  • 对速度的需要: SAX 实现通常要比 DOM 实现更快。
SAX 和 DOM 不是相互排斥的,记住这点很重要。您可以使用 DOM 来创建 SAX 事件流,也可以使用 SAX 来创建 DOM 树。事实上,用于创建 DOM 树的大多数解析器实际上都使用 SAX 来完成这个任务!

參考:
http://www.ibm.com/developerworks/cn/views/xml/tutorials.jsp?cv_doc_id=84979

//EOF Read More...

2008-12-11

網頁互動游戲 Stargate Origin

網頁 Stargate Origin
是一個網頁游戲,主要是造東西然后再造東西,還有掠奪別人的東西…… 比較無聊。

昨天申請了個帳號,今天登錄發現被掠奪一空了 -_-||||

//EOF Read More...

2008-12-10

struts 配置文件中元素的順序

今天才發現原來 struts 配置文件中元素之間的順序是有要求的。

controller 放在 message-resources 之前會報錯,雖然程序能夠正常運行,但在加載的時候會報一個“配置文件解析錯誤”。

看來順序還是不能變~

//EOF Read More...

一个怪异都梦

昨天晚上做了个梦,大致是这样的:

似乎是在急匆匆的赶夜路,夜空非常的清明,奇怪的是空中找不到月亮,但是空中有三颗很亮的星,看起来有两颗在一等星或一等星以上,另一颗大概是二等星,由于这三颗星的亮度太大,其它星基本看不到。虽然我移动的很快,但仍然感觉得到三颗星都在移动,而且是不规则的运动轨迹,想停下来仔细看看,但发现停不下来──哦~ 原来我躺在一个敞篷的运输车厢里,旁边还挤着其他一些穿着和我一样的人。

飞星!飞星!
以上情节与《三体》中的场景很象吧?很奇怪我怎么会做这样的梦,《三体》我看过少说也有一两年了,怎么会在这时候梦到就奇怪了。
不过也不一定就是“飞星”,人造天体/飞行器具 也说不定,还有可能是导弹的尾焰……

大概在这里,就迷迷糊糊的醒来了,之后似乎又迷迷糊糊的睡着了……
总体来说昨晚的睡眠质量特差,断断续续的醒来又迷迷糊糊的睡去,这样往复不断,之后似乎也做了些梦,但都记不得了~~。

这个梦给我印象最深的就是 夜空 ,夜空非常的清明,稀稀的伴着几朵薄薄的云彩。这样的夜空已经很久没有看到过了,至少在我现在住的地方是看不到的。记得最接近的就是我上湘大时的图书馆前坪看到过比较接近的夜空──那是在图书馆还没实行亮化工程前,实行亮化之后也看不到了。

不知道要待到何时才能再次在现实中看到这样的夜空?我希望能在我住的地方仰头就能看到这样的夜空 :)

//EOF Read More...

2008-12-07

ASP.NET TreeView check childs/parents

給 ASP.NET 的 TreeView 寫了一個掛件,主要功能就是在 TreeView 是 ShowCheckBox 模式的時候,當勾選某個節點時能自動的勾選這個節點相關的所有父節點,以及勾選、反勾選這個節點的所有子節點。

功能很簡單純 javascript 實現:

/*************************************************************************
 * change the tree view node's child nodes check-state, when check
 * this node.
 *
 *   NOTE: for ASP.NET TreeView
 *
 * @author h_Davy
 * @version 2008-12-5
 *************************************************************************/

/**
 * check the tree node's childs with this checkbox's stats
 *
 * @param chk   the check box element
 *
 * @private
 */
function _checkTreeChilds(chk)
{
    var childId = chk.id.replace('CheckBox', 'Nodes');
    var child = document.getElementById(childId);
    if (child) {
        var chks = child.getElementsByTagName('input');
        for (var i in chks) {
            if (chks[i].type == "checkbox") {
                chks[i].checked = chk.checked;
            }
        }
    }
}

/**
 * find out the checkbox-node's parent node's checkbox id
 *
 * @param chk       the check box element
 * @param treeView  the treeView element
 *
 * @return  the parent node checkbox id
 *
 * @private
 */
function _findTreeParentId(chk, treeView)
{
    if (!chk) return null;
    var tmpElm = chk.parentNode;
    for(;;) {
        if (tmpElm.tagName == "TABLE") {
            return tmpElm.parentNode.id.replace('Nodes', 'CheckBox');
        } else {
        // go up to find out the parent node, until touch the treeview
            tmpElm = tmpElm.parentNode;
            if (tmpElm == treeView) return null;
        }
    }
    return null;
}

/**
 * check the tree node's parent w this checkbox is checked
 *
 * @param chk   the check box element
 * @param treeView  the treeView element
 *
 * @private
 */
function _checkTreeParent(chk, treeView)
{
    if (!chk.checked) return;
    var tmpChk;
    var parentId = _findTreeParentId(chk);
    for(;;) {
        if (!parentId) return;
        if (chk.checked) {
            tmpChk = document.getElementById(parentId);
            if (!tmpChk || tmpChk == treeView) return;
            tmpChk.checked = true;
        }
        parentId = _findTreeParentId(tmpChk, treeView);
    }
}

/**
 * use this bind to a tree view
 *
 * @param id    the tree view's id (NOTE: it's the HTML node id, not .NET page server id)
 */
function bindCheckEvent(id) {
    var treeView = document.getElementById(id);
    var chks = treeView.getElementsByTagName('input');
    for(var i in chks) {
        if (chks[i].type == "checkbox") {
            chks[i].onclick = function() {
                _checkTreeChilds(this);
                _checkTreeParent(this, treeView);
            };
        }
    }
}

// -- EOF --

使用方法,在要使用的頁面導入以上代碼后,在頁面結尾處加上:
<script type="text/javascript">

bindCheckEvent('TreeView1');
// 這里的 'TreeView1' 就是那個TreeView的ID
// !!!注意:這里的ID指的是最終生成的HTML頁面中的ID,
//                 如果你的TreeView是在某個使用了模板頁的內容頁里面的話,
//                 就有可能是 'ctl00_ContentPlaceHolder1_TreeView1' 了。

</script>

//EOF Read More...

2008-11-30

Linux 中使用NetBeans部署、运行Web应用要注意目录权限设置

使用的是 tomcat
要注意以下几个目录的权限要当前用户可写

$CATALINA_HOME/conf/Catalina/localhost/
$CATALINA_HOME/webapps/
$CATALINA_HOME/work/Catalina/localhost/
$CATALINA_HOME/temp/

否则,有可能会出现无法写入部署目录而部署失败:

Failed to deploy application at context path /xxx

另外,还要注意
$CATALINA_HOME/bin/
下几个.sh文件的当前用户执行权限,不然tomcat都无法运行。

//EOF Read More...

2008-11-23

限用存储过程

存储过程是个好东西,但是偶尔用用就好了,不要过分的使用!
特别的在业务逻辑较复杂的应用中 或 在表间关系较复杂的应用中。这时候如果大量使用了存储过程,在后期系统维护、功能改进的过程中你会非常痛苦的~~!!!
业务逻辑尽量交给应用来做。

// EOF Read More...

2008-11-18

Linux Admin IQ Test

問題見:
http://www.infoworld.com/tools/quiz/news/IQ2008linux-news-quiz.php

只的了 65 分啊~~

Question 1: Which vendor has never branded its own Linux?

5 points
c. IBM

Even SCO briefly offered its own Linux product. Big Blue, despite being an enthusiastic Linux backer, has always partnered with other distributors instead of packaging its own version of the OS.

Question 2: Why GRUB over LILO?

5 points
d. You want to boot from a network

LILO supports a wide variety of boot configurations, but you'll need the more modern GRUB if you want to boot from a network.

Question 4: What's a "shebang"?

5 points
a. A unique sequence of characters that indicates the start of a shell script

Short for "shell bang," shebang is a hash or pound sign (#) followed by an exclamation mark (!), known in Unix parlance as a "bang."

Question 8: Which graphics chip vendor hasn't released a Linux driver?

5 points
c. Nvidia

Although most of the competition has released open source drivers for at least some of their graphics chips, Nvidia has remained a staunch holdout.

Question 15: What's the benefit of noatime?

5 points
a. It improves performance by reducing the frequency of disk writes

Normally, Linux will update the time stamp on a file every time it is accessed. With the noatime option, the kernel will update files only when their contents are changed.

Question 16: Which virt tech allows Windows VMs to run on Linux?

5 points
c. Xen

Most of the virtualization software listed can only launch other instances of Linux. Xen can support Windows virtual machines also, provided your processor supports Intel VT or AMD-V technology.

Question 17: What's a "binary blob"?

5 points
a. A driver that is loaded into the kernel as a binary object, for which no source code is available

The Linux community is divided over the practice of running closed source code as part of the Linux kernel, but when hardware vendors refuse to release their specifications, it's often the only option.

//EOF Read More...

2008-11-02

javascript 中判断是否为IE的技巧

利用 IE 中 jscript/javascript 的“条件编译”
条件编译:
/*@cc_on, @if, @elif, @else, @end, @*/
如:

/*@cc_on
   @if (@_win32)
      document.write("操作系统是32位windows。浏览器是IE。");
   @else
      document.write("操作系统不是32位windows。浏览器是IE。"); // 这个是不会输出的
   @end
@*/
技巧:
    if (!/*@cc_on!@*/0) { //if not IE
        //Firefox2、Firefox3、Safari3.1+、Opera9.6+ support 
    } else {
        //IE6、IE7 support 
    }

//EOF Read More...

2008-10-25

mono+mysql 出现 EntryPointNotFoundException: CreateSemaphore

今天试着在 Mono 中使用 mySql 的连接驱动 "MySql.Data.dll" 时出现异常:

System.EntryPointNotFoundException: CreateSemaphore
at (wrapper managed-to-native) MySql.Data.Common.Semaphore:CreateSemaphore (MySql.Data.Common.SECURITY_ATTRIBUTES&,int,int,string)
at MySql.Data.Common.Semaphore..ctor (Int32 initialCount, Int32 maximumCount) [0x00000]
at (wrapper remoting-invoke-with-check) MySql.Data.Common.Semaphore:.ctor (int,int)
at MySql.Data.MySqlClient.MySqlPool..ctor (MySql.Data.MySqlClient.MySqlConnectionString settings) [0x00000]
at MySql.Data.MySqlClient.MySqlPoolManager.GetPool (MySql.Data.MySqlClient.MySqlConnectionString settings) [0x00000]
at MySql.Data.MySqlClient.MySqlConnection.Open () [0x00000]
google 后发现 似乎时需要在连接字符串中设置 "Pooling=false"
private const string CONNECTION_STRING = "server={0};database={1};uid={2};pwd={3};Pooling=false;";
这样就正常了。
原因还不清楚……

//EOF Read More...

2008-10-14

OpenOffice 3.0 在 KDE 下的一点小问题

3.0速度快了很多,感觉很爽!
但是有个小问题,就是:
“Tools”等几个菜单项选中的时候会挂掉(Arch 的 KDE4桌面环境)
解决方法:
export OOO_FORCE_DESKTOP=gnome
就好了,据说是因为3.0里面没有支持KDE的主题所致。
//EOF Read More...

2008-10-08

DIV+CSS 布局时要注意的

左右浮动分栏布局时要记得清除浮动,否则下面的东西会上来哦!
在一行的浮动,之后不需要浮动的时候,记得在中间加上一个清除浮动层:

<div style="clear:both;line-height:0;height:0;font-size:0;"></div>
或:
.clear {clear:both;line-height:0;height:0;font-size:0;}
...
<div class="clear"></div>

例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>双栏</title>
<style type="text/css">

body {
    text-align: center;
}

#body {
    text-align: left;
    width: 95%;
    margin: 0pt auto;
    min-width: 640px; /* IE6 不支持 */
}

#header {
    background-color: #def;
}

#content {
    
}

.left {
    float: left;
    width: 20%;
}

.right {
    float: left;
    width: 80%;
}

#foot {
    font-size: .8em;
    color: #999;
    text-align: center;
}

#header, #content, #foot {
}

p, h1 {
    margin: 0pt;
    padding: 5pt;
}

*, body {
    font-family: "Verdana", Geneva, Sans-Serif;
    /*font-size: 10pt;*/
}

</style>
<script type="text/javascript">

</script>
    </head>
    <body>
<div id="body">
        <div id="header">
            <h1>Header</h1>
            <p>this is the header</p>
        </div>
        <div id="content">
            <div class="left">
                <p>Left</p>
                <p>Left</p>
                <p>Left</p>
                <p>Left</p>
                <p>Left</p>
                <p>Left</p>
                <p>Left</p>
                Left
            </div>
            <div class="right">
                <p>Right</p>
                <p>Right</p>
                <p>Right</p>
                Right<br />
                Right<br />
                Right<br />
            </div>
        </div>
        <!-- 去掉下面这行试试 -->
        <div style="clear:both;line-height:0;height:0;font-size:0;"></div>
        <div id="foot">
            Copyright &copy; 2008, h_Davy; Powered by: VIM;
        </div>
</div>
    </body>
</html>

//EOF Read More...

2008-10-05

一些字节的单位

如下是一些存储中用到的单位,及其换算:

bit, Byte, KiloByte(KB,KiB), MegaByte(MB,MiB), GigaByte(GB,GiB), TeraByte(TB,TiB),
PetaByte(PB,PiB), ExaByte(EB,EiB), ZettaByte(ZB,ZiB), YottaByte(YB,YiB)

  • 1 bit
  • 8 bits = 1 Byte (on most systems)
  • 1024 bytes = 1 KiloByte (KBytes or KB or KiB)
  • 1024*1024 bytes = 1024 KB = 1 MegaByte (MBytes or MB or MiB)
  • 1024*1024*1024 bytes = 1024*1024 KB = 1024 MB = 1 GigaByte (GBytes or GB or GiB)
  • 1024*1024*1024*1024 bytes = 1024*1024*1024 KB = 1024*1024 MB = 1024 GB = 1 TeraByte (TBytes or TB or TiB)
  • 1024*1024*1024*1024*1024 bytes = 1024*1024*1024*1024 KB = 1024*1024*1024 MB = 1024*1024 GB = 1024 TB = 1 PetaByte (PBytes or PB or PiB)
  • 1024*1024*1024*1024*1024*1024 bytes = 1024*1024*1024*1024*1024 KB = 1024*1024*1024*1024 MB = 1024*1024*1024 GB = 1024*1024 TB = 1024 PB = 1 ExaByte (EBytes or EB or EiB)
  • 1024*1024*1024*1024*1024*1024*1024 bytes = 1024*1024*1024*1024*1024*1024 KB = 1024*1024*1024*1024*1024 MB = 1024*1024*1024*1024 GB = 1024*1024*1024 TB = 1024*1024 PB = 1024 EB = 1 ZettaByte (ZBytes or ZB or ZiB)
  • 1024*1024*1024*1024*1024*1024*1024*1024 bytes = 1024*1024*1024*1024*1024*1024*1024 KB = 1024*1024*1024*1024*1024*1024 MB = 1024*1024*1024*1024*1024 GB = 1024*1024*1024*1024 TB = 1024*1024*1024 PB = 1024*1024 EB = 1024 ZB = 1 YottaByte (YBytes or YB or YiB)

参考:http://en.wikipedia.org/wiki/Byte

//EOF Read More...

2008-10-02

使用 vim, ctags 来记带书签的笔记

个人比较偏好纯文本的记录,因为不管何种严苛的条件下只要能查看文本文档就能够读取。
(当然某些特殊的笔记还是需要依靠富文本才能完成的)

在某些时候希望这些纯文本的记录能够带上书签就更好了——特别是当这些记录日渐积累过多的时日——能够带上目录索引就更好了。

记得 vim 的help文档么?都是纯文本文件,但是它有带书签、索引的特性跳来跳去,并且还带少量高亮。

看来仅依靠 vim 自带的这个功能就可以做到了。

如何做呢?
只需在每个文本文档末尾加上:

 vim:ft=help

就能让 vim 在读取该文档后按照vim help来解析。

仅仅这样么?
还不够!
那么如何能够让 vim 在文本中支持书签功能呢?
随便打开一个vim的帮助文档看看就知道了。

通过两个"*"括起来的字符来锚定书签,
通过两个"|"括起来的字符来索引书签。
如:

索引 |the_first_bookmark|
书签 *the_first_bookmark*

在“索引”后面的"the_first_bookmark"上面Ctrl+]来跳转到
“书签”后面的"the_first_bookmark"所在位置,
然后按Ctrl+T(或Ctrl+O)可以跳回原来的“索引”后的"the_first_bookmark"所在位置。
还能支持不同文件之间的书签跳转,当然前提是书签不能够重名!!!

什么?不能跳,提示没有“tag”文件?
哦!忘记说了,还有条vim的命令:
:helptags .

表示构建当前目录下的*.txt文件的vim help tag索引。
能否构建成功关键是看你的系统里面是否有ctags程序(一般开发用Linux都会有的)
没有的话可以到 http://ctags.sf.net/ 去下载(有Windows版本)

要注意的是:
书签的命名规则,字符串中间不要有空格,不要有除"_"之外的符号。
还有就是当前目录下不要有重名的书签——就是说所有"*"中间的字符串们不要有重复的。


其他:
分隔行,支持如下三种高亮分隔行(内容分块显示,看起来更清晰):

---------------------------------------------------------------------------
===========================================================================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

感兴趣的话,还可以玩玩ASCII艺术。


总结如下:

  1. 文件结尾 vim解析标识:
     vim:ft=help

  2. "*"中间的字符串锚定命名书签

  3. "|"中间的字符串索引到指定命名的书签

  4. 构建tags索引:
    :helptags .



//EOF Read More...

2008-09-28

用kexec快速切换内核

详见:http://www.linuxsir.org/main/node/296

总的来说:



  1. 内核版本必需为 2.6.13 或以上,因为自该版本起内置了 kexec 系统调用的程序。

  2. 内核编译需加入 kexec 支援
    Processor type and features --->

    [*] kexec system call (EXPERIMENTAL)


  3. 系统需要安装 kexec-tools

  4. 用 /sbin/kexec 加载另一内核,语法是:
    kexec -l <kernel-image> --append="<command-line-options>" 
    如:
    kexec -l /boot/lfskernel-2.6.25.4 --append="root=/dev/sda6 ro nomce vga=0x317"

  5. 想重启内核,就以 kexec -e 来切换。




//EOF Read More...

2008-09-26

FtpViewer 初始版本源代码

源代码下载:http://sites.google.com/site/dave3068/Home/my-project/FtpViewer_src.zip

见:http://sites.google.com/site/dave3068/Home/my-project

history:
2008-09-26 最初版本。
2008-09-27 有所改进,界面有所改进、增加删除功能。(今后不会再增加功能,有违做这个软件的初衷)

注:
为何不加入上传下载功能?
毕竟我写这个工具的初衷是:某FTP提供限额文件存放服务,而我的限额到了,我想看看哪些东西占用空间,并将其删除,并没有其它需求。
而对于FTP的上传、下载:每个操作系统安装后一般都默认自带了命令行的ftp工具,通过脚本可以很方便的实现文件的上传、下载。所以我认为没必要再提供多余的操作。


//EOF Read More...

sun.net.ftp.FtpClient 编码问题解决

使用 sun.net.ftp.FtpClient 在遇到中文文件名和中文目录名时会出现些问题。

  1. list() 得到的文件名乱码,这个很好解决:

    /**
    * 字符编码转换:ISO-8859-1 => GBK
    *
    * @param str
    * @return
    * @throws UnsupportedEncodingException
    */
    public static String iso2Gbk(String str)
    throws UnsupportedEncodingException {
    return new String(str.getBytes("ISO-8859-1"), "GBK");
    }


  2. 遇到某中文目录时会无法进入,这个问题困扰我好几天(这几天一直在摆弄这个)。
    发现服务端接收到的中文目录名都成乱码了,一开始我以为通过 new String() 的方式也可以解决。
    其实不然,怎么试都不行,好象在 sun.net.ftp.FtpClient 里面会自动转换成 ISO 的编码。
    今天偶然有机会看到 sun.net.ftp.FtpClient 的源码才发现果然如此。
    sun.net.ftp.FtpClient 有个超类 sun.net.NetworkClient 在里面会将所有传输出去的编码都转换成 ISO 的。看来问题出在这里了。
    同时 sun.net.NetworkClient 还有个:

    /* Name of encoding to use for output */
    protected static String encoding;

    这个可以控制其编码,于是乎:

    /**
    * 设置连接编码
    *
    * @param encodingStr
    */
    public static void setEncoding(String encodingStr) {
    sun.net.NetworkClient .encoding = encodingStr;
    }

    将编码设置成 GBK 问题即解决。


至此,遇到的两个编码问题都已解决,一切都是那么轻松 ^_^ 。

//EOF Read More...

2008-09-25

回来了!LinuxSir 终于回来了!

历时一个半月。LinuxSir 终于又回来了 !!!

//EOF Read More...

2008-09-22

Java 获取FTP文件大小

使用 sun.net.ftp.FtpClient。


package h.davy;

import h.davy.ftp.FtpFileInfo;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import sun.net.TelnetInputStream;
import sun.net.ftp.FtpClient;

public class Test {

private static int test() {
FtpClient ftp = null;
try {
ftp = new FtpClient();
ftp.openServer("192.168.1.27");
ftp.login("t01", "12345");
// ftp.login("anonymous", "anonymous@do.c");

System.out.println(ftp.pwd()); // 当前目录
System.out.println(ftp.system());

System.out.println("===============================");
ftp.ascii();
// 获取目录文件列表详细信息
TelnetInputStream listStream = ftp.list();
byte[] buf = new byte[2048];
int n = 0;
while (true) {
if (0 > (n = listStream.read(buf, 0, buf.length)))
break;
System.out.println(n);
String fileName = new String(buf, 0, n);
System.out.println(fileName);
}
listStream.close(); // 需要这个关闭流

System.out.println("===============================");
getFilesInfo(ftp, "/");
System.out.println("===============================");
System.out.println(getFileSize(ftp, "/test.tar.bz2"));
System.out.println(getFileSize(ftp, "/phpMyAdmin/index.php"));
System.out.println("===============================");
getFilesInfo(ftp, "/phpMyAdmin");
// 退出登录
ftp.sendServer("QUIT\r\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
// try {
// ftp.closeServer();
// } catch (IOException e) {
// e.printStackTrace();
// }
}
return -1;
}

/**
* 获取某文件大小
*
* @param ftp
* @param filePath
* @return
* @throws IOException
*/
static long getFileSize(FtpClient ftp, String filePath) throws IOException {
ftp.binary(); // 需要切换到 Binary 模式
ftp.sendServer(String.format("SIZE %s\r\n", filePath));
StringBuffer sb = new StringBuffer();
while (true) {
int c = ftp.serverInput.read();
char ch = (char) c;
if (c < 0 || ch == '\n') { // end of stream || end of line
StringTokenizer tk = new StringTokenizer(sb.toString());
int index = 0;
while (tk.hasMoreTokens()) {
String token = tk.nextToken();
if (index == 1) {
try {
return Long.parseLong(token);
} catch (NumberFormatException e) {
return -1L;
}
}
index++;
}
}
if (ch == '\n')
continue;
else if (c <= 0)
break;
sb.append(ch);
}
return -1L;
}

/**
* 获取某目录中的所有文件
*
* @param ftp
* @param path
* @return
* @throws IOException
*/
static List<FtpFileInfo> getFilesInfo(FtpClient ftp, String path)
throws IOException {
List<FtpFileInfo> ret = new ArrayList<FtpFileInfo>();

ftp.cd(path); // 切换到指定目录
ftp.ascii(); // 需要切换到 ASCII 模式
TelnetInputStream listStream = ftp.list();
StringBuffer sb = new StringBuffer();
while (true) {
int c = listStream.read();
char ch = (char) c;
if (c < 0 || ch == '\n') { // end of stream || end of line
FtpFileInfo ffi = new FtpFileInfo();
StringTokenizer tk = new StringTokenizer(sb.toString());
int index = 0;
while (tk.hasMoreTokens()) {
String token = tk.nextToken();
switch (index) {
case 0: // file attribute string
// 这里可以根据 attribute string 分析该文件是否为目录。
// (若为目录第一个字符为"d")
ffi.setAttributeStr(token);
break;
case 1: // ??
break;
case 2: // owner
break;
case 3: // group
break;
case 4: // file size
try {
ffi.setFileSize(Long.parseLong(token));
} catch (NumberFormatException e) {
e.printStackTrace();
}
break;
case 5: // month
case 6: // day
case 7: // time
break;
case 8: // file name
ffi.setFileName(token);
break;
}
index++;
}
ret.add(ffi);
sb.setLength(0);
}
if (ch == '\n') {
continue;
} else if (c <= 0)
break;
sb.append(ch);
}
listStream.close(); // 需要这个关闭流
return ret;
}

/**
* @param args
*/
public static void main(String[] args) {
System.out.println(test());
}

}


注:其中的 FtpFileInfo 仅仅是个人定义的一个 Java Bean 没什么实质的内容。

注:对于 ftp.list() 打开的流需要关闭,要不然后续读取操作会被挂起。


//EOF Read More...

2008-09-21

some photos

http://www.getdropbox.com/gallery/163800/1/2008-09-17?h=c63c62

//EOF Read More...

2008-09-15

SGER 回来了!

回来了!回来了!终于回来了!
http://bbs.sger.net/ 终于回来了!
好激动啊! 可惜丢失了3个多月的数据。

另外期待 linuxsir 也能尽快回来!

//EOF Read More...

2008-08-09

开幕式

还有印象的:

击缶(第一印象——好大的CPU。。。)
贯穿开幕式的画卷
大脚印
会场真的很热~~`` 释放了这么多热量到空气中全集中在那里。。。(庆幸自己没去,嗯……)

最后,辛苦李林了,发福的年纪了还要被吊在上面折腾~~
(话说中间有一段他“跑”快了,看起来就像是在被后面展开的画卷追赶一样 :D,不过后面还是调整过来了。)


总体来说我对这个开模式不太满意(特别是点火部分),和我心目中的还是有些距离。(可能我科幻看多了吧)



//EOF Read More...

2008-08-05

proftpd 限制用户目录

proftpd 是个不错的FTP服务端。

在 /etc/proftpd.conf 中配置


DefaultRoot ~

即可将登录的用户限制在其$HOME中(要不然用户登录后连"/"都能访问)。

另外加入

<Limit LOGIN>
DenyUser username
</Limit>

可限制登录用户。

//EOF Read More...

2008-08-01

Linux 版 QQ ?

听说 TX 出了 Linux 版的QQ,我下载了 tar 版的。
但是,这个可怜的QQ,在我的硬盘上仅存在了 10秒不到~~
马上就被我删掉了,太恶心了~~
花哨的界面和简陋的功能严重不匹配~ 有心思做花哨的界面还不如多花点心思来完善功能。
//EOF Read More...

2008-07-29

用上KDE4.1了

昨天 Arch 官方升级了KDE到4.1,昨天没注意,今天早上开始时吓了一跳~~

不过也好,迟早是要升级的。就是刚开始从3.5到4.1还有些不太适应。

//EOF Read More...

2008-07-21

Komodo

Komodo Edit 是 ActiveState 的IDE的一个免费版,具有一些基本的 IDE 功能。支持 HTML/CSS/javascript/Perl/Python/PHP/Ruby 等。

Komodo 是使用 Python 开发的,基于 XUL (据说ActiveState出钱出人,在FireFox中占了一席之地,专门开发Python for XUL scripting)所以 Komodo 看起来会和 FireFox 有些像,特别是那个 Extension Manager(当然这个是连接上ActiveState的插件站点——不过似乎可以安装FireFox的JavaScript debugger)。

http://community.activestate.com/

//EOF Read More...

2008-07-06

untitle

要面对未知。只有宽容才能正视,正视才能理解,而理解才能超越。。。
//EOF Read More...

2008-06-25

std::for_each 调用本类的成员函数

std::for_each 是个好用的东西,不过在调用本类的成员函数时稍微遇到点问题。
在网上查找了N久,然后经过自己调试终于得到一个稍微简便的方法:
(结合 std::bind1st 和 std::mem_fun)


// coding by : h_Davy
//
#include <iostream>
#include <vector>

using std::out;

class Test
{
public:
    Test() {};

    void push(int i)
    {
        vi.push_back(i);
    }

    void show()
    {
        std::for_each(
                vi.begin(),
                vi.end(),
                std::bind1st(
                    std::mem_fun<void, Test, int>(
                        &Test::print1 ), this ) );
    }

private:
    std::vector<int> vi;

    void print1(int i)
    {
        cout << "> " << i << "\n";
    }
};


int main()
{
    Test t;

    t.push(123);
    t.push(456);
    t.push(789);

    t.show();

    return 0;
}

(以上代码在 GCC 4 中编译通过,并正常运行)

如果是 MS-VC6 稍微需要些修改:

  1. VC6 中似乎不支持 void 的返回值,所以那个成员函数的返回值改成 int 或 任何你觉得合适的类型。

  2. VC6 中应该将 std::mem_fun 改成 std::mem_fun1 。


如此,VC6 中能正常使用。

//EOF Read More...

2008-06-14

试用 VS.PHP

前几天搞了个 Vs.Php 来,今天试用了一下。

VS.PHP 是一个 PHP 开发的 IDE(基于M$提供的VS.NET) ,我下载的是 VS.Php.for.Visual.Studio.2005。
装好后像VC那样在提供一个新建工程的模板。新建工程再新建php文件后就可以写代码了。

不过比较奇怪的是,老是运行不起来~~
(按理说,安装好后Apache,PHP都自带了的啊)

最后发现是没能正常创建 httpd.conf 所致,配置:
Project => Properties => Configuration Properties => Debug => Advanced => Apache configuration template

将VS.PHP安装目录中带的 "httpd-template.conf" (httpd.conf模板文件) 设置到此处,然后就会在工程所在目录中根据该模板自动创建一个 .httpd.conf 文件。
然后运行成功。


—— 让我感觉到奇怪的是 php.ini 都能自动找到并创建,这个 httpd.conf 的模板怎么就没找到呢?好像其他人也没这样的情况~~ 难道和我用的是试用版有关?还是说是我的RPWT 囧?



//EOF Read More...

2008-05-28

竟然还是无法面对自己 = =

事情过去几年了,想不到我竟然还是无法面对自己。
shit!
//EOF Read More...

2008-04-08

买刻录机有一年了~

今天又刻了几张碟。想起来,我买这个刻录机也有一年了吧~
一年之间用它刻碟无数,刻好的碟装了一箱了……
确实是方便了不少,为我节约了大量大精力和时间,看来当初做的这个决定没有错!
//EOF Read More...

2008-03-05

absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved

有一段时间没搞JSP了,今天用了标准标签库。奇怪,竟然会出现如下错误:

The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved

以前一直是正常的啊,探求了半天都未果。
(jstl.jar, standard.jar 我是放在WEB-INF/lib中的,以前这样做一直都OK啊!)
后来突发奇想,将这两个文件移到Tomcat的 shared/lib 中,然后重启那只笨猫,竟然OK了……
这个真的是诡异了,竟然在 WEB-INF/lib 中就找不到??
(其实WEB-INF/lib中我还有几个库也能找到啊!怎么就是标签库的就找不到呢?)

//EOF Read More...

2008-02-06

Core Wars

目录:


  1. 简介
  2. Mars机体系结构
  3. RedCode简单语法
  4. 语法实例讲解
  5. 简单实例
  6. 如何实战
  7. 相关资料

一、简介

    CoreWars 磁核大战,是个很古老的编程游戏。
就是大家各自写一个程序,然后把这些程序都载入内存,然后“并发运行”,看最后都结果谁能消灭内存中其他程序而最终存活下来。

    当然这些程序不是运行于家用PC上,也不是使用大家常用的Intel汇编来编写的。其运行平台是Mars机──Mars机是一种简单的计算机,有固定的8000个内存单元,和约10来个指令,当然这些程序都是使用这些指令来完成。

二、Mars体系结构

    Mars机器由一组内存单元,一个CU单元,一个简单进程管理系统,和一组指令集构成。

    Mars机的标准主要参考pMars虚拟机标准,主要有两个:88标准和94标准。一下都是默认为88标准(扩展94标准会专门标识出来。)

    该系统内存大小固定为8000个内存单元,每一个内存单元由5个部分构成:

  1. OPCODE 区:操作数区,该区域指定了机器指令,如:MOV, ADD 等。
  2. A 数据区:一个32位的数据存储区,存放相应数据,如:128, -100。
  3. A 数据区寻址修饰:指定了A数据区的寻址方式。
  4. B 数据区。
  5. B 数据区寻址修饰。
  6. 操作数修饰区。(94标准中新加入)

    系统寻址方式分为:立即寻址,直接寻址,间接寻址。
(94标准中加入:间接A-1寻址、间接A+1寻址、间接B-1寻址、间接B+1寻址)

    系统寻址都是相对于当前IP为基准寻址的,这是Mars系统和传统计算机最大的不同之处。
如:mov 0, 1 表示将当前指令所在内存单元的下一个内存单元。

    CU单元用于执行相应的指令,配合CU单元还有一个隐含的寄存器IP,每次执行单元执行IP指定的内存单元的指令。

    简单进程管理器。系统的进程由一个先进先出队列构成。每次管理系统将当前进程的执行地址出队放入IP寄存器,然后CU单元执行指令,最后将该进 程的下一条指令地址放入队尾。如果该进程产生新进程,则在队尾再加入新进程的起始执行地址。简单进程管理器保证每个进程轮流执行,当一个进程执行了 DAT 或者执行了 被0除 的操作则该进程结束。

系统指令包含:
DAT  MOV  ADD  SUB  JMP  JMZ  JMN  CMP  SLT  DJN  SPL
( 94标准中加入了新的指令: SUB MUL DIV MOD SEQ SNE NOP LDP STP )

    Mars机的汇编程序通常是RedCode,而Mars模拟器几乎都集成了一个RedCode的编译器,将RedCode程序编译为机器码写入内存。

    系统初始时内存中都是 DAT $0,$0 ,每一个程序加载到内存的随机位置,当多个程序都加载完后系统给每个程序创建一个进程,此时每个进程在进程队列中的位置是随机的,然后系统开始运行。


三、RedCode简单语法(按94标准)

指令写法:<label> OPCODE < OP_modify > <A_modify> A_field ,<B_modify> B_field
                             ------------------  ------------------
                                  整体记做A           整体记做B
<>包含的部分可以省略。
通常A表示源地址,B表示目标地址。

OPCODE包含:
DAT     中止进程
MOV     移动数据A到B
ADD     A + B -> B
SUB     A - B -> B
MUL     A * B -> B
DIV     B / A -> B (若A=0进程结束)
MOD     B % A -> B (若A=0进程结束)
JMP     跳转到A
JMZ     若 B == 0 则跳转到A
JMN     若 B != 0 则跳转到A
DJN     先 B - 1, 若 B != 0 跳转到A
SPL     开启一个新进程,新进程起始执行地址为A
SLT     若 A < B 跳过下一条指令
CMP     和SEQ相同
SEQ     若 A == B 跳过下一条指令
SNE     若 A != B 跳过下一条指令
NOP     空指令,什么也不干。

LDP/STP 本地地址操作指令,一般都没有实现,这里就不解释了。

DAT     指令可以只有A区域出现,此时一般编译器会将内存的A区域拷贝一份到B区域。
JMP/SPL 指令也可以只有一个A区域出现,此时一般编译器会将内存的B区域作为 $0

OP_modify包含:.A   指令读写目的地址的A区域
.B   指令读写目的地址的B区域 (如果Op_modify没有指定,则默认使用该规则)
.AB  指令读A指定地址的A区域,结果写入B指定地址的B区域
.BA  指令读A指定地址的B区域,结果写入B指定地址的A区域
.F   指令读A指定地址的A和B区域,操作结果写入B指定地址的A和B区域
.X   指令读取A指定地址的B区域,操作结果写入B指定地址的A区域;
     然后读取A指定地址的A区域,进行同样的操作操作结果写入B指定地址的B区域
.I   指令读写源和目标地址的整个内存单元。
    (mov指令没有指定OP_modify,并且源操作数不是立即数时使用该规则)

Modify指定了寻址方式:#   立即数
$   B直接寻址
@   间接寻址
<   B先减1,再间接寻址
>   B先减1,再间接寻址
*   A间接寻址
{   A先减1,再间接寻址
}   A先加1,再间接寻址

值得注意的是地址跳转相关的指令A区域不能为立即数,加减乘除模指令的B区域不能为立即数,否则要么模拟器报语法错误,要么作为执行非法指令中止进程或者作为空指令处理。

Filed就是指定数据的地方了。

程序注释符为";",从;到行尾均作为注释。但有几个特殊的注释,作为程序信息:
;name   filename  指定程序的名字
;author author    指定程序的作者
;debug  [static|off] 指定是否调试程序,但不是每个模拟器都实现

此外不同的模拟器也有自己特定的特殊符号。

宏一般不同的模拟器都有自己的一套,但通常都实现了EQU,语法
label EQU 表达式    (表达式可以为数字或标签的加减乘除)

ORG 数字或标签       指定程序执行的开始地址
END <数字或标签>     程序结束,此后的部分不会被编译,如果指定了一个数字或标签则作为程序开始地址。


四、语法实例讲解

以下我们写一个完整的RedCode文件:
;name Test
;author cloud

org 1
data  dat 5
    mov data , @ data
    mov -2   , < data
    mov # 3  , data
    jmp -1
end

编译器编译后将各指令的各个区域写入对应内存单元的对应区域。
假如程序放到内存的0001单元到0005单元,写入内存后反汇编过来就是
0001  DAT $ 5 , $ 5
0002  mov $ -1, @ -1
0003  mov $ -2, < -2
0004  mov # 3 , $ -3
0005  jmp $ -1, > 2
程序入口地址org 1,就是程序的第1条指令开始(编号从0开始),就是地址0002

0002处mov指令的寻址如下:
源地址:  $ -1 ,就是直接寻址,以当前地址(0002)相对的-1处的地址作为源地址 ,即 0001
目的地址:@ -1 ,就是间接寻址,以当前地址(0002)相对的-1处的地址的 B区域作为直接寻址地址
就是0001处的B数据区的数据5作为直接寻址地址,取出0001处的5作为直接寻址,5也是一个相对地址,相对于0002就是地址0007,最终目标地址为0007那么最终就是将0001的内存单元拷贝一份到0007

0003处的mov源地址一样,操作的是0001的地址,目标地址为:
 < -2 ,就是取出相对0003地址-2的地址(就是0001)的B数据区(就是5),先将其减1(即为4),然后在存放回去(0001处的B数据区变成4),将得到的结果(4)作为直接寻址,目标地址就是相对当前地址(0003)为4的地址,即0007最终结果和上一条指令一样,但真正内存单元拷贝时001的B数据区已经变成了4

0004处的结果就是把3放到0001的B数据区中

0005处的结果就是把0007的B数据区的数据加1,然后跳转到0006


五、简单实例

作为对抗程序最重要的就是生存,一个最简单的程序就是
jmp 0始终跳转到自身,死循环,自己没有攻击能力,唯一取胜的方法就是期望对手自己死亡,可谓守株待兔。
但这个程序一个弱点是自己在内存中的地址固定,很容易收到攻击。

下面这个程序可以说是非常出名的IMP程序了:
mov 0,1它不断把自己移动到下一个内存单元,然后执行到下一个内存单元执行。

这个程序具有一定的攻击能力,能够覆盖别人的程序,但是覆盖他人程序后也不能取胜,因为不能导致他人程序执行中止进程操作,唯一的取胜方法也是等待他人程序死亡,但自身在内存中的位置不断移动,生存能力比jmp 0强。

对付IMP程序的方法也很简单:
jmp 0 , < -2这段代码始终跳转到自身,但是跳转前会将前面的第2个内存单元的B数据区数据减1,当imp程序将自己移动到该地址后将被修改为 mov 0, 0 这样下次IMP执行时执行mov 0, 0 没能将自己移动,但执行地址已经到达下一个内存单元,而Mars系统初始化时内存单元为 dat 0, 0 这就导致IMP程序执行一个DAT指令而导致进程中止

攻击他人程序通常都是通过扔出一个DAT来覆盖他人程序,使得其他程序因执行DAT而中止比如下面这个程序:
org start
    dat 0,5
start
    mov -1,@-1
    jmp -1,> -2
end
第一次mov -1 , @ -1 将 dat 0, 5 拷贝一个到相对为5的地址处进行一次轰炸
    jmp -1 ,> -2将 dat 0 ,5 修改为 dat 0, 6
然后跳转执行 mov -1, @ -1 ,执行mov时导致将dat 0,6 拷贝到相对为6的地址进行轰炸
如此循环,最终将对整个内存以dat轰炸一遍,可谓杀伤力非常。

像这样的轰炸程序是非常有效的攻击,现在的很多程序都是靠这种手法攻击他人,然后利用IMP的方法移动自己避免被攻击。

当然,你也可以每隔几个单元轰炸一次:
org 1
   dat 0  , 5
   mov -1 , @-1
   add #4 , -2
   jmp -2
end 
这个程序每次将dat 0,5的B数据区加4,然后在MOV处以此寻址进行轰炸,所有长度大于4的程序都容易受到它的攻击。

作为对抗手段,程序可以采用哨兵概念,先在代码前面放一个数据,然后检查该数据是否被改变,如果被改变表示其他程序运行到了该处,或者攻击了该地址,自己就可以采取相应的对策,把自己移动躲避攻击或者发动对该地址的攻击。


六、如何实战

需要一个虚拟机。RedCode扩展名为.red放/redcode/目录下。


七、相关资料

http://www.koth.org/ 官方站点
http://vyznev.net/corewar/guide.html RedCode初学指导



// EOF Read More...

2008-02-01

ScribeFire 中添加 <code> 标签支持

Scribefire具体安装在 <firefox home path>/extensions/ 下的哪个目录可以在 extensions.rdf 文件中找到(搜索 "ScribeFire" 即可),以下文件操作的根目录均为 Scribefire 的安装目录。

1. 自定义 <code> style
文件 /chrome/skin/blank.css 中添加:
code {
  display: block;
  font-size: 110%;
  margin: 5px;
  margin-left: 1.3em;
  padding: 3px;
  padding-left:  10px;
  background: #eee;
  border: 1px solid #ccc;
  border-left: 3px solid #ccc;
}


2. 操作界面外观
文件 /chrome/skin/toolbar/toolbar-code.png
(自己作的“<code>”按钮图片)

文件 /chrome/skin/overlay.css 中设置按钮外观图片
#code-button {
  list-style-image: url(chrome://performancing/skin/toolbar/toolbar-code.png);
}


3. 界面、事件关联

文件 /chrome/content/editor.xul 中:
 1) 按钮事件关联:
<command id="cmd_blockquote" oncommand="performancingMidas.blockquote()"/>
下依葫芦画瓢之:
<command id="cmd_code" oncommand="performancingMidas.code()"/>

 2) 按钮布局:
<toolbarbutton id="blockquote-button" command="cmd_blockquote" tooltiptext="&performancing.editor.bar.quote.tt;"/>
下依葫芦画瓢之:
<toolbarbutton id="code-button" command="cmd_code" tooltiptext="&performancing.editor.bar.code.tt;"/>


文件 /chrome/content/midas.js 中定义事件响应,分别在:
performancingMidas.blockquote = function(){
...
}

case "blockquote":
...

case "blockquote":
...

下依葫芦画瓢之。


文件 /chrome/content/locale-default/overlay.dtd 中定义 tooltips,在
<!ENTITY performancing.editor.bar.quote.tt "Quote">
下依葫芦画瓢之:
<!ENTITY performancing.editor.bar.code.tt "Code">

又做了一件无聊之事~~

//EOF Read More...

2008-01-31

QT右键菜单

  1. 右键弹出菜单:
    重写void QWidget::contextMenuEvent(QContextMenuEvent)函数
    如:
    void MainWindow::contextMenuEvent( QContextMenuEvent* e)
    {
      QMenu *menu = new QMenu();
      menu->addAction(openAct);
      menu->addSeparator();
      menu->addAction(quitAct);
      menu->exec(e->globalPos());
      delete menu;
    }

  2. 定制原生器件的弹出菜单(某些器件可能本身就自带popMenu)
    那么如何获得已有的菜单项呢?利用:
    QList<QAction *> QWidget::actions() const
    返回的是其所包含QAction的一个列表。

    如:
    TextViewer::TextViewer() : QTextEdit()
    {
      this->setReadOnly(true);
    }

    void TextViewer::contextMenuEvent ( QContextMenuEvent* e )
    {
      QMenu *menu = createStandardContextMenu();

      // remove the separator between 'copy' & 'select all'
      menu->removeAction(menu->actions().at(1));

      // insert separator before 'copy'
      QAction *sepTop = menu->insertSeparator(menu->actions().at(0));
      // insert 'open' & 'top' before that separator
      menu->insertAction(sepTop, ((MainWindow*)this->parentWidget())->openAction());
      menu->insertAction(sepTop, ((MainWindow*)this->parentWidget())->topmostAction());

      // add separator after 'select all'
      menu->addSeparator();
      // add 'quit' after that separator
      menu->addAction(((MainWindow*)this->parentWidget())->quitAction());

      menu->exec(e->globalPos());

      delete menu;
    }

    效果预览:



//EOF Read More...

QT快捷键

  1. shortcut作用域。
        QT 无全局快捷键(全局快捷键与相应的窗口管理器(KDE等)相关)。
    QAction::setShortcutContext(Qt::ShortcutContext)
      Qt::ApplicationShortcut 当前程序中有任意一窗口被激活时可使用的快捷键
      Qt::WindowShortcut      仅适用于当前窗口的 (default)
      Qt::WidgetShortcut      当前器件被激活时可用的快捷键


  2. 若该窗口无menuBar,对于popupMenu[contextMenu]中的menuItem之快捷键会无效。

      QAction 为抽象器件,可将该QAction添加到该窗口中,则可使用该菜单项的快捷键了 。


//EOF Read More...

QT程序外观定制

今天才发现,原来QT的程序可以像网页写CSS那样来用StyleSheet定制外观,真是方便啊。
(Qt >= 4.2) 其语法、作用域、优先级和网页的CSS差不多。
QApplication::setStyleSheet(QString);
QWidget::setStyleSheet(QString);

  1. 程序级的外观:(作用于整个程序的器件)
    如:
    QLineEdit { background: yellow }
    QCheckBox { color: red }

  2. 器件级的外观:(作用于本器件及其子器件)
    如:
    textViewer->
      setStyleSheet("background-color: #FFFFBB;"
                    "color: #000099;"
                    "margin: 10px;"
                    "padding: 5px;"
                    "padding-left: 15px;"
                    "padding-right: 15px;"
                    "border-radius: 5px;" // 圆角边框(只用IE的人就不知道了吧:D)
                    "border: 3px solid #abc;"
    );

    效果预览:




//EOF Read More...

2008-01-27

fucking the damn winter!!

今年实为近几十年来最严重的冰冻天气,道路结冰,高压输电线路冻成了几十厘米粗的“冰棍”~~还冻垮了几个高压输电塔,冻断了输电线路,全省供电紧张。
托这种鬼天气的福,我们这几天每天都是在一天之内全城停电、断电多次,搞的这几天什么都干不成。
调试一个程序好不容易恢复到上次的断点条件,马上又黑了~~郁闷啊!!搞的我都不敢开机了。
想出去走走,道路又滑的要命~听说还摔死了几个人!-_-(幸好我比较小心,就第一天摔了几跤)
不止如此,听说水管被冻爆了,今天还停水了── Oh, my God!!!(真担心我家的太阳能会不会被冻爆?)
据说这种鬼天气还要持续十多天!!??

这样下去怎么过啊~~ 不如冬眠算了!
说实话冬眠确实是个好办法,不过我天生就不是冬眠动物啊,白天怎么睡都睡不着的~~还弄得浑身酸痛~呜……

//EOF Read More...

2008-01-20

墨菲定理

http://baike.baidu.com/view/40544.htm

“如果一件事情有可能向坏的方向发展,就一定会向最坏的方向发展”。

这个说得果然对!。。。。。。 郁闷啊!
//EOF Read More...

2008-01-12

KISS

[转载,源出处不可考(不知被转过多少次了)。]

KEEP IT SIMPLE , STUPID !


KISS──UNIX/LINUX哲学思想

      编写只做一件事情,并且要做好的程序;编写可以在一起工作的程序,编写处理文本流的程序,因为这是通用的接口。这就是UNIX哲学.所有的哲学真正的浓缩为一个铁一样的定律,高明的工程师的神圣的“KISS 原则”无处不在。

      大部分隐式的UNIX哲学不是这些前辈所说的,而是他们所做的和UNIX自身建立的例子。从整体上看,我们能够抽象出下面这些观点:
  1. 模块性原则:写简单的,通过干净的接口可被连接的部件;
  2. 清楚原则:清楚要比小聪明好。
  3. 合并原则:设计能被其它程序连接的程序。
  4. 分离原则:从机制分离从策略,从实现分离出接口。
  5. 简单原则:设计要简单;只有当你需要的时候,增加复杂性;
  6. 节俭原则:只有当被证实是清晰,其它什么也不做的时候,才写大的程序
  7. 透明原则:为使检查和调试明显更容易而设计
  8. 健壮性原则:健壮性是透明和简单的追随者
  9. 表现原则:把知识整理成资料,于是程序逻辑能变得易理解和精力充沛的。
  10. 最小意外原则:在接口设计中,总是做最小意外事情
  11. 沉默原则:当一个程序令人吃惊什么也不说的时候,他应该就是什么也不说
  12. 修补补救:当你必须失败的时候,尽可能快的吵闹地失败
  13. 经济原则:程序员的时间是宝贵的;优先机器时间节约它。
  14. 产生原则:避免手工堆砌;当你可能的时候,编写可以写程序的程序;
  15. 优化原则:在雕琢之前先有原型;在你优化它之前,先让他可以运行;
  16. 差异原则:怀疑所有声称的“唯一真理“
  17. 可扩展原则:为将来做设计,因为它可能比你认为来的要快


//EOF Read More...