流川的Blog

流川的Blog

<2008年10月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

导航

统计

公告

终于有自己的blog啦。不过还不怎么会用。慢慢适应。

留言簿(0)

随笔分类

随笔档案

文章分类

文章档案

vckbase的好友们

搜索

最新评论

  • 1. re: 写一个"实时"定时器
  • 好东西,支持
  • --飞凌
  • 2. re: 无界面程序中使用ActiveX控件完成其功能
  • 好东西,收藏了
  • --配线架
  • 3. re: 我负责的项目进度回顾。
  • XD,你这个太快了吧,PF啊,看你们好象只有2三个人在做事情,一个新项目2个月左右就出了几个版本最后稳定下来真是很难得啊
  • --XC
  • 4. re: 乘错车的后果
  • 呵呵,我也经常坐错车的。有几次朋友来我们这里旅游,我们做错了公车,最后到的地方我也不熟悉了。感觉都很搞笑的呢。
  • --精灵
  • 5. 素衣女服饰
  • --素衣女服饰
  • 6. re: 畸形的中国共享软件产业
  • 你的文章非常精彩,秀逗邀请您加入秀逗博客联盟.中国最大最专业的博客推荐联盟,秀逗博客联盟不截取流量,推荐后的文章指向作者本人的BLOG,文章24小时循环首页展示,真正意义上迅速提升你的博客流量!欢迎注册,注册后将推荐代码添加到自己的BLOG相应位置即可轻松推荐文章,让更多人分享你的文章!后期更有秀逗市场、同心琐秀、商业联盟以及社区陆续登场,更多娱乐功能、商业展示机会,完全免费使用,名人博客,不用再眼红,使用秀逗推荐,流量迅速上升,好的博客,秀逗为您宣传!地址:http://www.sodooo.com
  • --ss
  • 7. re: 畸形的中国共享软件产业
  • 唉~~~~~~~~~~~~....................
  • --freedk
  • 8. re: 畸形的中国共享软件产业
  • 唉~~~~~~~~~~~~....................
  • --freedk
  • 9. re: 软件项目进度的估算
  • 写的很好!
  • --黄道余生
  • 10. re: 畸形的中国共享软件产业
  • 补充: 我的意思是这个问题是社会问题,而并非个人素质或者品德问题。古人云“仓秉实然后知礼节”,老外也有马斯诺五个需求层次之说。如果我们吃、穿、住、用都不能保障(或者要斤斤计较),谈道德、谈素质有点太远了。毕竟这是一个物欲横生的社会,大家又都是俗人。
  • --一笑

阅读排行榜

评论排行榜

2006年8月20日

畸形的中国共享软件产业

今年关于共享软件产业里面的新闻倒是不少。2005年7月18日,百度收购天空软件园,收购价格为3000万元。而此时,千橡集团秘密收购中国共享软件注册中心,并在6月将其改造成为“中国软件社区”,与其此前收购的下载工具软件DUDU加速器一起捆绑。(DUDU加速器正是北京市软件协会公布的“十大流氓软件”之一。)

回想起今年上半年,N多人加我QQ,说想让我和他们合作。我问怎么合作法?几乎都无一例外的说捆绑插件,根据流量来支付广告费,我的态度选择沉默,因为我不想让自己开发的软件背上“流氓软件”的罪名。我就感觉很奇怪,怎么会忽然之间有这么多人加我,和我谈捆绑软件的事情
...

在《中国共享软件联盟》群里(是softreg.com.cn开发者讨论群),上面贴着这么一句公告:"动荡,呵呵,动荡。物是人非,你大娘已经不是你六年前的你大娘,你大爷还是你大爷"。现在我明白了,softreg被收购了,还和流氓软件合作了,我也感觉到里面的人事也发生了很大变化...

我的邮箱里面每天都会受到上百封垃圾邮件,偶尔会收到这样的英文邮件,大致意思是说,你的软件已经经过我们检测,没有捆绑流氓软件,可谓"Clean Soft",希望能把这个连接标志放上去...

不久前,一哥们在QQ上发消息给我说:知道吗?flashget被收购了,获得了1000多万。然后开玩笑似得跟我说,你的软件比他做得好,应该值5000多万吧?跟着,发了一个大笑的表情。我发了一个微笑的表情给他。没有继续再说一句话。我心里明白,flashget之所以值那么多钱,并不是因为它软件本身,而是他拥有的用户数。而我的呢,原本可怜的用户数,加之很久未更新,很多人都不知道有这款软件存在了...

当然,也有很多个人或者团体,想通过收购源代码的方式,将他买下...

我是早在2004年1月19日就辞了原本在老家在常人眼里看上去还不错的工作。承受了常人无法想象的压力,于2005年12月25日发布了1.0版。就在当时,还曾经有一次小小的轰动,本人也被<大众软件>2005年02期做了采访。
 
然后紧接着,似乎预期结果要比我预料中差很多。3月底,由于压力,不得不来到上海找了一份工作,那时,我的银行账户里全部积蓄只剩下2000多元。4月,和我相恋3年的第一个女朋友终于宣布分手。在接下去几个月里,人都过得很颓废,心里被痛苦压抑着。7月终于从痛苦里走出来,做了一次小小的更新。接着,就似乎完全和这个产业绝缘了。现在这份工作,也不是因为那个软件而找到的。在我们公司里,也没有人知道我是那个软件的作者。而我一天的收入,恰好等于该软件在1、2年里所收取的全部注册费用。 现在我连在quwert(有点忘了名字)和shareit的用户名密码也忘了...或许我的经历,也只是该行业圈里千万人中的一个缩影。

