2011年11月13日星期日

CSS绝对定位的一些解释






absolute定位实验







absoluteA
absoluteB
floatC
floatD






效果如下:
css定位

可以看到:

  1. 采用absolute定位时,left,right,top,bottom分别是定位元素与父元素 左-左 右-右 上-上 下-下 边的距离

  2. float元素的父元素为非绝对定位元素时,float不会撑大父元素的高度。当float元素的父元素为绝对定位元素时,float元素会撑大父元素的宽度和高度

  3. 当absolute定位的元素(比如元素M)内容改变时,定位属性不会改变。比如指定M的bottom为10px,当动态向M添加了一些内容导致M高度增大时,M将向上面伸展,底框与父元素始终保持10px

2011年11月10日星期四

C++ 以POST方式向网页提交数据

示例代码如下:


#include
#include
#include //定义了MFC CInternetSession类等

bool PostHttpPage(const std::string& hostName, const std::string& pathName, const std::string& postData)
{
using namespace std;

CInternetSession session("your app agent name");

try
{
INTERNET_PORT nPort = 80;
DWORD dwRet = 0;

CHttpConnection* pServer = session.GetHttpConnection(hostName.c_str(), nPort);
CHttpFile* pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST, pathName.c_str());

CString strHeaders = "Content-Type: application/x-www-form-urlencoded"; // 请求头

//开始发送请求

pFile->SendRequest(strHeaders,(LPVOID)postData.c_str(),postData.size());
pFile->QueryInfoStatusCode(dwRet);


if (dwRet == HTTP_STATUS_OK)
{
CString result, newline;

while(pFile->ReadString(newline))
{//循环读取每行内容
result += newline+"\r\n";
}

std::cout< }
else
{
return false;
}
delete pFile;
delete pServer;

}
catch (CInternetException* pEx)
{
//catch errors from WinInet
TCHAR pszError[200];
pEx->GetErrorMessage(pszError, 200);

std::cout< return false;
}
session.Close();

return true;
}

int main(void)
{
//向http://current.sinaapp.com/post.php发送数据
PostHttpPage("current.sinaapp.com","post.php","name=rain&age=12");
}

C++程序读取和保存配置信息

虽然MSDN推荐使用注册表代替ini文件来保存程序配置和运行信息,但一般的小程序还是用ini文件来保存信息比较方便一些。

微软提供了GetPrivateProfile和WritePrivateProfile开头的一组函数来读取和保存ini文件。
比如对于名称为scan.ini的配置文件

[lastest]
year =2011
month =11
day =8
hour =19
minute =0
second =56


读取时间信息的代码如下

CTime get_last_time()
{
int year,month,day,hour,minute,second;

year = GetPrivateProfileInt("lastest","year",1970,"./scan.ini");
month = GetPrivateProfileInt("lastest","month",1,"./scan.ini");
day = GetPrivateProfileInt("lastest","day",2,"./scan.ini");
hour = GetPrivateProfileInt("lastest","hour",0,"./scan.ini");
minute = GetPrivateProfileInt("lastest","minute",0,"./scan.ini");
second = GetPrivateProfileInt("lastest","second",0,"./scan.ini");

return CTime(year,month,day,hour,minute,second);
}


写入时间信息的代码如下

bool set_latest_time(const CTime &latest)
{
BOOL year,month,day,hour,minute,second;

year = WritePrivateProfileString("lastest","year",latest.Format("%Y"),"./scan.ini");
month = WritePrivateProfileString("lastest","month",latest.Format("%#m"),"./scan.ini");
day = WritePrivateProfileString("lastest","day",latest.Format("%#d"),"./scan.ini");
hour = WritePrivateProfileString("lastest","hour",latest.Format("%#H"),"./scan.ini");
minute = WritePrivateProfileString("lastest","minute",latest.Format("%#M"),"./scan.ini");
second = WritePrivateProfileString("lastest","second",latest.Format("%#S"),"./scan.ini");

return year && month && day && hour && minute && second;
}

2011年11月9日星期三

CPP程序监视plot文件夹并以post方式上传数据


//#include // MFC 核心和标准组件

#include
#include
#include
#include
#include

void display_post_result(std::string result)
{
std::cout<
std::ofstream fout("log-info.txt",std::ios_base::out|std::ios_base::app);
if(!fout.is_open())
{
std::cout<<"打开或创建文件log-info.txt失败!";
return;
}
CTime now = CTime::GetCurrentTime();

fout<}

