Archive for 十二月, 2006

搬家――搬家――不在和讯了

星期天, 十二月 10th, 2006

<![CDATA[

搬到http://blogger.com

windows环境下的SVN安装

星期五, 十二月 8th, 2006

<![CDATA[
>操作系统:windows2000 pack4
SVN版本:1.3.0
Tortoise版本:TortoiseSVN-1.3.2.5840-svn-1.3.0
汉化语言包:LanguagePack_1.3.2_zh_CN
Apache版本:apache_2.0.55-win32-x86-no_ssl

步骤一:安装包下载
Apache下载:在http://httpd.apache.org/download.cgi下载apache_2.0.55-win32-x86-no_ssl.msi

SVN下载:在http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91
下载svn-1.3.0-setup.exe

Tortoise下载:在http://prdownloads.sourceforge.net/tortoisesvn/TortoiseSVN-1.3.2.5840-svn-1.3.0.msi?download下载TortoiseSVN-1.3.2

Tortoise语言包下载:在http://prdownloads.sourceforge.net/tortoisesvn/LanguagePack_1.3.2_zh_CN.exe?download下载1.3.2的中文简体语言包。

步骤二:安装Apache

步骤三:安装SVN

步骤四:安装Tortoise

]]>

你的 Web 服务可以赢利吗?

星期二, 十二月 5th, 2006

<![CDATA[

文章来源: http://chn.blogbeta.com/245.html

原文链接:Will Your Web App Make Money?
原文作者:Ryan Carson

假如你有构建一个Web服务的想法,看看它将是会成为你的摇钱树,还是会导致你破产。

构建Web服务,第一部分

这是第一篇关于如何构建Web服务的系列文章。今天,我们将讨论在你的Web服务构建中关于现金流和财务可行性这两个重要的问题。

关于这方面的问题,我们曾获得了许多经验――在我们构建 DropSend 服务的时候,我们的第一个企业Web应用,面临着同样的问题:它能为我们带来收益吗?DropSend当前拥有17,000的用户,仅花费了五个多月的时间。使用了6台服务器,托管在 San Francisco 的 365Main 机房。我们的服务基于 LAMP(Linux + Apache + Mysql + PHP)架构,三个开发人员和一个设计师(由我和我妻子 Gill 做协助)。我们的桌面应用程序可构建在 Mac 和 PC 上,都是基于私有的API。从构思到创建,花了9个月的时间,总计投入£35,000。

下了这么大的赌注,我们不得不设法确保DropSend的可赢利性,而不仅仅是一串提供给人们玩玩而已的“Web糖果”。

你的Web服务可以赚取足够的钱吗?

除非你是一个有很多钱可以烧的大型企业公司,或仅仅是个寻求乐趣的编码者,否则在你开始构建 Web 应用前,你需要问自己一个最重要的问题――人们会愿意为它付费吗?这并非是唯物主义的金钱观。若你没有构想出切实可行的收益模式来支撑你的服务,那么你将 变得不切实际。我们需要澄清一下,如果你的应用程序仅仅是做着玩的,那么它无需考虑可赢利性。若将来它在某方面变得有价值了,那再好不过了,Delicious 就是一个很好的例子。然而,如果你花费了大量的时间在你的服务程序上面,并且你还有计划靠它来维持你的生活,那就建议你最好有个坚实的盈利方案。

你将获得1%-2%的付费用户

若你提供一个免费的方案给你的用户(例如,DropSend 提供一个免费的方案,让新用户每个月可以免费发送5个次文件),然后预想将会有大约98%-99%的用户采用该方案。这意味着你将仅可指望1%-2%的用 户会采用付费方案。根据我们的经验,这个比例是合理的,同行的其他主要竞争者也认同。这大概也是业界的平均值。

许多人(包括我们自己――在创办 DropSend 之前)都大大的高估了他们将获得的付费用户数量。让我们做个计算,如果你预计在前6个月将会有2000的用户,按1%的付费用户算,你的收入将会是多少。那么,再客观一些,若你实际上只获得了65%的注册用户,估计你的服务会为你赚取多少钱?请参照下列现金流数据表的示例。你可以从这里下载

>0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” title=”A screengrab of several rows of a cashflow spreadsheet” alt=”A screengrab of several rows of a cashflow spreadsheet” src=”http://www.thinkvitamin.com/images/articles/features/will-your-web-app-make-money/cashflow.gif”>

万能的现金流数据表

若你想确定你的Web服务是否具备可赢利性,要做的第一件事情就是创建一个现金流数据表。可以用Excel,但你也可以使用许多免费的在线电子表格工具,比如Num Sum

对于现金流,你们当中的一些人可能不是很熟悉,它是一个简单的文档,用于帮助你快速的了解公司当前的现金状况。实际上,它仅仅是帮你合计一下每月的收入,扣除当月的开支,并告诉你还有多少钱存留在银行。这绝对不是什么高深的学问,但它却是你业务成功的要素。

之所以要创建现金流,是帮助你看到未来可能的现金短缺。它将给与你充足的时间做调整,在你的业务停止运转前。如果想获得更多关于创建现金流方面的信息,Signal Vs Noise 上有一篇名为 in-depth article on cashflow 的文章很具指导性。若你是一个小公司,你的现金流应包含当月及未来的三个月。

一旦你创建了现金流数据表,你需要再加上你的预期收益,逐月地,以确保赚取足够的钱来支撑你的业务。现实是残酷的,它可能会缩减你预期收益的35%。如果你的公司仍有可用资金(在银行还有存款),即使这是个悲观的预见,你继续往前就是了。如果没有,务必要小心跟进。

让风险最小化

将金融风险最小化的一个很好途径就是,让你所开展的 Web 服务尽可能的基于或贴近你当前工作(可能是一个公司,计日工也好)相关的一个项目。如果你的公司正在做一些能够带来收益的东西,那么继续做下去,虽然你正 在构建你的新应用。这意味着你可以启动你的服务,屏息凝神,看看它是否有起色。如果失败了,你仍然有固定的收入来维持生计,你也不至于会破产。

信用卡测试

一个对你服务的财务可行性的测试方法,我们称之为“信用卡测试”。试问自己是否会真正地说出你的信用卡号码、发行日期、验证码以及姓名。你的服务是否有足 够的价值让人们支付他们辛苦赚来的钱,或者它仅仅是有用的?这两者有很大的不同!若你的应用不是针对你自己,那么尝试转换一下思路,把你自己放在用户的角 度,试着想象一下是什么将有可能影响你的支付行为。俗话说:己所不欲,勿施于人。如果你有信心认为你的服务具备足够的价值,令人们真正的毫无争议地为它付 费,那么是时间开始构建它了。

调研

另一个影响财务可行性的因素就是竞争。你是否调查过有多少其他的产品已经推出了?你能让自己的做得更好或有差异化吗?是否有比你更大的公司在计划创建类似 的东西?他们的市场路线是什么?他们是否已经拥有现成的行销渠道?把所有的这些都总结起来。但最关键的是不能让它令你分心。记得,所有人都曾认为世界上的 搜索引擎已经足够了,然而 Google 却诞生了。所以无论在什么时候,都还是有东西可以被改进的。

第二部分…

下一部分,我们将谈论一下如何管理你的Web开发项目,同时也给大家一些技巧和提示来提高开发的速度。无论你是否认同这些观点,你都可以在这里给出你的见解。待续…

]]>

东拉西扯:反商业作为一种商业

星期二, 十二月 5th, 2006

<![CDATA[

文章来源: http://blog.donews.com/keso/archive/2006/11/30/1087803.aspx

在对牛乱弹琴的blog上看到这篇文章,不错,值得思考。

改变未来IT业发展的趋势

星期二, 十二月 5th, 2006

<![CDATA[

文章来源: http://chn.blogbeta.com/116.html

原文地址:Growth puts Japan back with the leaders

日本经济在过去三个月实现了出人意料的强劲增长,促使日本再度回归世界经济强国浪尖,同时也预示了其长达15年经济萧条的终结。

作为世界第二大经济体,日本经济在第四季度(译者注:指2005年第四季度)增长了1.4%,远超美国的0.3%和欧盟的0.4%。

得益于最后3个月超过市场预期的增长,日本经济2005年全年的增幅达到2.8%。同时,2005年也成为日本经济在内需刺激下的第三个健康增长年。

经济学家认为,由于财政不再受坏账拖累,日本迎来了自1991年以来保持经济持续增长的最佳时机。

日本银行部分官员认为宽松的货币政策应当终止(译者注:2006年2月9日,日本银行政策委员会决议继续维系现行的宽松货币政策),而较高的经济增速似乎是对此种观点的有力支持。出于这样的考虑,日本的部长们(译者注:在日本称为“相”,如大藏相即财政部长:Financial Minister)近来有意压低了相关数字。而昨天,日本财政金融大臣与谢野馨(Kaoru Yosano)却一反常态,认为增长的数字是“非常积极的经济指标”。

分析家认为经济的高增长预示着日本最终走出了多年的经济停滞阶段。

2005年日本经济发展的中流砥柱则是国内因素的主导作用。家庭消费上升了2.2%,而非住宅商业投资则陡增了8.4%。同时,出口净额对年度增长2.8%的贡献仅为0.2个百分点。

然而,日本在向全世界宣称经济复苏这个好消息之前,还要跨越几个坎。通货紧缩的阴影依旧。而国内生产总值(译者注:GDP,Gross Domestic Product)的统计数字则表明,消费者价格指数(译者注:CPI, Consumer Price Index)近来开始的增长,在较高程度上源自油价上升。

与此同时,日本经济增长对于减小全球贸易失衡(具体体现为美国贸易逆差)的作用甚微。进口的增速尚不足以降低日本的贸易顺差。

]]>

程序员应学C语言的十个理由

星期二, 十二月 5th, 2006

<![CDATA[

文章来源: http://www.jubling.com/ten-reasons-why-every-programmer-should-learn-c.html

来自Jubling的文章说:每个程序员在他们的编程事业生涯当中都应该学C语言。C语言有太多不容忽视的好处。它不仅可以带来更多的工作机会,而且也会在总体上让你对计算机有更多的了解。

1)相对于其它编程语言(C++,Java),C语言是更底层的。在一个较底层水平编程能够在总体上让你进一步加深对计算机的理解。

2)设备驱动程序和操作系统都是唯一采用C语言写的。现在,也许你从来也不会去写一个设备驱动程序或一个操作系统,但是如果只是要求你去修改一下,会是怎样呢?

3)如果你想要得到一份给微控制器编程的工作那会是什么样呢?它们都是用C语言编程的。你是否打算因为自己不想去学一门新语言而限制你获得更多工作的机会呢?

4)相比用其它语言写出的程序,C语言更小更快。有时你的程序所需要的速度只有C语言能够提供。

5)如果你已经学会了C语言,那么你将能够学习任何现代的编程语言。这背后的原因是所有的现代的编程语言都是基于C语言之上发展而来的(比如Java,C++,C#等等)。

6)由于C语言已经存在了好多年,它有很大的网络社区和收集的代码库。这些允许你快速有效的实现新算法或以前已经编写好的函数。

7)C语言是开源社区的使用语言。开源帖子、Linux都是用C语言编写的。如果你会C语言,你就能够参与到众多的象Source Forge这样的开源社区中并做出贡献。