说起产业畸形,当然和中国的基本国情脱不了关系。

先根据我的经历看看国内和国外的软件递交方面的不同。
1.当初我把软件发布到国外站点的时候,经常会收到下载站的邮件,大致意思是说,愿意和我按照下载量分享注册费用。而当我把软件发布到国内站点时,他们也很高兴,说感谢提供软件,我们会免费给你刊登之。
2.国外站点发布的时候,大部分站点只需要递交一个PAD文件就可以了。(说白了就是一个xml文件,里面有一些软件版本,文件大小,信息,注册地址等等全部信息)。国内站点发布的时候,需要将这些信息放在邮件正文里面发送过去。
3.若非特殊说明,国外没有收到你递交软件的网站是不会刊登你的软件的。在国内,几乎所有的网站(特别是中小下载站)不经过你的同意,就可以将你的软件刊登上去。
4.我没有看到过自己的软件被人家破解了放在国外的站点上。而在国内的一些站点却可以堂而皇之的挂上去。
5.如果自己的软件更新了,在你不通知其他站点的情况下,国外网站如果支持PAD软件的,他有个机器人会自动更新之。如果不支持PAD的,就不会去更新,偶尔,他会发封邮件给你,说是否愿意去他们站点手工更新一下。国内站点,会很勤快的帮你更新。
说明一下,这可能和中国的传统文化有关系。国外人做事,一是一,二是二,没有任何余地。而中国人深受传统文化的影响,加上勤劳和互帮互助就是中国人的传统美德形成的差异。当然,一方面和我们制定的法律法规不完善也有点关系,那种版权观念尚未深入人心。

再看看产业链。与其说是产业的畸形,还不如说是盈利模式的畸形。做企业也好,做行业也好,首先你要明白,你所在的产业链是什么样子的。你的合作伙伴是谁,你的竞争对手是谁,你的上游是谁,你的下游是谁。当然也要掌握国家的宏观经济,法律法规,市场规律等。
在csdn上这篇文章写得很好(http://news.csdn.net/n/20060814/93678.html)。已经说出了我的心声。


现在的我,就和常人没什么两样,过着常人应该过的生活。在我的职业生涯中,在IT业里做了五年多,中间一年多去了另外一条路转了一圈又回来了。就算中国共享软件产业再怎么畸形再怎么病态,也是我个人所无法改变的。希望有朝一日,他能走上正常的轨道,有他自己的盈利模式。而这种盈利模式,不是通过那种强制在用户机器上,强制安装插件等流氓行为为代价的。到那时,我还是会辞了工作,在家专职做共享的,那才是我向往的生活,做自己想做的事情,不被衣食所迫,过着自由无虑的生活。我会期待那一天到来的。现在,我还是会笑着对你说:我还会回来的!

发表于 2006-08-20 16:11 liuchuan的Blog 阅读(5305) | 评论 (5)编辑 收藏

软件项目进度的估算


当是否决定做一个项目时,总是要评价该项目是否能带来利润。

这就需要估算成本和收益。由于IT是人密集型产业,在估算成本时,人力成本是占主要成本之一。而在公司里面,人员的工资一般是固定的。因此,就需要估算项目的开发时间。

IT行业不同其他行业,其他行业,比如建筑,房地产等,开发完毕一个项目时,可能会再开发一个相同的项目。项目经理可以根据以前的经验,精确的估算下一个项目的时间。但IT项目每个项目都是最新的,因为不可能说开发同一个项目多次,也没有必要。加上IT又是一个新兴的行业,只有很少的历史数据可以参考。这就更加加强了估算的难度。

从以往经验来看,估算的精度一般是实际的20%-100%左右。能达到10%以内已经算是很好了。5%以内?呵呵,没听说过。

根据什么来估算呢?只能根据项目经理以往的经验和自己掌握的各方面技能估算。时间不能估得太短,也不能估得太长。如果估得太短,在开发过程中会面临各种各样的风险,比如人员的离职和抽调,需求的变更,其他项目的介入等等,到最后完不成任务,影响小组的士气,对以后肯定影响不好。估得太长,你的上司就不会同意,还会认为你的人怎么怎么样,会给他们留下不好的印象。何况根据帕金森法则:一个项目给它多少时间,他就会在这段时间内将它耗完。你的小组人员本来2天能做完的时间,听说有5天时间,于是乎,会将2天的工作量分散到5天里。不知不觉地就把时间耗完。同样的项目,给不同的开发团队,实际的进度也不同。开发人员的心情会影响进度,心情好的时候,开发速度快,心情不好的时候,开发速度就很慢。水平高的和水平低的开发人员,差异也很大。(据《人员神话》记载,好像相差10倍,等我确认后再写上去)。

然而大部分项目经理在执行项目时,时间进度却不是由自己和开发小组决定的,而是由老板或者市场部决定的。他们似乎也不怎么和你讲道理的。如果他们将时间压得太紧,而你知道,在这段时间内根本就不能完不成任务。怎么办呢?如果你只是将这个消息传递给开发小组人员,那整个项目注定是失败的。因为开发小组如果一致认为,是完不成的任务。那肯定就会有很大的压力,有能力者就会有跳槽的打算。反正完不成,很多人就没有心情再做下去了。于是,你必须针对不同的情况,了解为什么给自己这么紧的原因。后来你了解到,有些项目是客户为了应付上级的演示,这时候,你可以根据实际情况,对功能进行裁减,哪些功能是必需的,哪些功能是可要可不要的。确定功能的优先缓急,将最主要的功能部分做好。

值得注意的是,随着开发过程的继续,估算的精度会越来越趋近于实际值。等到详细开发文档出来,就和实际值相差无几了。这就是软件估算的渐进性。

项目估算是在进行执行项目前必须的工作。估算的结果,直接影响到该项目是否应该实施。建议最好在估算时,最好将部分有难度的功能提炼出来,给开发小组人员进行估算。另外,一个团队在一起进行估算,到以后实施时候就有很大的时间上的保证。三峡工程在进行估算(可行性分析)的时候花了几年时间,可见估算有时候也是一项很重要的工程了。

以上都是理论知识,下面说说我们单位的情况吧,我在我们单位的角色,既是某项目的负责人,又是其他项目的参与者。最多的时候,1个星期内负责/参与3-4个项目。同时工作10几个模块。让我很郁闷的是,竟然没有开发计划,老板会一天到晚在你身边转悠,问你进行到什么情况了,如果看到你没有完成,就更加有理由监督你了,如果看到你完成,就更急了,先是自己想,看看有没有事情给你做,想不到,就让部门经理分配事情给你做!无休无止的加班。 如果是老板早上来,就是9点初,因为我们9点上班。如果是中午,就是12:30过后一点点,因为我们12:30就会上下午班。下午,5点多过来,我们5:30下班。然后赖着一直不走。。。监督机制不错,但是殊不知,他无法确认我们在做什么。虽然公司装了监控系统,上网的行为都会被监控,但是,相互都不知道在做什么。我是不管,过了下班时间1小时左右,我是呆不住的。就算那时候走,也是差不多我们部门第一个走。(今年续签协议后,感觉很郁闷,压力也很大,发发牢骚罢了。)

记得福特公司老板去他车间里转悠时,看到一个人在那里吊儿郎当,非常看不惯,于是他把他主管找来,说,把那个翘着二郎腿,什么事都不做的那个人开掉。主管一听急了,说,我们公司所有的汽车可都是他设计的!结果可想而知,光从表面看,你无法知道脑力劳动者在做什么。区别于机器,一天能生产1000个零件,2天就能生产2000个。

在我们公司项目前期很少估算,因为谁也保证不了时间。我不知道这样的情况会不会是以后职业生涯中的一个反面案例。

开发是一项脑力劳动,和人有很大的关系,如果缺乏有效的管理,势必会跌入泥潭,能力高着一个接一个跳槽。

发表于 2006-08-20 13:41 liuchuan的Blog 阅读(3351) | 评论 (1)编辑 收藏

2006年4月17日

无界面程序中使用ActiveX控件完成其功能

比如,需要用一些ActiveX控件,但程序本身无界面的情况下。

1)从CWnd类中派生CMyWindow
2)增加成员函数 HWND Create();
HWND CMyWindow::Create()
{
 //Register a window class
 LPCTSTR classname = 0;
 classname = AfxRegisterWndClass(0);

 //Create the window and return it's handle
 CWnd::CreateEx(NULL,classname,NULL,NULL,0,0,0,0,NULL,NULL);
 ASSERT(m_hWnd!=NULL);

 return m_hWnd;
}