bool PostHttpPage(const std::string& hostName, const std::string& pathName, const std::string& postData)
{
using namespace std;

CInternetSession session("Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2) Gecko/20100115 Firefox/3.6");

try
{
INTERNET_PORT nPort = 80;
DWORD dwRet = 0;

CHttpConnection* pServer = session.GetHttpConnection(hostName.c_str(), nPort);
CHttpFile* pFile = pServer->OpenRequest(CHttpConnection::HTTP_VERB_POST, pathName.c_str());

CString strHeaders = "Content-Type: application/x-www-form-urlencoded"; // 请求头

display_post_result("posting data...");

pFile->SendRequest(strHeaders,(LPVOID)postData.c_str(),postData.size());
pFile->QueryInfoStatusCode(dwRet);


if (dwRet == HTTP_STATUS_OK)
{
CString result, newline;

while(pFile->ReadString(newline))
{
result += newline+"\r\n";
}

display_post_result(("back:"+result).GetBuffer());
}
else
{
display_post_result("post 失败!");
return false;
}
delete pFile;
delete pServer;

}
catch (CInternetException* pEx)
{
//catch errors from WinInet
TCHAR pszError[200];
pEx->GetErrorMessage(pszError, 200);

display_post_result(pszError);
return false;
}
session.Close();

return true;
}

bool deal_plot_file(std::string orgine_name, std::string &result)
{
std::ifstream fin(orgine_name.c_str());
if(!fin.is_open())
{
display_post_result("打开文件"+orgine_name+"失败!");
return false;
}

display_post_result("dealing "+orgine_name+"...");

result = "";
std::string linestr, number;

std::istringstream stringin;
while(std::getline(fin,linestr))
{
stringin.clear();
stringin.str(linestr);
if(stringin>>number)
{
if(number.size() == 5)
{
result += number;
//读取并丢弃经纬度高度和站点级别信息
stringin>>number>>number>>number>>number;

while(stringin>>number)
{
result += ' ' + number;
}
//result += "\r\n";

}
else
{
result += linestr + "\r\n";
}
}
}

return true;
}

CTime get_last_time()
{
int year,month,day,hour,minute,second;

year = GetPrivateProfileInt("lastest","year",1970,"./scan.ini");
month = GetPrivateProfileInt("lastest","month",1,"./scan.ini");
day = GetPrivateProfileInt("lastest","day",2,"./scan.ini");
hour = GetPrivateProfileInt("lastest","hour",0,"./scan.ini");
minute = GetPrivateProfileInt("lastest","minute",0,"./scan.ini");
second = GetPrivateProfileInt("lastest","second",0,"./scan.ini");

return CTime(year,month,day,hour,minute,second);
}

bool set_latest_time(const CTime &latest)
{
BOOL year,month,day,hour,minute,second;

year = WritePrivateProfileString("lastest","year",latest.Format("%Y"),"./scan.ini");
month = WritePrivateProfileString("lastest","month",latest.Format("%#m"),"./scan.ini");
day = WritePrivateProfileString("lastest","day",latest.Format("%#d"),"./scan.ini");
hour = WritePrivateProfileString("lastest","hour",latest.Format("%#H"),"./scan.ini");
minute = WritePrivateProfileString("lastest","minute",latest.Format("%#M"),"./scan.ini");
second = WritePrivateProfileString("lastest","second",latest.Format("%#S"),"./scan.ini");

return year && month && day && hour && minute && second;
}

std::string get_plot_dir()
{
char dir_buf[1024] ;
DWORD result = GetPrivateProfileString("path","plotdir","Z:/surface/plot/",dir_buf,1000,"./scan.ini");

return dir_buf;
}

bool scan_plot_dir()
{
CTime last_time = get_last_time();

CFileFind finder;

std::string dir = get_plot_dir();
if('\\' != dir[dir.size()-1 ] && '/' != dir[dir.size()-1 ] )
{
dir += '/';
}
BOOL bWorking = finder.FindFile( (dir+ "*.000").c_str() );

CTime lastest(1), ftime;
std::string result;
//

while (bWorking)
{
bWorking = finder.FindNextFile();

if(finder.GetLastWriteTime(ftime)
&& ftime > last_time
&& deal_plot_file(finder.GetFilePath().GetBuffer(), result)
)
{
bool is_post_success =
PostHttpPage("current.sinaapp.com","update-mysql-from-post.php","app-content="+result);

if(!is_post_success)
{//有一次post不成功就返回本次dir scan
display_post_result("post maybe failure...");
return false;
}

lastest = ftime > lastest ? ftime : lastest;

display_post_result("wait 2 minute...");
Sleep(2*1000*60);//post成功时等待2分钟
display_post_result("continue next file find...");
}
}

if(CTime(1) != lastest )
{
return set_latest_time(lastest);
}

return false;
}

