下面让我们来分析以下VCL for PHP的基本结构,李维在作 Demo的时候最喜欢拿出来炫的就是Google Map VCL,你们能够想像得出来这个组件一共有多少行代码吗?
不到100行,是不是吓到了?你有可能编写很少的代码,就可以开发一共非常漂亮的组件,并且开始你自己的软件创业之路。
下面让我们来看一下这个组件的源代码:
<?php
//Includes
require_once("vcl/vcl.inc.php");
use_unit("controls.inc.php");
//Class definition
class GoogleMap extends Control
{
function __construct($aowner = null)
{
parent::__construct($aowner);
}
private $_mapskey="ABQIAAAAQlQ8ZvigZnDc1z7MTEuUQxTJO8fVsnY3pyCJC531oZiosu_8phSnTlxi08R1_58Gfdyd9NUJdyES5w";
function getMapsKey() { return $this->_mapskey; }
function setMapsKey($value) { $this->_mapskey=$value; }
function defaultMapsKey() { return "ABQIAAAAQlQ8ZvigZnDc1z7MTEuUQxTJO8fVsnY3pyCJC531oZiosu_8phSnTlxi08R1_58Gfdyd9NUJdyES5w"; }
private $_address="Scotts Valley, CA";
function getAddress() { return $this->_address; }
function setAddress($value) { $this->_address=$value; }
function defaultAddress() { return "Scotts Valley, CA"; }
function dumpHeaderCode()
{
?>
<script src="http://maps.google.com/maps?file=api&v=2&key= <?php echo $this->MapsKey; ?>"
type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
function <?php echo $this->Name; ?>load()
{
if (GBrowserIsCompatible())
{
var map = new GMap2(document.getElementById("<?php echo $this->Name; ?>_div"));
map.addControl(new GLargeMapControl());
map.addControl(new GScaleControl());
map.addControl(new GMapTypeControl());
var geocoder = new GClientGeocoder();
var address="<?php echo $this->Address; ?>";
geocoder.getLatLng (address,
function(point)
{
if (!point)
{
alert(address + " not found");
}
else
{
map.setCenter(point, 13);
var marker = new GMarker(point);
map.addOverlay(marker);
marker.openInfoWindowHtml(address);
}
}
);
}
}
//]]>
</script>
<?php
}
function dumpContents()
{
echo "<div id="".$this->Name."_div" style="width: ".$this->Width."px; height: ".$this->Height."px"></div>";
?>
<script type="text/javascript">
<?php echo $this->Name; ?>load();
</script>
<?php
}
}
?>
连空行都算上一共84行。我就不讲解这段代码了,我想不管你是什么语言的程序员, Delphi、PHP、Java 、C++、C# 、JavaScript等等等等,你应该都能够读懂上面的几十行代码。
看看,这是多么容易的一件事啊,你也能的。
如果你希望能够进入这个行业,那么我给大家指几个方向,供大家参考。在早期,这个领域还是一片空白的时候,大家可以试着从这些方向下手。
第一、 使用现有组件进行一些扩展,完成一些更加具体的功能:
下面这个例子是LabeledEdit组件,将一个 Label和一个Edit组合起来,完成一个完整的功能。
class SubLabel extends Persistent
{
protected $_caption = "";
function assignTo($dest)
{
$dest->_caption=$this->_caption;
}
/**
* Specifies the caption used in the label
*
* @return string
*/
protected function readCaption() { return $this->_caption; }
protected function writeCaption($value) { $this->_caption=$value; }
function defaultCaption() { return ""; }
// publish properties
function getCaption() { return $this->readCaption(); }
function setCaption($value) { $this->writeCaption($value); }
}
class CustomLabeledEdit extends CustomTextField
{
protected $_lblname = "";
protected $_edtlabel=null;
protected $_lblspacing = 3;
protected $_lblposition = lpAbove;
protected $_text = "";
protected function CalculateEditorRect()
{
switch ($this->_lblposition)
{
case lpBelow:
$y = 0;
break;
default: // lpAbove:
$y = 14 + $this->_lblspacing;
break;
}
return array(0, $y, $this->Width, $this->Height – 14 – $this->_lblspacing);
}
protected function dumpExtraControlCode()
{
$eh = $this->Height – 14 – $this->_lblspacing;
switch ($this->_lblposition)
{
case lpBelow:
$y = $eh;
break;
default: // lpAbove:
$y = 0;
break;
}
$this->_lblname = $this->Name . "_Lbl";
echo " var $this->_lblname = new qx.ui.basic.Atom("" . $this->_edtlabel->Caption . "");n"
. " $this->_lblname.setLeft(0);n"
. " $this->_lblname.setTop($y);n"
. " $this->_lblname.setWidth($this->Width);n"
. " $this->_lblname.setHorizontalChildrenAlign("left");n";
if (($this->Visible) || (($this->ControlState & csDesigning)==csDesigning))
{ $visible="true"; }
else { $visible="false"; };
echo " $this->_lblname.setVisibility($visible);n"
. " inline_div.add($this->_lblname);n";
}
function __construct($aowner = null)
{
//Calls inherited constructor
parent::__construct($aowner);
$this->_edtlabel = new SubLabel();
$this->Width = 121;
$this->Height = 34;
}
function setName($value)
{
$oldname=$this->_name;
parent::setName($value);
//Sets the caption if not already changed
if ($this->_edtlabel->Caption == $oldname)
{
$this->_edtlabel->Caption = $this->Name;
}
}
/**
* Use EditLabel to work with the label that is associated with this
* labeled edit control. Use this label�s properties to specify the
* caption that appears on the label.
*/
protected function readEditLabel() { return $this->_edtlabel; }
protected function writeEditLabel($value) { if (is_object($value)) $this->_edtlabel=$value; }
/**
* Specifies the position of the label relative to the edit control.
*
* @return enum (lpAbove, lpBelow)
*/
protected function readLabelPosition() { return $this->_lblposition; }
protected function writeLabelPosition($value) { $this->_lblposition=$value; }
function defaultLabelPosition() { return lpAbove; }
/**
* Specifies the distance, in pixels, between the label and the edit region.
*
* @return integer
*/
protected function readLabelSpacing() { return $this->_lblspacing; }
protected function writeLabelSpacing($value) { $this->_lblspacing=$value; }
function defaultLabelSpacing() { return 3; }
}
class LabeledEdit extends CustomLabeledEdit
{
//Publish common properties
function getAlign() { return $this->readAlign(); }
function setAlign($value) { $this->writeAlign($value); }
//function getFont() { return $this->readFont(); }
//function setFont($value) { $this->writeFont($value); }
function getColor() { return $this->readColor(); }
function setColor($value) { $this->writeColor($value); }
function getEnabled() { return $this->readEnabled(); }
function setEnabled($value) { $this->writeEnabled($value); }
function getParentColor() { return $this->readParentColor(); }
function setParentColor($value) { $this->writeParentColor($value); }
function getParentFont() { return $this->readParentFont(); }
function setParentFont($value) { $this->writeParentFont($value); }
function getParentShowHint() { return $this->readParentShowHint(); }
function setParentShowHint($value) { $this->writeParentShowHint($value); }
function getPopupMenu() { return $this->readPopupMenu(); }
function setPopupMenu($value) { $this->writePopupMenu($value); }
function getShowHint() { return $this->readShowHint(); }
function setShowHint($value) { $this->writeShowHint($value); }
function getVisible() { return $this->readVisible(); }
function setVisible($value) { $this->writeVisible($value); }
//Publish Edit control properties
function getBorderStyle() { return $this->readBorderStyle(); }
function setBorderStyle($value) { $this->writeBorderStyle($value); }
function getCharCase() { return $this->readCharCase(); }
function setCharCase($value) { $this->writeCharCase($value); }
function getDataField() { return $this->readDataField(); }
function setDataField($value) { $this->writeDataField($value); }
function getDataSource() { return $this->readDataSource(); }
function setDataSource($value) { $this->writeDataSource($value); }
function getIsPassword() { return $this->readIsPassword(); }
function setIsPassword($value) { $this->writeIsPassword($value); }
function getMaxLength() { return $this->readMaxLength(); }
function setMaxLength($value) { $this->writeMaxLength($value); }
function getReadOnly() { return $this->readReadOnly(); }
function setReadOnly($value) { $this->writeReadOnly($value); }
function getText() { return $this->readText(); }
function setText($value) { $this->writeText($value); }
// publish Common Events
function getjsOnActivate() { return $this->readjsOnActivate(); }
function setjsOnActivate($value){ $this->writejsOnActivate($value); }
function getjsOnDeActivate() { return $this->readjsOnDeActivate(); }
function setjsOnDeActivate($value) { $this->writejsOnDeActivate($value); }
function getjsOnChange() { return $this->readjsOnChange(); }
function setjsOnChange($value) { $this->writejsOnChange($value); }
function getjsOnBlur() { return $this->readjsOnBlur(); }
function setjsOnBlur($value) { $this->writejsOnBlur($value); }
function getjsOnClick() { return $this->readjsOnClick(); }
function setjsOnClick($value) { $this->writejsOnClick($value); }
function getjsOnContextMenu() { return $this->readjsOnContextMenu(); }
function setjsOnContextMenu($value) { $this->writejsOnContextMenu($value); }
function getjsOnDblClick() { return $this->readjsOnDblClick(); }
function setjsOnDblClick($value){ $this->writejsOnDblClick($value); }
function getjsOnFocus() { return $this->readjsOnFocus(); }
function setjsOnFocus($value) { $this->writejsOnFocus($value); }
function getjsOnKeyDown() { return $this->readjsOnKeyDown(); }
function setjsOnKeyDown($value) { $this->writejsOnKeyDown($value); }
function getjsOnKeyPress() { return $this->readjsOnKeyPress(); }
function setjsOnKeyPress($value){ $this->writejsOnKeyPress($value); }
function getjsOnKeyUp() { return $this->readjsOnKeyUp(); }
function setjsOnKeyUp($value) { $this->writejsOnKeyUp($value); }
function getjsOnMouseDown() { return $this->readjsOnMouseDown(); }
function setjsOnMouseDown($value){ $this->writejsOnMouseDown($value); }
function getjsOnMouseUp() { return $this->readjsOnMouseUp(); }
function setjsOnMouseUp($value) { $this->writejsOnMouseUp($value); }
function getjsOnMouseMove() { return $this->readjsOnMouseMove(); }
function setjsOnMouseMove($value) { $this->writejsOnMouseMove($value); }
function getjsOnMouseOut() { return $this->readjsOnMouseOut(); }
function setjsOnMouseOut($value) { $this->writejsOnMouseOut($value); }
function getjsOnMouseOver() { return $this->readjsOnMouseOver(); }
function setjsOnMouseOver($value) { $this->writejsOnMouseOver($value); }
// publish new properties
function getEditLabel() { return $this->readEditLabel(); }
function setEditLabel($value) { $this->writeEditLabel($value); }
function getLabelPosition() { return $this->readLabelPosition(); }
function setLabelPosition($value) { $this->writeLabelPosition($value); }
function getLabelSpacing() { return $this->readLabelSpacing(); }
function setLabelSpacing($value) { $this->writeLabelSpacing($value); }
// publish events
function getOnClick() { return $this->readOnClick(); }
function setOnClick($value) { $this->writeOnClick($value); }
}
第二、 结合JavaScript来做一些页面特效,这需要JavaScript 比较熟悉的人来完成。我向很多JavaScript程序员手里应该已经积攒了不少非常棒的代码,比如各种按钮、菜单等等。
第三、 结合一些提供特定服务的网站,例如Google Map,或者是图片交流方面的或者是提供一些特定信息的 WebServices网站,例如股票、金融、餐饮服务、新闻、天气、出行信息等内容,作一些能够提供特定信息的组件。这些组件可以从网站得到一些收入。
第四、 将现在比较流行的完整的开源代码拆开,封装成组件包。
第五、 Grid、Report、 Chart这三类组件在Delphi VCL里面是种类最丰富的,所以如果能够在这方面及早下手,肯定效果不错。
第六、 调用PHP基础函数,封装一些基础功能也是一个不错的选择,比如 phpinfo()就完全可以进行些方面的封装,FTP和各种文件操作封装的余地也很大。
第七、 编写一些特定的数据库连接和操作的组件应该有不错的应用前景。
第八、 结合Delphi或者是C++ 来编写一些PHP扩展,然后将去封装到VCL中,可以完成一些更强劲的的功能,也更容易让客户认同这些组件的价值。
第九、 编写完整的网站决绝方案,比如门户网站、BBS、商务网站等等。
我在这里只是启一个头儿,相信大家能够想出更多更有创意的点子来。
让我们一起来迎接新控件时代的到来吧!
Both comments and pings are currently closed.