3)重载virtual void PostNcDestroy();
void CMyWindow::PostNcDestroy()
{
 //clean up this object
 delete this;
}

这样使用:
1).h中声明CMyWindow*m_pWnd;
2)初始化:
 m_pWnd = new CMyWindow;
 HWND hwndTarget = m_pWnd->Create();
3)销毁
m_pWnd->DestroyWindow();


该类不可见,可以包含一些ActiveX控件。
如果要相应ActiveX的事件,则
.h中
 DECLARE_EVENTSINK_MAP()
.cpp中
BEGIN_EVENTSINK_MAP(CMyWindow, CWnd)
  ON_EVENT(CMyWindow, CONTROL_ID, 2, OnNewImageCamimage, VTS_NONE)
END_EVENTSINK_MAP()

发表于 2006-04-17 16:24 liuchuan的Blog 阅读(2070) | 评论 (1)编辑 收藏

2005年10月21日

窗口查找类以及扩展

class CFindWnd {
private:
 //////////////////
 // This private function is used with EnumChildWindows to find the child
 // with a given class name. Returns FALSE if found (to stop enumerating).
 //
 static BOOL CALLBACK FindChildClassHwnd(HWND hwndParent, LPARAM lParam) {
  CFindWnd *pfw = (CFindWnd*)lParam;
  HWND hwnd = FindWindowEx(hwndParent, NULL, pfw->m_classname, NULL);
  if (hwnd) {
   pfw->m_hWnd = hwnd; // found: save it
   return FALSE;   // stop enumerating
  }
  EnumChildWindows(hwndParent, FindChildClassHwnd, lParam); // recurse
  return TRUE;    // keep looking
 }

public:
 LPCSTR m_classname;   // class name to look for
 HWND m_hWnd;     // HWND if found

 // ctor does the work--just instantiate and go
 CFindWnd(HWND hwndParent, LPCSTR classname)
  : m_hWnd(NULL), m_classname(classname)
 {
  FindChildClassHwnd(hwndParent, (LPARAM)this);
 }
};

该类来自于MSDN Magazine -- August 2003。
用法:CFindWnd fw(hwndParent,classname);
fw.m_hWnd就是你要找到的窗口句柄。如果目标窗口是顶层窗口,则hwndParent填为NULL.