int main(void)
{
std::cout<<"version 1.1 2011-11-09\n"
<<"-------------------------------------\n";
while(true)
{
scan_plot_dir();

display_post_result("wait 5 minute...");
Sleep(5*1000*60);//每次dir scan完成时等待5分钟
display_post_result("continue next plot dir scan...");
}

}

C++ 获取文件修改时间等信息

可以利用MFC中的文件查找类CFileFind来获取文件或文件夹的修改时间访问时间等信息


#include // MFC 核心和标准组件
#include
#include

void get_file_info(const std::string &orgine_name)
{
CFileFind finder;
BOOL bWorking = finder.FindFile(orgine_name.c_str());

while (bWorking)
{
bWorking = finder.FindNextFile();
CTime ftime;

std::cout<<"\nGetFileName: "< <<"\nGetFilePath: "< <<"\nGetFileTitle: "< <<"\nGetFileURL: "< <<"\nIsDirectory: "<

finder.GetCreationTime(ftime);
std::cout<<"\nGetCreationTime:"<
finder.GetLastWriteTime(ftime);
std::cout<<"\nGetLastWriteTime: "<
finder.GetLastAccessTime(ftime);
std::cout<<"\nGetLastAccessTime:"<
std::cout< }

}

int main(void)
{
get_file_info("Z:/surface/plot");
get_file_info("Z:/surface/plot/11110911.000");
}


运行上面代码输出如下:

GetFileName: plot
GetFilePath: Z:\surface\plot
GetFileTitle: plot
GetFileURL: file://Z:\surface\plot
IsDirectory: 1
GetCreationTime:[2011-05-22 10:10:45]
GetLastWriteTime: [2011-11-09 11:30:55]
GetLastAccessTime:[2011-11-09 12:30:57]

GetFileName: 11110911.000
GetFilePath: Z:\surface\plot\11110911.000
GetFileTitle: 11110911
GetFileURL: file://Z:\surface\plot\11110911.000
IsDirectory: 0
GetCreationTime:[2011-11-09 11:30:55]
GetLastWriteTime: [2011-11-09 13:00:54]
GetLastAccessTime:[2011-11-09 13:00:54]
请按任意键继续. . .

2011年11月7日星期一

jQuery 1.7 事件绑定函数

jQuery 1.7 前几天发布了,新增了两个事件处理函数 .on().off() 分别用来绑定和解除事件。这两个函数可以取代之前版本中所有的事件处理函数。
现在事件绑定和解除更简单了,下面是新旧版本事件处理代码的对比:

$('a').bind('click', myHandler);
$('a').on('click', myHandler);

$('form').bind('submit', { val: 42 }, fn);
$('form').on('submit', { val: 42 }, fn);

$(window).unbind('scroll.myPlugin');
$(window).off('scroll.myPlugin');

$('.comment').delegate('a.add', 'click', addNew);
$('.comment').on('click', 'a.add', addNew);

$('.dialog').undelegate('a', 'click.myDlg');
$('.dialog').off('click.myDlg', 'a');

$('a').live('click', fn);
$(document).on('click', 'a', fn);

$('a').die('click');
$(document).off('click', 'a');


另外想说一下jQuery中的事件对象(Event Object)

jQuery的事件系统规范化了事件对象(根据W3C标准)。jQuery保证事件对象被传递给事件处理程序。大部分的属性从原来的事件中复制和规范化给新的事件对象。

jQuery保证下列属性是事件对象的成员,尽管它们中的一些值可能是undefined(依赖于具体的事件):

altKey, attrChange, attrName, bubbles, button, cancelable,
charCode, clientX, clientY, ctrlKey, currentTarget, data, detail,
eventPhase, fromElement, handler, keyCode, layerX, layerY,
metaKey, newValue, offsetX, offsetY, originalTarget,
pageX, pageY, prevValue, relatedNode, relatedTarget,
screenX, screenY, shiftKey, srcElement, target,
toElement, view, wheelDelta, which