8)C语言是仅有的教你什么是真正的指针的语言。C#和Java完全跳过了这个章节。指针赋予了C语言不凡的能力。

9) 对于编程工作C语言仍然是最一般的要求会的语言。它是值得你花时间去装进肚子里的。

10)任何带有微处理器的东西都支持C语言。从你的微波炉到你的手机,C语言赐予技术以力量。

]]>

近日琐事

星期二, 十二月 5th, 2006

<![CDATA[

Introduction to wxWidgets――跨平台界面开发的优秀工具

星期二, 十二月 5th, 2006

<![CDATA[

文章来源: http://www.codeproject.com/library/wxwidgets.asp

wxWidegets是个好东西,我喜欢,后面开始学习


Introduction

wxWidgets formerly known as wxWindows is a framework for developing cross-platform GUI applications in C++. Julian Smart started the framework in 1992 at the Artificial Intelligence Applications Institute, University of Edinburgh. In 1995, a port to Xt was released by Markus Holzem. In May 1997, the Windows and the GTK+ ports were merged and put into a CVS repository.

What is wxWidgets

wxWidgets gives you a single, easy-to-use API for writing GUI applications on multiple platforms. Link it with the appropriate library for your platform (Windows/Unix/Mac) and compiler (almost any popular C++ compiler), and your application will adopt the look and feel appropriate to that platform. On top of the great GUI functionality, wxWindows gives you: online help, network programming, streams, clipboard and drag and drop, multithreading, image loading and saving in a variety of popular formats, database support, HTML viewing and printing, and much more.

Who should use wxWidgets

wxWidgets is a framework very much similar to MFC, except for a few negative points of its own. Those MFC programmers who are aware of the growing number of Linux users and who want to write cross platform GUI applications can use wxWidgets. With wxWidgets, it is very easy to use a framework based on C++ and it has a proven record of 13 years. In fact, wxWidgets is very stable and is supported on:

  • Windows 3.1, Windows 95/98, Windows NT, Windows 2000/XP, Windows ME, Windows CE.
  • Linux and other UNIX platforms with GTK+.
  • UNIX with Motif or the free Motif clone Lesstif.
  • Mac OS.
  • Embedded platforms are being investigated. See the wxUniversal project.
  • An OS/2 port is in progress, and you can also compile wxWidgets for GTK+ or Motif on OS/2.

Why use wxWidgets

There are a number of options available for writing cross platform GUI development, like: JAVA, Mono.NET, Qt, etc. Java has failed to prove itself as an efficient alternative. Qt is good but commercial and nobody knows its future. Mono.NET seems to be good but is largely driven by Microsoft, it seems like a copy of the work done by Microsoft and it has not yet proved itself as a successful alternative. Also, people would not like to use an extra burden of layer for highly efficient software. As wxWidgets does not use any middle layer and uses only the native controls available on the platform, it gives a nice look and feel to the application.

  • It is very complete. There are many utility classes like : wxRegEx, wxFTP, wxSplashScreen, wxZipInputStream, etc.
  • It is still heavily developed, and has a lot of support from the open source community.
  • Many compilers and platforms are supported : Windows, Linux, Mac, Unix.
  • There&aposs a lot of documentation available on the internet, forums, wxBook.
  • It&aposs free for personal and commercial use, and is more flexible than the LGPL license.
  • Whenever possible, wxWindows uses the platform SDK. This means that a program compiled on Windows will have the look and feel of a Windows program, and when compiled on a Linux machine, it will have the look and feel of a Linux program.
  • Ease of learning, it has the same Event tables and similar API and classes like that of WINAPI and MFC.
  • A lotof sample is provided in the samples directory of the installation, which contains how to use the basic controls, multi threading, MDI, drag and drop, sockets, printing and lots more.
  • A lot of ready to use classes are available, like: wxGenericDirCtrl, wxCalendarCtrl, wxDatePickerCtrl, wxTipWindow, wxStyledTextCtrl, wxStaticPicture, wxLEDNumberCtrl, wxEditableListBox, wxFoldPanelBar, wxGIFAnimationCtrl, wxSplashScreen, OGL (Object Graphics Library), FL (Frame Layout), etc. This is one of the main repository.
  • A lot of add on libraries are available to make the programming task more easier:

Main features

  • Multi threading.
  • Clipboard and drag and drop.
  • Network programming, like: wxSMTP, wxHTTP, wxFTP.
  • Image loading and saving in a varietyof popular formats.
  • Streams (ZIP, Network, File, etc.), like: wxRarInputStream.
  • Database support, like: wxDao.
  • HTML viewing and printing, like: wxMozilla, wxIE.
  • XML based resource, multi language/Unicode support.
  • Default style themes available with the OS (e.g.: XP style themes).

Similarity to MFC

MFC and wxWidgets macros

MFC version wxWidgets version
BEGIN_MESSAGE_MAP BEGIN_EVENT_TABLE
END_MESSAGE_MAP END_EVENT_TABLE
DECLARE_DYNAMIC DECLARE_CLASS
DECLARE_DYNCREATE DECLARE_DYMAMIC_CLASS
IMPLEMENT_DYNAMIC IMPLEMENT_CLASS
IMPLEMENT_DYNCREATE IMPLEMENT_DYNAMIC_CLASS
IsKindOf(RUNTIME_CLASS(CWindow)) IsKindOf(CLASSINFO(wxWindow))

MFC and wxWidgets classes

Miscellaneous Classes
MFC version wxWidgets version
CWinApp wxApp
CObject wxObject
CCmdTarget wxEvtHandler
CCommandLineInfo wxCmdLineParser
CMenu wxMenu, wMenuBar, wxMenuItem
CWaitCursor wxBusyCursor
CDataExchange wxValidator
Window Classes
MFC version wxWidgets version
CFrameWnd wxFrame
CMDIFrameWnd wxMDIParentFrame
CMDIChildWnd wxMDIChildFrame
CSplitterWnd wxSplitterWindow
CToolBar wxToolBar
CStatusBar wxStatusBar
CReBar wxCoolBar, but see contrib/src/fl and wxAUI, wxDockIt
CPropertyPage wxPanel
CPropertySheet wxNotebook, wxPropertySheetDialog
Dialog Classes
MFC version wxWidgets version
CDialog wxDialog
CColorDialog wxColourDialog
CFileDialog wxFileDialog
CFindReplaceDialog wxFindReplaceDialog
CFontDialog wxFontDialog
CPageSetupDialog wxPageSetupDialog
CPrintDialog wxPrintDialog
Control Classes
MFC version wxWidgets version
CAnimateCtrl wxMediaCtrl, wxAnimationCtrl
CButton wxButton
CBitmapButton wxBitmapButton
CComboBox wxComboBox, wxChoice
CDateTimeCtrl wxDatePickerCtrl
CEdit wxTextCtrl
CHotKeyCtrl None, but see Keybinder
CListBox, CDragListBox wxListBox
CCheckListBox wxCheckListBox
CListCtrl wxListCtrl, wxListView
CMonthCalCtrl wxCalendarCtrl
CProgressCtrl wxGauge
CReBarCtrl None, but see contrib/src/fl and wxAUI, wxDockIt
CRichEditCtrl wxTextCtrl
CScrollBar wxScrollBar
CSliderCtrl wxSlider
CSpinButtonCtrl wxSpinButton, wxSpinCtrl
CStatic wxStaticText, wxStaticLine, wxStaticBox, wxStaticBitmap
CStatusBarCtrl wxStatusBar
CTabCtrl wxTabCtrl
CToolBarCtrl wxToolBar
CToolTipCtrl wxToolTip
CTreeCtrl wxTreeCtrl
Graphics Classes
MFC version wxWidgets version
CBitmap wxBitmap, wxImage, wxIcon, wxCursor
CBrush wxBrush
CPen wxPen
CFont wxFont
CImageList wxImageList, wxIconBundle
CPalette wxPalette
CRgn wxRegion
CClientDC wxClientDC
CMetaFileDC wxMetaFileDC
CPaintDC wxPaintDC
CWindowDC wxWindowDC
CDC wxDC, wxMemoryDC
Data Structure Classes
MFC version wxWidgets version
CArray, CObArray, CPtrArray wxArray
CStringArray wxArrayString
CDWordArray, CByteArray, CUIntArray wxArrayInt
CList, CPtrList, CObList wxList
CStringList wxArrayString, wxStringList
CMap wxHashMap
CString wxString
CPoint wxPoint
CRect wxRect
CSize wxSize
CTime wxDateTime
CTimeSpan wxTimeSpan, wxDateSpan
COleVariant wxVariant
Internet Classes
MFC version wxWidgets version
CSocket wxSocket
CFtpConnection wxFTP
CHttpConnection wxHTTP
Document/View Classes
MFC version wxWidgets version
CDocument wxDocument
CView wxView
CDocTemplate, CSingleDocTemplate, CMultiDocTemplate wxDocTemplate
Drag and Drop Classes
MFC version wxWidgets version
COleDataSource wxDataObject
COleDropSource wxDropSource
COleDropTarget wxDropTarget
File Classes
MFC version wxWidgets version
CFile wxFile, wxFFile, wxTextFile
CMemFile wxMemoryInputStream, wxMemoryOutputStream
CSocketFile wxSocketInputStream, wxSocketOutputStream
CRecentFileList wxFileHistory
Multithreading Classes
MFC version wxWidgets version
CWinThread wxThread
CCriticalSection wxCriticalSection
CMutex wxMutex
CSemaphore wxSemaphore

Class hierarchy

0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=310 src=”http://www.codeproject.com/library/wxWidgets/wxposter.gif” width=439>

Getting started

Starting with wxWidgets is really very easy. Just follow these steps:

  • Download the wxMSW-2.6.2-Setup.exe from the sourceforge.net website.
  • Run the setup&aposs EXE and install it in say “C:\wxWidgets\” folder.
  • Add an environment variable $(WXWIN) to your system. The value will be the path of the folder where you have installed wxWidgets.
    1. Right click on the My Computer icon on your desktop.
    2. Select Properties.
    3. A dialog appears. Select the “Advanced” tab in that dialog.
    4. Click “Environment Variables” button.
    5. Another dialog appears. Click on the “New” button in the “System variables” box.
    6. Add “WXWIN” in the “Variable name” text box and the folder path where you have installed wxWidgets in the “Variable value” text box.
    7. Click the OK button till all the dialogs disappear.

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=303 src=”http://www.codeproject.com/library/wxWidgets/image001.jpg” width=500>

  • Open “src\wxWindows.dsw” and “build\msw\wx.dsw” files in Visual studio and build the projects (libraries) in the solution for all the project configurations namely: Debug, Release, Debug DLL, Release DLL, Unicode Debug, Unicode Release, Unicode Debug DLL, Unicode Release DLL. These solution files are in the wxWidgets installation folder. This step will create some libraries needed by our application for linking. These files will be created in the “lib“, “lib\vc_lib\” and “lib\vc_dll\” folders under your wxWidgets installation directory.
  • Now everything is ready to feel the power of wxWidgets.

Hello world

Hello world is a classic example to start learning any new language. It gives an overview of the language without going deeper into it.

  • Just create a new project “HelloWorld” in your Visual Studio editor of “Win32 Project” type:

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=393 src=”http://www.codeproject.com/library/wxWidgets/image002.jpg” width=531>

  • In the Application Settings, choose the application type as “Windows Application” and in the Additional options check the “Empty project” checkbox and click the “Finish” button:

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=385 src=”http://www.codeproject.com/library/wxWidgets/image003.jpg” width=541>

  • Now create a new file, by pressing “Ctrl+N”, and select the type as “C++ File” in the “Visual C++” categories. Click Open:

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=373 src=”http://www.codeproject.com/library/wxWidgets/image004.jpg” width=531>

  • Now type the following code into the file: >0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” id=preimg0 style=”CURSOR: hand” height=9 src=”http://www.codeproject.com/images/minus.gif” width=9 preid=”0″> Collapse
    /* * hworld.cpp * Hello world sample by Robert Roebling */ #include “wx/wx.h”  class MyApp: public wxApp{    virtual bool OnInit();}; class MyFrame: public wxFrame{public:     MyFrame(const wxString& title,            const wxPoint& pos, const wxSize& size);    void OnQuit(wxCommandEvent& event);    void OnAbout(wxCommandEvent& event);     DECLARE_EVENT_TABLE()};enum{    ID_Quit = 1,    ID_About,}; BEGIN_EVENT_TABLE(MyFrame, wxFrame)    EVT_MENU(ID_Quit, MyFrame::OnQuit)    EVT_MENU(ID_About, MyFrame::OnAbout)END_EVENT_TABLE() IMPLEMENT_APP(MyApp)bool MyApp::OnInit(){    MyFrame *frame = new MyFrame( “Hello World”,          wxPoint(50,50), wxSize(450,340) );    frame->Show(TRUE);    SetTopWindow(frame);    return TRUE;}  MyFrame::MyFrame(const wxString& title,        const wxPoint& pos, const wxSize& size): wxFrame((wxFrame *)NULL, -1, title, pos, size){    wxMenu *menuFile = new wxMenu;    menuFile->Append( ID_About, “&About…” );    menuFile->AppendSeparator();    menuFile->Append( ID_Quit, “E&xit” );     wxMenuBar *menuBar = new wxMenuBar;    menuBar->Append( menuFile, “&File” );     SetMenuBar( menuBar );    CreateStatusBar();    SetStatusText( “Welcome to wxWindows!” );} void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)){    Close(TRUE);} void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)){    wxMessageBox(“This is a wxWindows Hello world sample”,        “About Hello World”, wxOK | wxICON_INFORMATION, this);}
  • Now save the file in the same project folder of “HelloWorld” as “Hello.cpp“:

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=327 src=”http://www.codeproject.com/library/wxWidgets/image005.jpg” width=500>

  • Now add the file to the project by right clicking on the “Source Files” >> “Add” >> “Add Existing Item…” in the Solution Explorer:

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=419 src=”http://www.codeproject.com/library/wxWidgets/image006.jpg” width=411>

  • Select “Open”:

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=327 src=”http://www.codeproject.com/library/wxWidgets/image007.jpg” width=500>

  • Now, select the properties from the project menu:

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}”height=299 src=”http://www.codeproject.com/library/wxWidgets/image008.jpg” width=342>

  • Expand the “C/C++” node and select “General”. In the “Additional Include Directories” add the following line for the “Debug” configuration:
    “$(WXWIN)\include”;“$(WXWIN)\contrib\include”;“$(WXWIN)\lib\mswd”

    And for the “Release” configuration add the following line:

    “$(WXWIN)\include”;“$(WXWIN)\contrib\include”;“$(WXWIN)\lib\msw”

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=308 src=”http://www.codeproject.com/library/wxWidgets/image009.jpg” width=452>

  • In the Preprocessor tab, add the following line in the “Preprocessor Definitions” for the “Debug” configuration:
    WIN32;_DEBUG;_WINDOWS;__WINDOWS__;__WXMSW__;__WXDEBUG__;WXDEBUG=1;__WIN95__;__WIN32__;WINVER=0×0400;STRICT

    And for the “Release” configuration, add the following line:

    NDEBUG,WIN32,_WINDOWS,__WINDOWS__,__WXMSW__,__WIN95__,__WIN32__, WINVER=0×0400,STRICT

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=308 src=”http://www.codeproject.com/library/wxWidgets/image010.jpg” width=452>

  • In the “Code Generation” select the “Runtime Library” for “Debug” configuration as:
    Multi-threaded Debug DLL (/MDd)

    And for the “Releasse” configuration as:

    Multi-threaded DLL (/MD)

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=308 src=”http://www.codeproject.com/library/wxWidgets/image011.jpg” width=452>

  • Expand the “Linker” node and select “General”. In the “Additional Library Directories”, add the following line for “Debug” configuration:
    “$(WXWIN)\lib”;“$(WXWIN)\contrib\lib”;“$(WXWIN)\lib\vc_lib”

    And for the “Release” configuration, add the following line:

    “$(WXWIN)\lib”;“$(WXWIN)\contrib\lib”;“$(WXWIN)\lib\vc_lib”

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=308 src=”http://www.codeproject.com/library/wxWidgets/image012.jpg” width=451>

  • In the “Input” tab add the following line in the “Additional Dependencies” for the “Debug” configuration:
    wxmsw26d_core.lib wxbase26d.lib wxtiffd.lib wxjpegd.lib wxpngd.lib wxzlibd.lib wxregexd.lib wxexpatd.libwinmm.lib comctl32.lib rpcrt4.lib wsock32.lib oleacc.lib kernel32.lib user32.lib gdi32.lib winspool.libcomdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
  • And for the “Release” configuration, add the following line:
    wxmsw26_core.lib wxbase26.lib wxtiff.lib wxjpeg.lib wxpng.lib wxzlib.lib wxregex.lib wxexpat.lib winmm.lib comctl32.lib rpcrt4.lib wsock32.lib oleacc.lib odbc32.lib kernel32.lib user32.lib gdi32.libwinspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbccp32.lib

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=308 src=”http://www.codeproject.com/library/wxWidgets/image013.jpg” width=451>

  • Press the “OK” button to save these changes and build the solution from the build menu:

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=269 src=”http://www.codeproject.com/library/wxWidgets/image014.jpg” width=220>

  • Select the “Start” or “Start Without Debugging” from the “Debug” menu to execute the program:

    0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=238 src=”http://www.codeproject.com/library/wxWidgets/image015.jpg” width=236>

Congratulations!

You have successfully created your first “Hello World” program with wxWidgets:

0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}” height=340 src=”http://www.codeproject.com/library/wxWidgets/image016.jpg” width=450>

Visual C++ 2005 Express

Install the Visual C++ 2005 Express by following the instructions given in Manual Installation Instructions for Express Editions and then configure the platform SDK by following steps given in Using Visual C++ 2005 Express Beta 2 with the Microsoft Platform SDK. After this, you need to change the following:

[Editor comment: Line breaks used to avoid scrolling.]

%program Files%\Microsoft Visual Studio 8\VC\VCProjectDefaults\                                         corewin_express.vsprops

to set “_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE” as PreprocessorDefinitions.

An example corewin_express.vsprops file:

        

Then open the file $(WXWIN)\src\msw\main.cpp, search for the function &aposDllMain&apos and add the following lines:

#if _MSC_VER >= 1400 && _WINDLL#undef _WINDLL#endif

before the line:

#if defined(_WINDLL)

After you have configured your Visual Studio, the remaining steps are the same, simply follow the instructions given above for Visual Studio .NET, and open the wx.dsw file and compile the libraries for all the project configurations namely: Debug, Release, Debug DLL, Release DLL, Unicode Debug, Unicode Release, Unicode Debug DLL, Unicode Release DLL.

VC8 has also changed the way manifests are embedded in your executable. Your project will not be built if you include wx.manifest in your resource file. First, exclude the manifest from your resources by adding the define statement to your YourAppName.rc file:

#definewxUSE_NO_MANIFEST 1

Second, add these lines to your one of your source or header files to enable XP-Style common controls:

#if defined(__WXMSW__) && !defined(__WXWINCE__)#pragma comment(linker, “\”/manifestdependency:type=&aposwin32&apos     name=&aposMicrosoft.Windows.Common-Controls&apos version=&apos6.0.0.0&apos    processorArchitecture=&aposX86&apos publicKeyToken=&apos6595b64144ccf1df&apos\“”)#endif

Linux

Due to the large number of pictures and high downloading time, this section has been moved to a new article. Working with wxWidgets on Linux, can be found here.

Understanding the program

You have to include wxWidgets&apos header files, of course. This can be done on a file by file basis (such as #include “wx/window.h”) or using one global include (#include “wx/wx.h”). This is also useful on platforms that support precompiled headers such as all major compilers on the Windows platform:

// file name: hworld.cpp//// purpose: wxWidgets “Hello world”//// For compilers that support precompilation,// includes “wx/wx.h”.#include “wx/wxprec.h”#ifdef __BORLANDC__  #pragma hdrstop#endif#ifndef WX_PRECOMP #include “wx/wx.h”#endif

Practically, every app should define a new class derived from wxApp. By overriding wxApp&aposs OnInit(), the program can be initialized, e.g. by creating a new main window.

class MyApp: public wxApp { virtual bool OnInit(); };

The main window is created by deriving a class from wxFrame and giving it a menu and a status bar in its constructor. Also, any class that wishes to respond to any “event” (such as mouse clicks or messages from the menu or a button) must declare an event table using the macro below. Finally, a way to react to such events must be done in “handlers”. In our sample, we react to two menu items, one for “Quit” and one for displaying an “About” window. These handlers should not be virtual:

class MyFrame: public wxFrame{public:  MyFrame(const wxString& title, const wxPoint& pos,                                   const wxSize& size);  void OnQuit(wxCommandEvent& event);  void OnAbout(wxCommandEvent& event);private:  DECLARE_EVENT_TABLE()};

In order to be able to react to a menu command, it must be given a unique identifier such as a const or an enum.

enum{  ID_Quit = 1,  ID_About,};

We then proceed to actually implement an event table in which the events are routed to their respective handler functions in the class MyFrame. There are predefined macros for routing all the common events, ranging from the selection of a list box entry to a resize event when a user resizes a window on the screen. If -1 is given as the ID, the given handler will be invoked for any event of the specified type, so that you could just add one entry in the event table for all menu commands or all button commands etc. The origin of the event can still be distinguished in the event handler as the (only) parameter in an event handler is a reference to a wxEvent object, which holds information about the event (such as the ID of and a pointer to the class, which caused the event).

BEGIN_EVENT_TABLE(MyFrame, wxFrame)  EVT_MENU(ID_Quit, MyFrame::OnQuit)  EVT_MENU(ID_About, MyFrame::OnAbout)END_EVENT_TABLE()

As in all programs, there must be a “main” function. Under wxWidgets, main is implemented using this macro, which creates an application instance and starts the program:

IMPLEMENT_APP(MyApp)

As mentioned above, wxApp::OnInit() is called upon startup and should be used to initialize the program, maybe for showing a “splash screen” and creating the main window (or several). The frame should get a title bar text (”Hello World”) and a position and start-up size. One frame can also be declared as the top window. Returning TRUE indicates a successful initialization:

bool MyApp::OnInit(){  MyFrame *frame = new MyFrame( “Hello World”,                     wxPoint(50,50), wxSize(450,340) );  frame->Show( TRUE );  SetTopWindow( frame );  return TRUE;}

In the constructor of the main window (or later on) we create a menu with two menu items as well as a status bar to be shown at the bottom of the main window. Both have to be “announced” to the frame with the respective calls:

MyFrame::MyFrame(const wxString& title,           const wxPoint& pos, const wxSize& size) : wxFrame((wxFrame *)NULL, -1, title, pos, size){  wxMenu *menuFile = new wxMenu;  menuFile->Append( ID_About, “&About…” );  menuFile->AppendSeparator();  menuFile->Append( ID_Quit, “E&xit” );  wxMenuBar *menuBar = new wxMenuBar;  menuBar->Append( menuFile, “&File” );  SetMenuBar( menuBar );  CreateStatusBar();  SetStatusText( “Welcome to wxWidgets!” );}

Here are the actual event handlers. MyFrame::OnQuit() closes the main window by calling Close(). The parameter TRUE indicates that other Windows have no veto power, such as after asking “Do you really want to close?”. If there is no other main window left, the application will quit:

void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event)){  Close( TRUE );}

MyFrame::OnAbout() will display a small window i.e. a Message box with some text in it. In this case, a typical “About” window with information about the program:

void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event)){  wxMessageBox( “This is a wxWidgets&aposs Hello world sample”,     “About Hello World”, wxOK | wxICON_INFORMATION );}