某些情况下,如果说你要找到一个对话框框中的密码框,那么该对话框中可能有多个Edit。
用该类显然不能满足要求。
很多情况下,我们要找到一个对话框中的所有Edit,怎么办呢?
因此,我按照他的思想,来定制了一个类。


#include <vector>
using namespace std;
class CFindWndEx {
private:
 //////////////////
 // This private function is used with EnumChildWindows to find the child
 // with a given class name. Returns FALSE if found (to stop enumerating).
 //
 static BOOL CALLBACK FindChildClassHwnd(HWND hwndParent, LPARAM lParam)
 {
  CFindWndEx *pfw = (CFindWndEx*)lParam;

  //判断该窗口
        char sClassName[1024]={0};
  ::GetClassName(hwndParent,sClassName,sizeof(sClassName)-1);
  if(strcmp(sClassName,pfw->m_classname)==0)
  {//本窗口!
   pfw->m_listWnd.push_back(hwndParent);
  }

  HWND hwnd = ::GetWindow(hwndParent,GW_CHILD);//第一个子窗口
  while(hwnd)
  {

   if(::GetWindow(hwnd,GW_CHILD))
   {//如果具有子窗口
    FindChildClassHwnd(hwnd, lParam); // 递归到该窗口下所有窗口
   }
   else
   {//如果非子窗口
    ::GetClassName(hwnd,sClassName,sizeof(sClassName)-1);
    if(strcmp(sClassName,pfw->m_classname)==0)
    {//该窗口!
     pfw->m_listWnd.push_back(hwnd);
    }
   }

   hwnd = ::GetWindow(hwnd,GW_HWNDNEXT);//下一个子窗口
  }


  return TRUE;    // keep looking
 }
public:
 vector<HWND> m_listWnd;
public:
 LPCSTR m_classname;   // class name to look for
 HWND m_hWnd;     // HWND if found

 // ctor does the work--just instantiate and go
 CFindWndEx(HWND hwndParent, LPCSTR classname)
  : m_hWnd(NULL), m_classname(classname)
 {
  m_listWnd.clear();

  if(!hwndParent)
  {//所有顶层窗口
   HWND hwnd = ::FindWindow(m_classname,NULL);//第一个子窗口
   while(hwnd)
   {
    FindChildClassHwnd(hwnd, (LPARAM)this);

    hwnd=::GetWindow(hwnd,GW_HWNDNEXT);
   }

  }
  else
  {
   FindChildClassHwnd(hwndParent, (LPARAM)this);
  }

       
  TRACE("Start=======================>\n");
  int nWndCount=m_listWnd.size();
  for(int n=0;n<nWndCount;n++)
  {
   TRACE("Index:%d\tHWND:%x\n",n,m_listWnd[n]);
  }
  TRACE("End=========================>\n");

 }
};

用法:CFindWnd fw(hwndParent,classname);
fw.m_listWnd就是目标的所有窗口列表。
如果你要得到密码框,你可以遍历,一个一个取属性后得到。

如果有任何疑问,欢迎指出。

发表于 2005-10-21 14:49 liuchuan的Blog 阅读(1752) | 评论 (0)编辑 收藏

2005年9月15日

写一个"实时"定时器

微软提供的SetTimer,KillTimer这样的函数设置定时器很简单。
但WM_TIMER这样的消息却是优先级很低。
很多情况下,如果你需要定时的去调用你的函数来实现功能。但是当系统繁忙的时候,你可能迟迟响应不到这样的消息。
我就有过这样的经历,需要定时的把视频流写入到文件。本来设置成1、2分钟,结果有时候竟然30分钟才响应。如果用CreateWaitableTimer之类的函数又太繁琐。要是设置很多定时器怎么办呢?

一怒之下,自己写了一组函数。

头文件:
TimerEx.h:
#pragma once

#include <list>
using namespace std;

class TimerParam
{
public:
 HWND hWnd;
 UINT nIDEvent;
 UINT uElapse;
 HANDLE hTimer;
 CWinThread* pThread;
};

//list<TimerParam*> m_listpTimer;
UINT SetTimerEx(HWND hWnd, UINT nIDEvent,UINT uElapse);
BOOL KillTimerEx(HWND hWnd, UINT uIDEvent);

TimerEx.cpp
#include "StdAfx.h"
#include ".\timerex.h"

UINT SetTimerEx(HWND hWnd, UINT nIDEvent,UINT uElapse);
BOOL KillTimerEx(HWND hWnd, UINT uIDEvent);

UINT MyControllingTimerFunction( LPVOID pParam );
list<TimerParam*> m_listpTimer;

UINT MyControllingTimerFunction( LPVOID pParam )
{
 TimerParam*pTimerParam=(TimerParam*)pParam;
 int nSleep=0;
 while(WaitForSingleObject(pTimerParam->hTimer,nSleep)==WAIT_TIMEOUT)
 {
  SendMessage(pTimerParam->hWnd,WM_TIMER,pTimerParam->nIDEvent,0);
  nSleep=pTimerParam->uElapse;  
 }
 return 0;
}