为了跨浏览器兼容,jQuery 对下列属性进行了规范化:

target
relatedTarget
pageX
pageY
which
metaKey


特别注意,并不是所有原始事件的属性都被复制给jQuery的事件对象。这时可以用 event.originalEvent 来获取原始事件对象。比如在HTML5文件拖放操作时需要用到drop事件的dataTransfer属性,可以像下面这样做:

$('body').on('drop',function(e){
var file = e.originalEvent.dataTransfer.files[0];//获取一组拖放文件中的第一个文件

reader = new FileReader();//创建FileReader对象来读取文件内容
reader.onload = function(e){//读取完成时将内容显示于body中
$('body').text(e.target.result);
};
reader.readAsText(file,'utf-8');//开始读取文件

//相当于同时调用e.stopPropagation() 和 e.preventDefault()
return false;//阻止事件冒泡和浏览器的默认行为
});

2011年11月6日星期日

Google Maps 显示地面天气实况

一、用到的技术
1.Google Maps API
2.jQuery & jQuery UI &jqPlot
3.canvas 绘制风速及UI
4.mysql 站点信息表 & 站点-时间-观测数据 表 &其他信息表(站点和数据最近更新时间、最新数据时间)
5.php返回json形式站点信息并在客户端持久存储
6.Ajax轮询请求获取最新数据
7.GeoLocation获取用户地理位置并定位
8.鼠标悬停站点时显示基本信息,点击detail时Ajax获取本站点最详尽信息
9.Javascript解析数据代码为天气信息,计算湿度和本站气压等
10.统计某一段时间数据(单站数据或多站对比)
11.C++ 自动监测处理(去掉站点经纬度高度等信息)地面图文件并post数据 & 网页手动上传文件更新(提供基本上传和拖动上传方式)

地面填图文件示例:11110620.000

二、代码实现
1.创建站点数据表

CREATE TABLE IF NOT EXISTS station(
id INT UNSIGNED NOT NULL UNIQUE PRIMARY KEY ,
lon DOUBLE NOT NULL ,
lat DOUBLE NOT NULL ,
height DOUBLE NOT NULL ,
LEVEL TINYINT UNSIGNED NOT NULL ,
name VARCHAR( 50 )
);

2.创建地面观测数据表

CREATE TABLE IF NOT EXISTS surface(
recordId int(10) unsigned NOT NULL AUTO_INCREMENT,
stationId int(10) unsigned NOT NULL,
recordTime datetime NOT NULL,
totalCloudAmount smallint(5) unsigned NOT NULL,
windDirection smallint(5) unsigned NOT NULL,
windSpeed smallint(5) unsigned NOT NULL,
seaLevelPressure smallint(5) unsigned NOT NULL,
press3hour smallint(6) NOT NULL,
pastWeather1 smallint(5) unsigned NOT NULL,
pastWeather2 smallint(5) unsigned NOT NULL,
hour6precipitation double NOT NULL,
lowCloudAmount smallint(5) unsigned NOT NULL,
lowCloudShape smallint(5) unsigned NOT NULL,
lowCloudHight smallint(5) unsigned NOT NULL,
dewpoint double NOT NULL,
visibility double unsigned NOT NULL,
presentWeather smallint(5) unsigned NOT NULL,
temperature double NOT NULL,
middleCloudShape smallint(5) unsigned NOT NULL,
highCloudShape smallint(5) unsigned NOT NULL,
transformT24 smallint(6) NOT NULL,
transformPress24 smallint(6) NOT NULL,
PRIMARY KEY (recordId),
UNIQUE KEY stationId (stationId,recordTime)
) ENGINE=MyISAM DEFAULT CHARSET=utf8


每个月数据约100万行,可每个月建立一张表

CREATE TABLE IF NOT EXISTS `surface201111` LIKE surface;


3.插入数据到station表

function update_stations($content){
preg_match_all('/^(\d{5})\s+(-?\d+\.\d+)\s+(-?\d+\.\d+)\s+(-?\d+)\s+(\d+)/m',$content,$matchs,PREG_SET_ORDER);

//print_r($matchs);

$sql = 'INSERT IGNORE INTO station (id, lon, lat, height, level) VALUES ';

for($i = 0; $i < count($matchs); $i++){
$sql .= '( ';

for($j = 1; $j < 5; $j++){
$sql .= $matchs[$i][$j].",";
}
$sql .= $matchs[$i][5] .' )';
if($i < count($matchs) - 1)
{
$sql .= ',';
}
}
//echo $sql;

$mydb = new DB(SAE_MYSQL_HOST_M);
return $mydb -> doSql($sql);
}