How events are processed

An event table is placed in an implementation file to tell wxWindows how to map events to member functions. These member functions are not virtual functions, but they are all similar in form: they take a single wxEvent-derived argument, and have a void return type.

Here&aposs an example of an event table:

BEGIN_EVENT_TABLE(MyFrame, wxFrame)  EVT_MENU    (wxID_EXIT, MyFrame::OnExit)  EVT_MENU    (DO_TEST,   MyFrame::DoTest)  EVT_SIZE    (           MyFrame::OnSize)  EVT_BUTTON  (BUTTON1,   MyFrame::OnButton1)END_EVENT_TABLE()

The first two entries map menu commands to two different member functions. The EVT_SIZE macro doesn&apost need a window identifier, since normally you are only interested in the current window&aposs size events. (In fact, you could intercept a particular window&aposs size event by using EVT_CUSTOM(wxEVT_SIZE, ID, func).)

The EVT_BUTTON macro demonstrates that the originating event need not come from the window class implementing the event table - if the event source is a button within a panel within a frame, this will still work, because event tables are searched up through the hierarchy of Windows. In this case, the button&aposs event table will be searched, then the parent panel&aposs, and then the frame&aposs.

As mentioned before, the member functions that handle events don&apost have to be virtual. Indeed, the member functions should not be virtual as the event handler ignores that the functions are virtual, i.e. overriding a virtual member function in a derived class will not have any effect. These member functions take an event argument, and the class of the event differs according to the type of the event and the class of the originating window. For the size events, wxSizeEvent is used. For menu commands and most control commands (such as button presses), wxCommandEvent is used. When controls get more complicated, then specific event classes are used, such as wxTreeEvent for events from wxTreeCtrl windows.