UINT SetTimerEx(HWND hWnd, UINT nIDEvent,UINT uElapse)
{
 TimerParam*pParam=new TimerParam;
 pParam->hWnd=hWnd;
 pParam->nIDEvent=nIDEvent;
 pParam->uElapse=uElapse;
 pParam->hTimer=CreateEvent(NULL,TRUE,NULL,NULL);
 pParam->pThread=AfxBeginThread(MyControllingTimerFunction,pParam);
 m_listpTimer.push_back(pParam);
 return 0;
}
BOOL KillTimerEx(HWND hWnd, UINT uIDEvent)

 MSG msg;
 for(list<TimerParam*>::iterator _Iter=m_listpTimer.begin();
  _Iter!=m_listpTimer.end();_Iter++)
 {
  TimerParam*pTimer=*_Iter;
  if(pTimer->hWnd==hWnd&&pTimer->nIDEvent==uIDEvent)
  {
   SetEvent(pTimer->hTimer);
   Sleep(0);
   PeekMessage(&msg,hWnd,0,0,PM_NOREMOVE);
   Sleep(0);
   WaitForSingleObject(pTimer->pThread->m_hThread,INFINITE);
   CloseHandle(pTimer->hTimer);
   delete pTimer;
   m_listpTimer.erase(_Iter);
   break;
  }
 }
 return TRUE;
}

你可以在窗口类面,用向导加入WM_TIMER消息。
作为测试,你可以在OnCreate函数中加入:
 for(int n=1;n<nMax;n++)
  ::SetTimerEx(m_hWnd,n,1000*n);

OnDestroy()加入:
 for(int n=1;n<nMax;n++)
  ::KillTimerEx(m_hWnd,n);

OnTimer(UINT nIDEvent)中加入你想要的函数就可以了。


如果你想修改以前的代码,只需要
在SetTimer的地方改成::SetTimerEx,
KillTimer的地方::KillTimerEx就可以了。
但请注意参数。
====================
关于KillTimerEx里面的2个小地方稍微做下解释:
Sleep(0);表示切换到另外一个线程。
PeekMessage,表示处理一下SendMessage消息。
这点比较重要,如果万一线程正在SendMessage中,而你又在
WaitForSingleObject(pTimer->pThread->m_hThread,INFINITE);
可能会发生死在那里的情况。虽然这种可能性极小。

有什么疑问和问题或者任何建议都欢迎和我探讨。

发表于 2005-09-15 16:16 liuchuan的Blog 阅读(3534) | 评论 (4)编辑 收藏

2005年9月6日

狂晕的几天!

 

我真是服了我们老板了!!!
一边催我们快做快做,要把东西在N天之内完成,一边又不断地加新功能。

今天又要加上为每个用户设置一个权限。
我在这个系统中设计了一个tUser表(用户)和tMonitor(摄像头表)。
在tUser表中有一个int型表示权限。我知道可以用&操作来判断是否具有这个权限的功能。
但老板说要用户1可以查看指定的一个或多个摄像头。
用户2可以查看其他指定的一个或多个摄像头。
在实际应用中,我估计可能是这样子的:
用户1是销售部经理,他可以查看属于销售部的摄像头。
用户2是测试部经理,他可以查看属于测试部的摄像头。
我现在头脑有点乱了。还没有想好怎么设计。

在和同事配合过程中,今天发现了一个大问题:
他的理解和我的思路不一致!
在客户端倒没什么,但到了管理端,我设计了数据库如下:
============================================================================
tMonitor (摄像头表)
主键、索引 字段名字 类型 长度 允许空 描述
主键 nID 自动增量 4 0 记录ID。
 sCompanyID nvarchar 13 0 应用平台ID.
 nMonitorID int 4 0 摄像头ID.
 sName nvarchar 256 0 摄像头名
 sIP nvarchar 16 0 摄像头IP(局域网可以访问的IP)
 nPort smallint 2 0 摄像头端口号(局域网可以访问的端口)
 nFPS smallint 2 0 摄像头图像传送速率 每秒*帧
 sSnapShotFolder nvarchar 300 0 摄像头拍照的路径(相对路径,/开头),允许用户修改
 bEnabled smallint 2 0 是否启用。1:启用,0:禁止。
 bConnected smallint 2 0 状态是否连通。
 lDeptID int 4 1 部门ID,默认0.为保持兼容,允许空
============================================================================
tMonitorLog(摄像历史记录表)
主键、索引 字段名字 类型 长度 允许空 描述
主键 nID 自动增量 4 0 记录ID。
 sCompanyID nvarchar 13 0 应用平台ID.
 nMonitorID int 4 0 摄像头ID。
 sFileName nvarchar 256 0 文件名
 sLogPath nvarchar 256 0 当前记录的路径(相对路径,/开头)
 nFileSize bigint 8 0 文件大小.
 nStatus smallint 2 0 0:初始状态。
 nRecvSize bigint 8 0 已经接受的长度
 dtLogTime datetime 8 0 记录的时间
============================================================================
tMonitorCommandLog(摄像历史记录读取命令表)
主键、索引 字段名字 类型 长度 允许空 描述
主键 nID 自动增量 4 0 记录ID。
 sCompanyID nvarchar 13 0 应用平台ID.
 nMonitorID int 4 0 摄像头ID。
 dtStartTime datetime 8 0 开始记录的时间.
 dtEndTime datetime 8 0 终止记录的时间.
 nFileType smallint 2 0 需要传送的文件类型0:照片1:视频
 nStatus smallint 2 0 0:尚未执行
============================================================================
还有很多表...
她把tMonitorLog/tMonitorCommandLog等表中的nMonitorID对应于tMonitor的nID。而不是tMonitor的nMonitorID!
还怪我我没有和她讲清楚。晕啊!!!
我举了很多情况,说明了如果按照她理解所带来的严重后果。
我知道她工作很忙,如果再加上权限功能,则工作量会更大。
但真的是没有办法!只能她那里改~
我想她心里一定对我很不舒服,可是没办法!
这几天工作压力太大了,每天都很晚才回去。
过几天你看着,又会说我项目拖了这么久了!!!唉.........
============================================================================