4.插入数据到surface表

function getSurfacePatten(){
$patten = '/^(\d{5})(?:\s+-?\d+\.\d+){2}(?:\s+-?\d+\s+\d+)';

$patten .= '\s+(\d+)';
$patten .= '\s+(\d+)';
$patten .= '\s+(\d+)';
$patten .= '\s+(\d+)';
$patten .= '\s+(-?\d+)';
$patten .= '\s+(\d+)';
$patten .= '\s+(\d+)';

$patten .= '\s+(\d*\.\d+|\d+)';

$patten .= '\s+(\d+)';
$patten .= '\s+(\d+)';
$patten .= '\s+(\d+)';

$patten .= '\s+(-?\d*\.\d+|\d+)';
$patten .= '\s+(\d*\.\d+|\d+)';
$patten .= '\s+(\d+)';
$patten .= '\s+(-?\d*\.\d+|\d+)';

$patten .= '\s+(\d+)';
$patten .= '\s+(\d+)';

$patten .= '\s+\d+';
$patten .= '\s+\d+';

$patten .= '\s+(-?\d+)';
$patten .= '\s+(-?\d+)';

$patten .= '/m';

return $patten;
}

function update_surface($content){

preg_match('/(\d+)\s+(0?\d+)\s+(0?\d+)\s+(0?\d+)\s+(\d+)\s*$/m',$content,$matchs);

$year = $matchs[1] > '50' ? '19'.$matchs[1] : '20'.$matchs[1];
$timestr = $year.$matchs[2].$matchs[3].$matchs[4].'0000';

$patten = getSurfacePatten();

preg_match_all($patten,$content,$matchs,PREG_SET_ORDER);

//print_r($matchs);

$sql = 'INSERT IGNORE INTO surface (';
$sql .= 'recordTime,stationID,';
$sql .= 'totalCloudAmount,windDirection,windSpeed,seaLevelPressure,press3hour,pastWeather1,pastWeather2,';
$sql .= 'hour6precipitation,lowCloudAmount,lowCloudShape,lowCloudHight,';
$sql .= 'dewpoint,visibility,presentWeather,temperature,';
$sql .= 'middleCloudShape,highCloudShape,';
$sql .= 'transformT24,transformPress24';
$sql .= ' ) VALUES ';

$mydb = new DB(SAE_MYSQL_HOST_M);

for($i = 0; $i < count($matchs); $i++){
$isexist = $mydb -> rows_of_select('select * from surface where stationId = '.$matchs[$i][1].' and recordTime = '.$timestr);

if($isexist > 0) continue;

$sql .= '( ';
$sql .= $timestr.",";

for($j = 1; $j < 20; $j++){
$str = $matchs[$i][$j].",";
$sql .= $str[0] === '.' ? '0'.$str : $str;
}
$sql .= $matchs[$i][20] .' )';
if($i < count($matchs) - 1)
{
$sql .= ', ';
}
}


return $mydb -> doSql($sql);
}

5.更新站点信息(站点名称)

update station set name = '顺义' where id=54398;
update station set name = '海淀' where id=54399;
update station set name = '延庆' where id=54406;
update station set name = '佛爷顶' where id=54410;
update station set name = '汤河口' where id=54412;
update station set name = '密云' where id=54416;
update station set name = '怀柔' where id=54419;
update station set name = '密云上甸子' where id=54421;
update station set name = '平谷' where id=54424;
update station set name = '通州' where id=54431;
update station set name = '朝阳' where id=54433;
update station set name = '昌平' where id=54499;
update station set name = '斋堂' where id=54501;


6.根据用户请求返回数据:

SELECT id, lon, lat,
LEVEL
FROM station
WHERE LEVEL <=2
ORDER BY sqrt( lon * lon + lat * lat )
LIMIT 30


7.检查是否有重复数据

SELECT recordTime, stationId, count( recordTime ) AS num
FROM `surface`
WHERE recordTime =20111111230000
GROUP BY stationId
LIMIT 500


8.添加唯一性约束条件

delete FROM `surface`
WHERE stationId =99999;

alter table surface
add unique (stationId,recordTime);