The event table in the implementation file must have a DECLARE_EVENT_TABLE macro in the class definition. For example:

class MyFrame: public wxFrame {  DECLARE_DYNAMIC_CLASS(MyFrame)public:  …  void OnExit(wxCommandEvent& event);  void OnSize(wxSizeEvent& event);protected:  int       m_count;  …  DECLARE_EVENT_TABLE()};

When an event is received from the windowing system, wxWindows calls wxEvtHandler::ProcessEvent on the first event handler object belonging to the window generating the event.

It may be noted that wxWindows&apos event processing system implements something very close to the virtual methods in normal C++, i.e. it is possible to alter the behavior of a class by overriding its event handling functions. In many cases, this works even for changing the behavior of native controls. For example, it is possible to filter out a number of key events sent by the system to a native text control by overriding wxTextCtrl and defining a handler for key events using EVT_KEY_DOWN. This would indeed prevent any key events from being sent to the native control - which might not be what is desired. In this case, the event handler function has to call Skip() so as to indicate that the searchfor the event handler should continue.

To summarize, instead of explicitly calling the base class version as you would do with C++ virtual functions (i.e. wxTextCtrl::OnChar()), you should instead call Skip.

In practice, this would look like the following if the derived text control only accepts &aposa&apos to &aposz&apos and &aposA&apos to &aposZ&apos:

void MyTextCtrl::OnChar(wxKeyEvent& event){    if ( isalpha( event.KeyCode() ) )    {       // key code is within legal range. we call event.Skip() so the       // event can be processed either in the base wxWindows class       // or the native control.       event.Skip();    }    else    {       // illegal key hit. we don&apost call event.Skip() so the       // event is not processed anywhere else.       wxBell();    }}

The normal order of event table searching by ProcessEvent is as follows:

  1. If the object is disabled (via a call to wxEvtHandler::SetEvtHandlerEnabled) the function skips to step (6).
  2. If the object is a wxWindow, the ProcessEvent is recursively called on the window&aposs wxValidator. If this returns TRUE, the function exits.
  3. SearchEventTable is called for this event handler. If this fails, the base class table is tried, and so on, until no more tables exist or an appropriate function is found, in which case the function exits.
  4. The search is applied down the entire chain of event handlers (usually the chain has a length of one). If this succeeds, the function exits.
  5. If the object is a wxWindow and the event is a wxCommandEvent, the ProcessEvent is recursively applied to the parent window&aposs event handler. If this returns TRUE, the function exits.
  6. Finally, ProcessEvent is called on the wxApp object.

Pay close attention to step 5: People often overlook or get confused by this powerful feature of wxWindows event processingsystem. To put it a different way, events derived either directly or indirectly from wxCommandEvent will travel up the containment hierarchy from child to parent until an event handler is found that doesn&apost call event.Skip(). Events not derived from wxCommandEvent are sent to the window where they occurred and are then stopped.

Finally, there is another additional complication (which, in fact, simplifies the life of wxWindows programmers significantly): when propagating the command events upwards to the parent window, the event propagation stops when it reaches the parent dialog, if any. This means that you don&apost risk to get unexpected events from the dialog controls (which might be left unprocessed by the dialog itself because it doesn&apost care about them) when a modal dialog is popped up. The events do propagate beyond the frames, however. The rationale for this choice is that there are only a few frames in a typical application and their parent-child relation are well understood by the programmer, while it may be very difficult, if not impossible, to track down all the dialogs which may be popped up in a complex program (remember that some are created automatically by wxWindows). If you need to specify a different behavior for some reason, you can use SetExtraStyle(wxWS_EX_BLOCK_EVENTS) explicitly to prevent the events from being propagated beyond the given window or unset this flag for the dialogs which have it by default.

Typically events that deal with a window as a window (size, motion, paint, mouse, keyboard, etc.) are sent only to the window. Events that have a higher level of meaning and/or are generated by the window itself, (button click, menu select, tree expand, etc.) are command events and are sent up to the parent to see if it is interested in the event.

Note that your application may wish to override ProcessEvent to redirect the processing of events. This is done in the document/view framework, for example, to allow event handlers to be defined in the document or view. To test for command events (which are probably the only events you wish to redirect), you may use wxEvent::IsCommandEvent for efficiency, instead of using the slower run-time type system.

As mentioned above, only the command events are recursively applied to the parent&aposs event handler. As this often causes confusion to the users, here is a list of the system events that are not sent to the parent&aposs event handler:

wxEvent The event base class.

许德风的赠言和凌斌的最爱

星期一, 十二月 4th, 2006

<![CDATA[

基于p2p的sip电话系统

星期一, 十二月 4th, 2006

<![CDATA[

文章来源: http://blog.csdn.net/lengxingfei/archive/2006/01/18/583227.aspx

摘要
p2p系统天生拥有高扩展性、健壮性和高容错性的特点,这些特点得益于系统没有中央服务器并且网络是自己管理的这种结构。本系统实现了在

p2p系统中较长的延迟的代价下定位感兴趣的资源。internet 话可以被看作一个p2p架构的应用,它在一部分和另外一部分定位和通讯时在p2p

这种自组网上实现。我们的目的是构建一个基于SIP信令的纯p2p架构的ip电话系统。 我们的p2psip架构支持基本的用户注册和呼叫建立,也提

供高级的服务 如:发送离线消息、声音/图像邮件 多方通话。同时我们提供一个可以实际操作的穿越防火墙NAT和安全性的p2psip。
(关键字 系统设计 点对点 高可靠性 扩展性 internet电话 SIP)

Peer-to-Peer Internet Telephony using SIP

原作者:Kundan Singh and Henning Schulzrinne
Department of Computer Science, Columbia University
fkns10,hgsg@cs.columbia.edu

译者 汪亮宇 wlywly@sina.com