发表于 2005-09-06 18:48 liuchuan的Blog 阅读(2971) | 评论 (7)编辑 收藏

2005年8月23日

又是一点小问题

今天在测试的时候又遇到了一个小问题:

起源于我把星期列表定义为一个DWORD型。
星期日代表0,星期一代表1,星期二代表2,星期三代表4。

为了清楚起见,我特意在文档说明了这个字段类型。

------------------------------------------------------------------
关于dwWeekList:
放入7个CheckBox,分别是:
星期日:1 -代表pow(2,1-1)=pow(2,0)=1
星期一:2 -代表pow(2,2-1)=pow(2,1)=2
星期二:3 -代表pow(2,3-1)=pow(2,2)=4
星期三:4 -代表pow(2,4-1)=pow(2,3)=8
星期四:5 -代表pow(2,5-1)=pow(2,4)=16
星期五:6 -代表pow(2,6-1)=pow(2,5)=32
星期六:7 -代表pow(2,7-1)=pow(2,6)=64

例:
从星期列表选择的结果得到值:
如果选择:星期一,星期三,星期四,星期五:
则dwWeekList的值为:2+8+16+32=58

从值转为星期列表:
如果dwWeekList为58,变成二进制为:0111010—〉从右向左排列:0101110
其中:0表示不选中,1表示选中.
从右向左代表:星期日(0), 星期一(1), 星期二(0), 星期三(1), 星期四(1),星期五(1), 星期六(0)
下述办法可以取得。&表示与
58&1=0: 星期日
58&2=1: 星期一
58&4=0: 星期二
58&8=1: 星期三
58&16=1: 星期四
58&32=1: 星期五
58&64=0: 星期六
------------------------------------------------------------------
结果她还是把星期一当成1,星期二当成2,星期三当成4处理,结果存入数据库。
结果我程序里面读取进行分解的时候造成不一致。

她问我,能不能在我这里改啊。我晕......
她说每次我和你不一致时,你总是让我改。

我回答:刚开始就是这么定义的。如果我没有按照定义去执行,那肯定是我要改。
但如果是你没有按照定义去做,那就是你改了。

她无奈的说,好吧,我知道了。

其实让别人改,我也不怎么好意思的。可是...
唉,不说了。

发表于 2005-08-23 12:49 liuchuan的Blog 阅读(2674) | 评论 (9)编辑 收藏

2005年8月22日

结不了的项目

8月19日,WY编码完毕,本以为这个项目今天可以结了。
结果上午又要添加2个新功能:
1)增加摄像头是否连通时间段列表
2)统计是否连通的摄像头。
好在我这里改动不是太大。
新建了一个表。另外在管理平台摄像头表里面添加一个字段。
我的编码部分也在1-2小时内完成了。

下午我给他们测试部全体人员作培训。
他们在会上还提出一些要求。还说准备整理发送给T总。
很显然,T总看了以后会催YY,然后YY会催我,我又会催WY.
因为改动的部分都在WY那边。
于是乎,我直接发送给WY说明情况,让她早有心理准备。

发表于 2005-08-22 17:44 liuchuan的Blog 阅读(2643) | 评论 (6)编辑 收藏

2005年8月18日

我负责的项目进度回顾。


项目进度列表(根据电子邮件来往记录确定。)

时间

邮件收发人及内容

后续的工作

2005 年 6 月 1 日

从DJB那里受到摄像头公司提供了一个 ocx 以及 html 示例调用。

正式接手项目。但还不清楚需求是什么.
用 vc 将 ocx 导入,查看该 ocx 能实现的功能。并新建简单的工程进行测试。
总结在以后开发过程中可能存在的技术难题。
摄像头公司技术人员来我们公司进行沟通。

2005 年 6 月 9 日

将总结可能在开发过程中遇到的难题发送给DJB。

T总提出需求:
1)保存网吧中的本地数据
2)实时监控。
3)每 2 个星期保存一次。定时监控,定时传送到远程。
4)查询功能。

2005 年 6 月 10 日

画出架构图和模块图以及完成概要设计书。发送给YY。

整理需求,并进行构思,规划和设计。

2005 年 6 月 13 日

发送相关文档给ZZY.
发送关于摄像头的一些疑问给摄像头公司

和同事讨论该方案是否可行。

2005 年 6 月 14 日

将数据库设计文档和模块图发送给YY。

完成数据库设计。完成写入视频模块和传输模块的流程图。

2005 年 6 月 17 日

将项目相关文档发送给WY

让ZZY协助开发用户管道程序。该程序定义为可选程序。考虑到难度较大。在数据库设计时考虑万一实现不了的情况。用端口映射的办法解决。
让WY协助开发应用中心和管理中心的设计。主要负责界面开发这一部分。

2005 年 6 月 20 日

数据库表作了修改 . 将修改后的表发送给WY,ZZY

主要涉及摄像头 / 摄像头操作 / 摄像头记录的表 .
和摄像头公司人员进行沟通。

2005 年 6 月 21 日

需要摄像头公司提供播放器代码请求T总确认。发送给T总和YY。
将摄像头公司发过来的 Ocx 文档发送给ZZY。

开发过程中需要播放器代码用来查看历史记录。
和美国摄像头公司联系。他们要求我们公司做一些担保。即
1) 不得将摄像头公司的源代码未经他们公司允许提供给第三方。
2) 我们用摄像头公司的代码实现播放器以后,将建立在他们公司代码的基础上实现的播放器代码给他们公司。

2005 年 6 月 22 日

发送需要项目需要实现的功能列表给WY。

发送需要实现的功能列表。
以及 ocx 的使用示例。

2005 年 6 月 27 日

数据库定义修改发送给WY和ZZY

将原先的用户名和密码信息合并入 tMonitorUser 表中

2005 年 6 月 30 日

发送测试程序给WY

写入视频服务和拍照服务完成,发送给WY。在数据库中可以自动插入一些记录。以便她可以开发查询功能。

2005 年 7 月 1 日

发送数据库给WY

增加数据库表部分对状态的定义

2005 年 7 月 4 日

再次发送测试程序给WY

视频服务和拍照服务的更新

2005 年 7 月 5 日

收到ZZY发送管道程序注册表结构
发送摄像头工程产品测试通知书和打包程序列表给WY请求确认和补充。

主要模块编码完毕

2005 年 7 月 6 日

发送WY最新测试程序

2005 年 7 月 11 日

发送测试通知书到测试部。
更新数据库发送给WY

2005 年 7 月 12 日

发送 Log 组件给WY调用

完成传输服务代码,并将接口提供给她。

2005 年 7 月 14 日

提供播放器组件给WY调用

完成播放器 ocx

2005 年 7 月 18 日

将打好的包通知测试部
将数据库设计书发送给测试部。
提供拍照组件给WY调用

给T总以及相关市场部人员演示后提出很多意见。

2005 年 7 月 21 日

将播放器代码发送给摄像头公司

该版本空间支持远程播放视频记录。通过 URL 指向地址。

2005 年 7 月 22 日

将意见转发给相关人员。

总结目前需要改进的地方:
1) 视频需要实现连续播放功能。
2) 为每个摄像头指定录制时间间隔。(类似计划任务功能)
3) 为每个摄像头添加使能功能。
(如果网络不通等原因引起的摄像头不能正常工作,可以暂时设置为禁止状态。则后台服务不记录以及不提示错误信息。待正常工作后设置为启用。即可恢复)
4) 为每个摄像头添加一个备注。用户可以指定显示或隐藏备注。
5) 自动清理 N 天内的记录。
6 )界面的显示需要友好。(标题部分的工程名 / 日志查询以后的某些字段名 / 摄像头设置的位置等等,)。
7 )登录之后自动显示实时视频。根据用户设置分页。并保存上一次登陆时候的设置。
8 )拍照按钮放于查看视频的下方,可以让用户一边看,根据需要来拍照。
9 )当摄像头连接失败时,给出中文提示。
10 )对播放视频控件进行改进,增加开始 / 停止 / 暂停 / 关闭按钮,以及加上滚动条。
11 )对日志的处理,允许用户删除。
12 )其他

2005 年 7 月 22 日

数据库稍作修改发送给WY

未考虑周到的地方 :
照片 / 视频 / 命令表中含有状态的地方。
客户端的视频查看可能也需要通过管道程序。

2005 年 7 月 23 日

发送相关文档给T总

T总叫我过来提出了不少意见。指出我工作中的不足和以后需要改进的地方。
( 周六 )

2005 年 7 月 25 日

将界面构思发送给WY
数据库修改以后发送给WY
最新版播放器发送给WY

界面需要重新规划。
做成左边“树”的形式,并将上面的菜单部分去除。

2005 年 7 月 26 日

发送效果图
以及界面设计等给YY

2005 年 7 月 27 日

发送取得大小的组件给WY

数据库中的字段是 bigint 型,将要换成 M 以便显示。

2005 年 7 月 29 日

确定时间进度
将最新版的播放器控件发送给摄像头公司。并要求将实时视频控件进行改装来满足我们的要求。以及其他问题。

新版本播放器增加:开始 / 停止按钮,显示时间,可以拍照,添加滚动条。以及进度条等界面的美化。

2005 年 8 月 1 日

对现有界面的要求发送给WY

1) 项目名的更改
2) 加上版本号
3)在登录后的首页,显示 ”1,4” 按钮切换。
4) bar 移动到摄像头控件的下方。 : 请选择 ” 背景和 bar 用颜色一致。
5)如果是一个窗口状态,则提供轮询功能。就是每隔一定的时间,自动切换到下一个摄像头显示。
6)在上方标题栏上显示当前时间。
7)最上方的标题栏 : 把IP地址隐藏掉。 ( 其实是 IE 版本问题 )

2005 年 8 月 3 日

通知测试部LWW联系摄像头公司的杭州办事处升级摄像头。
摄像头公司控件升级通知ZZY

2005 年 8 月 8 日

收到WY邮件,确认代码写完。并作内部测试。

2005 年 8 月 9 日

通知测试部ZYH搭建测试环境
收到美国摄像头总部的 ocx 源代码转交给ZZY

2005 年 8 月 10 日

将最新版 ocx 控件发送给WY
提出对界面的一些不足让她加以修改。

T总以市场部人员对该工程又进行一次验收。并提出了相关建议。

2005 年 8 月 11 日

将整理后的意见发送给WY

1) 日志查询 ( 照片 , 视频 ), 查询按钮的位置。
2) 视频的连续播放。 ( 网页上放入上一个,下一个,加入自动播放按钮 )
3) 照片的连续播放。 ( 加入自动播放按钮 )
4) 设置自动播放的时间间隔。
5) 点查看视频以后,将摄像头名替换为原来的文件名。
6) 点查看照片以后,将摄像头名替换为原来的文件名。
7) 查看照片以后的关闭按钮的位置。
8) 策略的多样化 ( 暂不修改 )
9) 应用程序名。客户端改成应用平台,服务器端改成管理平台。
10) 将 SQL Server 改成 MySQL .
11) 其他
后来的要求 :
在管理端 :
1) 首页显示实时视频。
2) 增加远程查询功能。
3) 增加单位管理。听T总说他要把这个系统单独出来去卖。需要有增加 / 修改 / 删除单位功能。
4) 查询功能能指定某个区所有的单位。(以前只是针对某个单位进行查询。 )

2005 年 8 月 15 日

数据库修改发送给WY
通知WY手头工作的优先级

更改原因 :
1) ZZY的管道程序已经做完并已完善。 ( 原先的设计曾考虑到没有管道程序的情况 / 通过端口映射实现而加入 sPubIP 和 nPubPort ) 。
2) 现确定 : 一个单位只能有一个管道程序。一个管道程序经过网管设置 , 可以访问所有 VLan 中的摄像头。 ( 原先考虑曾经可以有多个。如果有多个将会导致 sShowMonitorNum 和管道程序端的 sShowMonitorNum 检验值不同步 ) 。
3) 以前的变量命名不明确,可能引起WY在编码过程中的疑问。
4) 新添加入远程查询功能必须要知道单位端的 URL 起始地址。
经过考虑,现将数据库某些部分做更改 :( 涉及到WY和WXQ的程序部分也必须作相应修改 ) 。
----------
一、应用平台数据库
tSystem 表中加入 2 个字段 :
sPipleIP 用户管道程序的 IP 地址
nPiplePort 用户管道程序的端口号
tMonitor 表中将 2 个字段去除。
sPubIP nvarchar 16 1 摄像头 IP (公网的 IP )
nPubPort smallint 2 1 摄像头端口号(公网的端口)
-------
二、管理平台数据库设计
tCompany 表中 :
将 IP 和端口号改为 :
sPipleIP 用户管道程序的 IP 地址
nPiplePort 用户管道程序的端口号
并增加
sUrlBase 字段。
tMonitor 表中将 2 个字段去除。
sPubIP nvarchar 16 1 摄像头 IP (公网的 IP )
nPubPort smallint 2 1 摄像头端口号(公网的端口)
经过这样改将导致程序的修改 :
WY :
应用平台 :
1) 增加 / 修改 / 显示摄像头时不用增加 / 修改 / 显示摄像头的公网 IP 和端口号。
2) 连接摄像头时,所有原来从 tMonitor 表中取得的 sPubIP 和 nPubPort 改为从 tSystem 表中取 sPipleIP 和 nPiplePort 。
1> 实时查看 .
3) 允许用户在系统设置中对 sPipleIP 和 nPiplePort 进行修改。
4) 其他保持不变。
管理平台
1) 对单位中摄像头管理部分,不用修改 / 显示摄像头表中的公网 IP 和端口号。
2) 连接摄像头时,所有原来从 tMonitor 表中取得的 sPubIP 和 nPubPort 改为从 tCompany 表中取 sPipleIP 和 nPiplePort 。
1> 实时查看 .
3) 当进行远程查询时 , 程序中 tCompany 表中取得 sUrlBase 进行查询。
4) 允许用户修改 tCompany 表中 sPipleIP/nPiplePort/sUrlBase .
5) 其他保持不变 .
另 : 关于远程查询的几点建议 :
1) 在应用平台最好新建一个目录 , 新建几个程序专门接收来自管理平台的查询。和原来应用平台的程序独立开来。
2) 出于安全性考虑,应用平台的接收程序需要通过加密验证等手段。 ( 优先级 : 低 )
我:
传输服务 ( 应用平台和管理平台 ):
1) 摄像头的 sPubIP 和 nPubPort 不需要传输。
2) 需要增加 sPipleIP/nPiplePort/sUrlBase 传送到管理平台并插入到数据库表 tCompany 中。
注 : 考虑到WY那边改动较多 , 先将 tMonitor 表中的 sPubIP 和 nPubPort 保留 , 等以后有时间了再逐步去除 .
以后新加的程序避免操作这 2 个字段 .

2005 年 8 月 16 日

管理中心数据库表修改通知WY

tCompany ( 单位表 ) 加入字段:

2005 年 8 月 18 日

管道程序部分发送给美国摄像头公司

尚未提供测试程序。等WY界面设计完成后再提供。

待续 …


个人经验总结:
缺点 :
1) 明确需求,应多和市场部人员沟通。确认用户需要什么。如果需求不停的改。那势必影响到
2) 设计时候,没有一个界面设计方案。只是简单的告诉WY需要实现什么功能。用户界面应该多和同事探讨确认。以致最后反复几次才最终确定。浪费了界面设计人员不少的时间和精力。
3) 时间的安排。进度把握不了。特别是不能确定其他同事的进展情况。以致整个项目的时间控制不住。
优点 :
1) 刚开始的架构定义的挺健壮。以后提出的要求和新需求对整个框架的影响都很小。数据库的变化也只是在少数表中的几个字段中进行。大部分改动都局限于界面。
2) 和摄像头公司合作很愉快,使得我们在使用他们控件或者遇到疑问的时候,都没有什么障碍。

发表于 2005-08-18 14:56 liuchuan的Blog 阅读(2657) | 评论 (1)编辑 收藏

2005年8月15日

生成一个GUID

GUID guid;
HRESULT  hrt=CoCreateGuid(&guid);
if(hrt==S_OK)
{
}
else
{
}

发表于 2005-08-15 13:05 liuchuan的Blog 阅读(2803) | 评论 (0)编辑 收藏