0

二十一世纪让人悲伤的七个原因


裸照测试, 它是这样的一个测试: 假如说有一张照片, 照的是你正裸体的干一件事,
这个事会让你和你的家人甚至以后的几代人都会感到羞耻.  打个比方, 人兽交.  问问你自己, 身边能有几个人可以信任到能够共同面对这张照片.
 如果你像下面我们说的那样, 你可能至多会有两个.

事实更令人沮丧,研究表明大约四分之一的人没有一个可以信赖的朋友.

The Sad Bear 1, by Nedroid

 我们发现人们拥有的亲密朋友的数量正在快速的戏剧性的减少,特别是最近的20年里. 为什么会这样?

#1.  我们的生活中缺少让人讨厌的人.

 这不是讽刺.   讨厌的人和事能够锻炼你忍耐的性格, 就像面对乙醇或其它难闻的气味.  如果我们尽量的去避免烦恼,那么,我们处理烦恼的能力也就越差.

 问
题就出在,我们使用科技手段给自己建立里一个令人恐惧的,四处蔓延的web网络,而这个网络就是要让我们躲避那些让人烦恼的朋友。
 不是吗?所有的圣诞采购都在网上进行,这样就避免了和那些胖大嫂为了同一个商品而发生购物车之间的磕磕碰碰。
 花5000美元买一个家庭影院系统,这样就可以坐在家里看电影,像在电影院里有个淘气的孩子老踢你的后座的事情再也不会发生了。
 天,连租DVD也只需要到Netflix网站上,根本不需要到音像店里和那些笨头笨脑的登记影碟的孩子打交道。

  老老实实的在候诊室里等着大夫?  遗憾,与邻座的散发着难闻气味的老人聊天是不可能的。
我们会用iPod听音乐,发短信给朋友或者玩任天堂的DS 把烦恼踢出我们的世界 

 来自outofbalance.org

 如果现在的生活真的没有烦恼,那真的太好了. 但是事实并不是这样  而且永远也不会这样.  只要你有需求,你就要不时的和你不能忍受的人打交道 
我们已经慢慢不懂得怎样和陌生人打交道, 不懂得忍受他们刺耳的声音,还有白痴的幽默,不能忍受他们的体味还有吱嘎作响的鞋.
那么,什么才能令你走到外面这个世界,一个你不能控制,一个令你想尖叫的世界. 

Oh, yeah. Right in the crotch, buddy.

#2. 我们也没有足够的令人讨厌的朋友.

我们大部分人生活的地方都充满了我们不能容忍的人.   当你是小孩的时候,也许你就会发现,在你小学教室里,装满了很多和你兴趣爱好都不同的同学,而你又不能选择的同学. 也许你会经常感到失望. 


是,你已经长大了.  还有,如果你是一个忠实的DragonForce(英国某乐队)迷,你可以到他们的论坛上找到一大堆和你一样喜欢这个乐队的人.
或者更可以自己开一个私密的房间,只和你的好友在一齐,其他人都不能进来.  可以告别和兴趣真的不同的人打交道的烦人,无聊,痛苦的过程  
都是旧社会的问题,就像以前你要到河边洗衣服,或者要打猎穿兽皮.

问题是友好的解决人与人之间的矛盾,在社会上是很重要的生存之道.  事实上,如果你认真的想一下,你能友好的解决和你有矛盾的人的关系.,这就是所谓的社会.   只要和那些有不同思想,不同性格的人一起生活,合作,通常会存在摩擦.

50年前,你不得不坐在一个拥挤的房间里看一部电影  你根本不能选择,除非你不想看这部电影.  当你买了新车,街上所有的人都会站在你院子里看来看去.   你能肯定有些人里面有不少傻B.

Your parents, circa 1982

但是总的来说,那时的人还是对他们的工作感到高兴,对生活感到满足的.  是因为:他们比现在有更多的朋友. 

 没错. 虽然他们几乎都是不能根据共同兴趣来选择朋友,(靠,那时候只要是你邻居都是你朋友了啦.),但是他们仍然能有很多很要好的朋友,起码比现代人来说,那时候的人更值得相信.


就是说,很明显,
在你和别人发生第一次争吵,当你为争面子说:”他们不听我喜欢的歌,是他们不懂得欣赏.”之后,在某程度上,除了共同兴趣外,你们会感到互相熟悉了,这所
谓不打不相识. 那就是说,毕竟人都是需要社交的.   而那容忍别人和事的能力,就是你能正常生活在这充满和你不同的人的世界里唯一的保证.
否则,你会变另类.  这是有科学根据D… 

#3. 文字交流是一个很白痴的交流方式. 

我有个朋友会讽刺的说,”不用了,谢谢.”  他的意思是,”我宁愿死也不要”.他说最后两个字的时候带讽刺的味道,让你知道他的意思.  当你问他”想不想去看罗伯施奈德最新的电影?”他会说”不用了,谢谢.”

有一天,我们用这样的文字交流: 


我”喂,要不要试下剩下的红辣椒,我亲手做的啊.” 

他:”不用了,谢谢. ”

我看到就很生气.  我很喜欢我做的红辣椒  我都做了4天了.  是我自己磨的胡椒粉, 那牛肉也很贵,是手打牛肉.  而现在我的好意就让他这样恶毒地拒绝了.

后来我六个月不和他说话.  他之后发了封邮件给我,我看都不看就回了, 还装了个死老鼠在里面.

最后是我太太去找他弄清楚了他那句”不用了,谢谢.”并不是反话,是”真的不用了,很感谢你”,原来他的冰箱已经满了.

The Sad Bear #2, by Nedroid

所以我们是不是需要一个研究结果来告诉我们,你每写一封邮件,里面可能就有百分之四十的内容会令别人误会.  嗯,真的有人研究了. 


有多少没见过真人的网友?   当你们用文字交流的时候,有百分之四十内容不是真的表达你自己的意思,你觉得你们真的了解对方吗? 
有人因为你在留言板,聊天室或者其他什么地方的言论而不喜欢你,是不是你真的那么令人讨厌呢?  又或者,其实是因为这百分之四十的误会. 
还有,那些喜欢你的人呢? 

 我们很多人都在纯粹为了虚构好友量,在My Space 上积累了大批的所谓好友. 但是,问题来了. 

#4. 网络交友只会让我们更加寂寞. 

当人们面对面交流的时候, 说话的内容占了实际表达意思多少比例? 此外还有身体语言和声音语气.  猜一下。


只有百分之七.其余百分之九十三不是语言,是有研究得出的数据.  是的,我也不知道他们怎么算出来的.  他们有个机器吧.  但是我们不需要它 
我的意思是,醒醒吧.  我们很多幽默都是来自于讽刺,而讽刺就是说话的时候语气和内容不相符.  就像我朋友说的:”不用啦,谢谢.” 

你不用等一个女孩亲口说她喜欢你  她眼力的火花,她的姿态,她塞你的脸到她胸前的方式,都告诉你,她喜欢你. 

 这
就是问题的关键. 人类通过这种潜意识去理解别人情绪的能力是很重要的.   如果一个小孩天生没有这个能力,我们会认为他是智力有缺陷的
 如果有人的这个能力异常发达的话,我们称之为”魅力”,他极有可能成为电影明星和政治家. 不是因为他们说了什么,而是
他们散发出来的能量,令我们感觉良好.

当我们生活在文字世界里,所有的一切都没了.   还有一个奇怪的理论:由于缺少对别人情绪的理解,我们每看到一句话,都会从我们自己的情绪去理解它. 我之所以以为我那个朋友说的话是讽刺,是因为我那时候心情并不是很好. 带着那种情绪,我是希望能有人给我骂的. 

更糟糕的是,如果我继续这样聊下去,我的情绪不会改变.  毕竟,总有人说些我不愿意听的话. 
 当然我会很沮丧. 是我在和这个世界斗争!

不是这样的,我只是想有人能搭搭我肩膀,赶走我的不好情绪.  这就是我要说的第五点. 

#5. 我们受到的批评不够. 

 没有好朋友最糟糕的地方不是没有生日派对可以玩,不是自己凄凉的对着墙打乒乓球. 都不是,最糟糕的是缺少真正的批评 


上网的时候,别人叫我”同性恋”叫了几乎104.165次.  我就做了个Excel 表.  还有人叫我”混蛋”,”
鸡头黄鼠狼”,”日骆驼”,”阴道饼”,”吃屎的”,”猪肉刀”,”王八蛋”,”屎口哨”,”雷阴道”,”屁王”,”屎绒”,”瘤精灵”,”无聊”.
  (译者:-_-||….)


部都没关系,因为没有人真的了解我,能说中我.   我给人侮辱很多,但是给人批评非常少. 千万别搞乱这两个词.
 侮辱是指某个讨厌你的人发出的噪音去表达他们的不满. 一只会吠的狗.  批评是指有人想去帮助你,指出你自己都不知道的缺点. 

Above: A flamboyant transvestite with about

five times as many friends as the average person

 可悲的是,有非常多的人根本没有那样的谈话.  就好像”你知道吗,所有人都生你的气,就因为你昨晚说的话,但是没人敢告诉你,因为大家都害怕你了.”这样的话,这样真诚的话. 那些可怕的 ,笨拙的,悲痛的,不舒服的时刻,只有一些能看穿你的人会告诉你.


电子邮件和文字聊天是阻止真诚对话的有效工具.   用文字,当你喜欢的时候可以回复.  你可以评估你的话语.  你可以选择问题来回答. 
在网络另一头的人看不到你的脸,看不到你在紧张,察觉不出你在撒谎. 
 你几乎能控制一切,所以,没人能撕下你的面具,永远看不到你的缺点,永远不知道你所做过的蠢事.
 怪癖,丢脸,缺点这些组成友谊关系的重要元素,都消失了.

 浏览一下人们在My Space的页面,看看他们为自己而虚构的人物性格.  如果你通过写博客,已经把自己塑造成一个神秘的夜游大师,的确很难让你说出事实你是怎样去那个舞会,还有在舞池上腹泻. 你永远不能做真正的自己, 那是一种非常寂寞的感觉

总的来说……

#6. 我们是现代机器的牺牲品. 

看这文章的一大部分人都会说,”我就是很沮丧.”   人们都饿坏了! 美国变成了德国纳粹时代.  我父母在看完白痴电视节目后还要继续讨论几个小时.  世界上的人们正在死于一些毫无意义的战争. 


是,我们是怎样从一个比我们老一辈日子更负面的世界里 发奋? 或者说更老一辈.  回到那个时候,人没有那么长命,婴儿也经常早死. 
疾病是更普遍  在那时候,如果你的好友搬走了,你们唯一的联络方法就是一支笔,一张纸和一张邮票. 
我们现在有伊拉克,但是老一辈有越南(比伊拉克死多50倍人) ,再老一辈有第二次世界大战(比伊拉克死多1000倍人)
 你们的祖父是生长在一个没有空调的时代.

在各个方面,我们自然比以前生活的更好,但是TMD网上的新闻都不知道是真的假的.  Why?

你问问你自己,如果有个音乐网站发了篇文章叫” Fall Out Boy是一支不错的乐队”,同一天还有另外一篇文章叫”专家说,Fall Out Boy是TMD一百年里最垃圾的乐队.”你猜哪篇文章会更热门.  第二篇肯定火了. 夸张制造口碑. 


看了多少写新闻的博客  写这个的人都知道一个事实. 
 每个网站都像狗和狗打架似的在争流量,(就算他们网站没有广告,他们会觉得多人看就满足了.)所以他们都会选一些奇怪的,激动的事情来写.
其他的网站开始模仿同样的手法.  你愿意的话,你可以在这充满温暖的不流动的的水的池塘里游一整天,(意思是看一天都是垃圾新闻)

Actually, if you count the guy holding the camera, this man

statistically has more friends than most of us do.

 只有在这样的环境下,才会有那白痴的911阴谋论出现(说是布什主脑的,由FDNY炸毁大厦,还有那飞机是全息图.) 他们都说,每个说反对的政治家都是希特勒,每个选举都是怪异的启示录.  都是为了让你去阅读 

9/11 photos. Circled: Conspiracy


然这些在以前是不会发生的.   我们中的一些人会记得那时候电视只有3个台. 没错.  三个.  我现在说的是80后. 
 所以有些东西都统一了,我们都看同样的新闻,都是同样的观点. 就算这些观点是弱智还有错的,
就算有些新闻是因为违法而不能报道的,我们都能分享它.


完了. 
 肯定是不会再有”混合媒体”的了,以前我们有异议是因为看了相同的新闻但是有不同的理解,现在我们有异议是因为我们看的是完全不同的奇怪的新闻.
 当我们连基本的真相都不能认同的时候,小小的不同就成了很大的矛盾.  那持续的点点优越感带来了不断的紧张和不安.

过去我们人类有很多天生的方法来释放这种焦虑。  但如今…


#7.  我们觉得生活没有价值,因为我们确实没有价值。

去找更多的在线朋友,这有个好处,而且是没人会谈到:

 他们对你几乎没有要求。


 的确,当他们有失恋时,你可以从感情上帮助他们,安慰他们,甚至能将他们从自杀的冲动中解救出来。  但现实世界的人们会强加你一大堆的讨厌的要求。
 浪费你整个下午去给他们修电脑。  跟他们一起去参加葬礼。  用你的车带着他们四处奔走,直到他们从银行哪里拿回自己的东西。
 正当你收拾好了要看Discovery频道的 Dirty Jobs
马拉松时,他们不请自来,而且告诉你他们如此的饥饿,直到把你的三明治分给他们一半。

 然而在聊天工具里,或论坛里,或魔兽争霸里,你却能有更多的支配权。


 问题就在这,由于人类进化的原因,你和社会已经绑在一起了,你需要为他人做些服务。  五千年来,每个都明白这些,然而就在近十年,人们却忘了。
 十几岁的孩子就有自杀心理,于是我们争先恐后的去教他们自爱,自尊。
 然而,不幸的是,这自尊和自爱只有当做了能让自己喜欢的事情后才会产生。这可不是胡说八道。
 如果那个Todd整体待在屋里,喝着百事,一只手玩着视频游泳,另一只手在手淫,我会认为他在做毫无价值的事情,但如果是我在做这些事情,我又会怎么认
为自己呢?

The Sad Bear #3, by Nedroid

 你能够把那些导致自卑的黑药丸丢掉吗?  收拾一下盖住眼睛的头发,从电脑面前走开,给你讨厌的人买一个礼物。  给你最大的死对头送张卡片。  给你的父母做顿晚餐。  或者简单做一些东西,一些真实存在的东西。  清扫屋檐下的落叶。  收拾一下快要死的花草。

 这
些都是简单易做的事情;人是一个社会性的动物,你出生时身体里就带有一点快乐荷尔蒙激素。当你看到自己的活动产生了实际存在的价值时,它就会释放到你的血
液里。  想想那些十几岁的孩子,在黑屋子里,抱着电脑,把他们的所有生活问题全都幻化到可笑的游戏、戏剧情节里。
 为什么他们会在自己的臂膀上能出那些小伤口?  因为这样可以能出疼痛—之后又能愈合—这是他们唯一能刺激体内的多肽激素的方法。
 这是疼痛,但至少是真实的。


 这种通过一些适度的困难任务来调节压力的办法过去曾是日常生活的一部分,例如猎捕羚羊,摘草莓,攀岩,猎捕熊。  不为别的。
 这就是整天坐在办公室工作里会让如此多的人感到难受;我没有获得任何实在的、有形的产出。
 在火热的太阳底下花两个月时间盖个建筑,余生里每当你开车经过这个建筑时你都可以说,“看看,我盖的。”这也许就是办公室里的枪击事件比工地里要常见的
多的原因。

 这种体力上的,手工劳动获得的快感只有在你关掉计算机,走出家门,重新融入真实社会后才能获得。  这种感觉,这种“我建的”或“我喂养的”或“我种的”或“我制作的这些裤子”的感觉是任何网络给你的东西都不能相比的。

  当然,除了这篇文章能给你的

0

slideshare 服务中断


在北京,此网站无法访问。

Something went wrong!

This is probably a temporary error.

504 Error

0

PHP招聘信息-PHP/MySQL DEVELOPER-TORONTO


Divaris Alexander Corporation is looking for an experienced to contribute as a contractor in the current development of our based property tax platform.
Duties/ Responsibilities:
Database Modeling.
Preparation of application architecture.
Design and implement application.
We are looking for a well-organized, conscientious person with skills in PHP programming and a working knowledge of . You will be required to interact with our team and deploy the application features quickly, maintaining quality and reliability.
Experience required:
Organizations Skills
Communication Skills (oral and written in English)
Understanding of standards
Working knowledge of XML, CSS and
PHP 4 and 5 (4 years +)
MySQL 4.11 and 5.1 (4 years +)
Additional Skills:
Working knowledge in a Environment
Knowledgeable in database modeling and tools(programs)
Flex 2 or 3 and
Coldfusion
Based in , Divaris Alexander Corporation, incorporated in 1987, provides property assessment and municipal tax consulting services for industrial, commercial, investment and special use property owners and occupants.
We require that you be based in Toronto and able to work onsite.
Apply via email to info[at]dival.com

01

Internet Explorer Toolbar (Deskband) Tutorial


转至http://www.codeproject.com

The Motley Fool Quote IE Toolbar

Introduction

Having recieved a number of requests for a tutorial of sorts on developing Internet Explorer Toolbars with the RBDeskband and CWindowImpl wizards that I created, I have come up with a simple sample toolbar which can be used as a reference when developing your own toolbars or explorer bars. The tutorial will walk you through the stages of developing a toolbar for IE that is very similar to the Address bar that is already present in IE. I wanted to do a tutorial that would provide a realistic sample and would produce an end result that could be used by others after the tutorial was finish. So, the tutorial is going to show you how to develop an IE toolbar to get stock quote information from The Motley Fool website. So with that, let us get started.

Prequisites

This tutorial assumes that you already know how to program in C++ and know some information about ATL and COM. To work through this tutorial, you will need the following installed on your development machine:

  • Visual C++6 installed
  • RBDeskBand ATL Object Wizard (Version 2.0) [get it here]
  • CWindowImpl ATL Object Wizard [get it here]

The Framework

The IE toolbar consists of a COM component supporting IDeskband and a few other necessary interfaces for which IE looks for when loading registered toolbars, explorer bars and deskbands. The RBDeskband ATL Object Wizard provides most of the framework for this article. What we will need to do is create our project, a new COM object to house our toolbar, and a few CWindowImpl classes using the CWindowImpl ATL Object Wizard. Then connecting these parts together we will produce the IE toolbar in the picture at the top of the article. Visually the toolbar consists of an editbox and a toolbar with one button on it. In actuality the toolbar consists of the fore mentioned and a non visible window that is used to reflect messages to the Toolbar window, which will process or forward messges to itself and the edit box.

Creating The

We will not work through the steps in creating the shell for our toolbar.

Creating The Project

  • If you have not done so already, start Visual C++6.
  • Then, from the File menu select New menu item; the New Dialog pops up.
  • In the New Dialog, select the Projects tab, if not already selected.
  • Select ATL COM AppWizard from the list view, if not already selected.
  • In the Project name, type "MotleyFool". See Figure 1.
  • Click the OK Button.

Figure 1. New Dialog.
Figure 1. New Dialog.
  • The ATL COM AppWizard will kick in.
  • Clicking the Finish Button, accepting the default AppWizard attributes. See Figure 2.
  • The New Project Information Dialog will present itself requesting confirmation of your project settings.
  • Click the OK Button.

Figure 2. ATL COM AppWizard
Figure 2. ATL COM AppWizard.

Creating The DeskBand Object

Now that we have our project container we need to add our IDeskBand derived component so that the DLL actually exposes something.

  • From the Insert menu, select New ATL Object menu item; the ATL Object Wizard dialog is invoked.
  • In the ATL Object Wizard dialog, select the RadBytes Category. If this category is missing then make sure that the RBDeskband and CWindowImpl ATL Object Wizards are installed.
  • Next select the DeskBand item from the Objects list.
  • Click the Next button to invoke the ATL Object Wizard Properties dialog for the Deskband object. See Figure 3.
  • On the Names property page, type "StockBar" into the Short Name field. See Figure 4.
  • Select the DeskBand ATL Object Wizard property page
  • Check the Internet Explorer Toolbar checkbox. See Figure 5.
  • Click the OK button on the ATL Object Wizard Properties Dialog. The ATL Object Wizard will create the files necessary for our DeskBand’s base implementation.

Figure 3. ATL Object Wizard.
Figure 3. ATL Object Wizard.
Figure 4. ATL Object Wizard Properties - Names.
Figure 4. ATL Object Wizard Properties – Names.
Figure 5. ATL Object Wizard Properties - DeskBand ATL Object Wizard.
Figure 5. ATL Object Wizard Properties – DeskBand ATL Object Wizard

Now our project has the DeskBand implementation that we will modify to produce the toolbar pictured at the top of the article. First we will create the window classes we will need and then come back to the Desbkand object and update it to use our window classes.

Creating The Window Classes

So back in the Framework section we said that we would need three window classes. One for the Edit Box, one for the toolbar, and one for message reflection back to the toolbar. Let us now create these window classes.

The Edit Window

We need to create a derived from the standard EDIT button window because we are going to be adding methods to our to help support functionality of the toolbar. This is one reason why we cannot use a CContainedWindow object directly.

  • From the Insert menu, select New ATL Object menu item; the ATL Object Wizard dialog is invoked.
  • In the ATL Object Wizard dialog, select the RadBytes Category. If this category is missing then make sure that the RBDeskband and CWindowImpl ATL Object Wizards are installed.
  • Next select the CWindowImpl item from the Objects list.
  • Click the Next button to invoke the ATL Object Wizard Properties dialog for the Deskband object. See Figure 3.
  • On the Names property page, type "EditQuote" into the Short Name field.
  • Select the CWindowImpl property page. See Figure 6.
  • Select the SUPERCLASS radio button from the DECLAR_WND_* group.
  • In the Window Class Name field, type "EDITQUOTE".
  • In the Original Class Name list, select the EDIT listbox item. See Figure 7.
  • Click the OK button on the ATL Object Wizard Properties Dialog. The ATL Object Wizard will create the files necessary for our CWindowImpl derived class implementation.

Figure 6. ATL Object Wizard Properties - Names.
Figure 6. ATL Object Wizard Properties – Names.
Figure 7. ATL Object Wizard Properties - Names.
Figure 7. ATL Object Wizard Properties – CWindowImpl.

The Toolbar Window

We need to create a derived class from the standard TOOLBARCLASSNAME window class because we are going to be adding methods to our class to help support functionality of the toolbar. It will also be the parent for the edit box and the window which the IE host will request from our DeskBand.

  • From the Insert menu, select New ATL Object menu item; the ATL Object Wizard dialog is invoked.
  • In the ATL Object Wizard dialog, select the RadBytes Category. If this category is missing then make sure that the RBDeskband and CWindowImpl ATL Object Wizards are installed.
  • Next select the CWindowImpl item from the Objects list.
  • Click the Next button to invoke the ATL Object Wizard Properties dialog for the Deskband object. See Figure 3.
  • On the Names property page, type "MFToolbar" into the Short Name field.
  • Select the CWindowImpl property page. See Figure 8.
  • Select the SUPERCLASS radio button from the DECLAR_WND_* group.
  • In the Window Class Name field, type "MOTLEYFOOLTOOLBAR".
  • In the Original Class Name list, select the TOOLBARCLASSNAME listbox item. See Figure 9.
  • Click the OK button on the ATL Object Wizard Properties Dialog. The ATL Object Wizard will create the files necessary for our CWindowImpl derived class implementation.

Figure 8. ATL Object Wizard Properties - Names.
Figure 8. ATL Object Wizard Properties – Names.
Figure 9. ATL Object Wizard Properties - Names.
Figure 9. ATL Object Wizard Properties – CWindowImpl.

The Reflection Window

We need to create a reflection window. It’s just a CWindowImpl window implmented class. We are going to be adding a small bit of functionality just to create the toolbar object and be able to access the toolbar member from our deskband class.

  • From the Insert menu, select New ATL Object menu item; the ATL Object Wizard dialog is invoked.
  • In the ATL Object Wizard dialog, select the RadBytes Category. If this category is missing then make sure that the RBDeskband and CWindowImpl ATL Object Wizards are installed.
  • Next select the CWindowImpl item from the Objects list.
  • Click the Next button to invoke the ATL Object Wizard Properties dialog for the Deskband object. See Figure 3.
  • On the Names property page, type "ReflectionWnd" into the Short Name field. See Figure 10.
  • We will not change any of the CWindowImpl property page values this time.
  • Click the OK button on the ATL Object Wizard Properties Dialog. The ATL Object Wizard will create the files necessary for our CWindowImpl derived class implementation.

Figure 10. ATL Object Wizard Properties - Names.
Figure 10. ATL Object Wizard Properties – Names.

Adding The Details

Now that we have our window classes available we can add our functionality for our toolbar to the appropriate window classes. Let us start with the deepest window class and work our way back out.

The EditQuote Details

For the EditQuote implementation, we need to be able to process keystrokes from the user and let the host that created our deskband object know our edit box has focus. To accomplish the first part, we need to look ahead and see that our DeskBand object will be implementing the IInputObject interface. So the host will query for that interface and know that we want to recieve messages and be given the chance to recieve focus. When the host sends our band messages to process they come through the IInputObject::TranslateAccelerator method. Our DeskBand will implement this method and it is best if our edit box, which will process the message, copy the TranslateAcceleratorIO method definition so our deskband can forward the message easily through a logical method call.

Figure 11. FileView Pane.
Figure 11. FileView Pane.

In the FileView pane (See Figure 11), double click the EditQuote.h item under Header Files. This will open the header file in the editing area. We now need to define the method definition for TranslateAcceleratorIO. To do this, add below the virtual CEditQuote destructor the following line of code:

STDMETHOD(TranslateAcceleratorIO)(LPMSG lpMsg);

Now Open the EditQuote.cpp source file and add the implementation of TranslateAcceleratorIO to the file

STDMETHODIMP CEditQuote::TranslateAcceleratorIO(LPMSG lpMsg){   TranslateMessage(lpMsg);   DispatchMessage(lpMsg);   return S_OK;}

Now our DeskBand implementation can call this message and the edit box will process the key strokes properly. But wait, our edit box should notify the toolbar to load the quote details entered if the key stroke is the enter key. For this, we will need to define a message id and send that message to the parent window to process. In the EditQuote.h header file below the include statement, add the definition of our message id as shown below in bold.

#include <commctrl.h>const int WM_GETQUOTE = WM_USER + 1024;			

In our EditQuote.cpp file we will add code to our TranslateAcceleratorIO method to process the enter key. Add the code below in bold to the EditQuote.cpp file.

STDMETHODIMP CEditQuote::TranslateAcceleratorIO(LPMSG lpMsg){   int nVirtKey = (int)(lpMsg->wParam);   if (VK_RETURN == nVirtKey)   {      // remove system beep on enter key by setting key code to 0      lpMsg->wParam = 0;      ::PostMessage(GetParent(), WM_GETQUOTE, 0, 0);      return S_OK;   }   TranslateMessage(lpMsg);   DispatchMessage(lpMsg);   return S_OK;}

Now our edit box will notify the parent when the user presses the enter key so that the parent can retrieve the requested ticker symbol details, this part will be implemented when we get to the toolbar details.

The first part of the Edit boxes implementation is finished. Now we need to be able for the edit box to have the deskband notify the host that we have focus or that we don’t have focus any longer. To do this we will need to add a method for the deskband to pass us it’s address so that we can call a method of the deskband class. These next steps will involve adding code to the CEditQuote class and to our Deskband class implementation.

Open the EditQuote.h file and add a forward reference to the CStockBar class so that we can defined our methods and members in our class header without knowing the implementation details of our deskband class, add the line in bold.

#include <commctrl.h>const int WM_GETQUOTE = WM_USER + 1024;class CStockBar;

For our class to notify the host that our deskband has focus, we need to add a message handler for EN_SETFOCUS. Add the command code handler code below in bold to your EditQuote.h file.

   BEGIN_MSG_MAP(CEditQuote)      COMMAND_CODE_HANDLER(EN_SETFOCUS, OnSetFocus)   END_MSG_MAP()

Then add the method definition for OnSetFocus to the header file below the commented out handler prototypes as follows below in bold.

// Handler prototypes:// LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);// LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);// LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);   LRESULT OnSetFocus(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);

Before we implement the OnSetFocus method, we need to define a method for our deskband to tells of it’s address and to retain that address for later use. Add the following lines of code to your EditQuote.h file below the TranslateAcceleratorIO definition.

   void SetBand(CStockBar* pBand);private:   CStockBar* m_pBand;

Now we can move to your EditQuote.cpp source file and implement the message handler, the SetBand method, and update the TranslateAcceleratorIO method for focus change. At the top of the EditQuote.cpp file add the following includes to the include list as shown below in bold.

#include "stdafx.h"#include "EditQuote.h"#include "MotleyFool.h"#include "StockBar.h"

Now when we can use the methods of the CStockBar class in our code. Add to the end of the constructor, the initalization of m_pBand. Don’t forget the colon operator.

CEditQuote::CEditQuote(): m_pBand(NULL){}

Next we will add the SetBand implementation to our CEditQuote class. Notice that since it is not a com object we don’t call AddRef or Release on it. It’s just a pointer to the class and when it’s destroyed our CEditQuote instance will also be destroyed. We could have also done this inline in our header file.

void CEditQuote::SetBand(CStockBar* pBand){   m_pBand = pBand;}

Next we need to add our message handler for our EN_SETFOCUS message. Add the code below to the end of the EditQuote.cpp source file.

LRESULT CEditQuote::OnSetFocus(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled){   //Notify host that our band has the focus so TranslateAcceleratorIO    //messages are directed towards our band.   if (m_pBand) m_pBand->FocusChange(TRUE);   return 0;}

We have one more section of code to add to our CEditQuote implementation then we can move to our CStockBar class to define and implement the FocusChange method. Add the following code to the CEditQuote TranslateAcceleratorIO method as shown in bold. We add this code so the host knows that we are no longer needing messages.

STDMETHODIMP CEditQuote::TranslateAcceleratorIO(LPMSG lpMsg){   int nVirtKey = (int)(lpMsg->wParam);   if (VK_RETURN == nVirtKey)   {      // remove system beep on enter key by setting key code to 0      lpMsg->wParam = 0;      ::PostMessage(GetParent(), WM_GETQUOTE, 0, 0);      return S_OK;   }   else if (WM_KEYDOWN == lpMsg->message && nVirtKey == VK_TAB)   {      // we no longer need messages forwarded to our band      if (m_pBand) m_pBand->FocusChange(FALSE);      return S_FALSE;   }   TranslateMessage(lpMsg);   DispatchMessage(lpMsg);   return S_OK;}

Open the StockBar.h header file and add the definition of FocusChange to it as shown below in bold.

// IStockBarpublic:   void FocusChange(BOOL bHaveFocus);

Now open the StockBar.cpp source file and add the implementation of FocusChange to it at the bottom.

void CStockBar::FocusChange(BOOL bHaveFocus){   if (m_pSite)   {      IUnknown* pUnk = NULL;      if (SUCCEEDED(QueryInterface(IID_IUnknown, (LPVOID*)&pUnk)) && pUnk != NULL)      {         m_pSite->OnFocusChangeIS(pUnk, bHaveFocus);         pUnk->Release();         pUnk = NULL;      }   }}

We have finished off the work needed for the edit box to work properly in our toolbar. Now we need to build our toolbar up so that it has a button and contains our edit box. Then we will add the nessecities to our reflection window and update our IDeskBand to provide the correct information to our host. We are almost there. If you were to compile the project and run it, it would except that the band would look like the following in figure X.

The MFToolbar Details

For the implementation of the MFToolbar window, we need to be able to have it do the following things. It must be able to process the WM_GETQUOTE message from the EditQuote window, communicate with the browser in which the toolbar is located, create the buttons and place the child on itself, forward messages to the EditQuote child window and size itself appropriately to the users actions.

So, the first thing we should do since our toolbar is going to contain an instance of CEditQuote is include the header file for the CEditQuote class. We will do this by opening the MFToolbar.h file and inserting the include statement for the CEditQuote class as shown in bold below.

#include <commctrl.h>#include "EditQuote.h"		

Next we need to add a member to our toolbar class for the CEditQuote class. We will do this by adding a private section to the end of our class and defining a member variable as shown below in bold.

   CMFToolbar();   virtual ~CMFToolbar();private:   CEditQuote m_EditWnd;

Now that we have our member defined for our EditQuote window, we need to forward window messages to it so that keyboard inputs are processed appropriately. We do this by updating the toolbar message map to chain messages to our member as shown below in bold.

   BEGIN_MSG_MAP(CMFToolbar)      CHAIN_MSG_MAP_MEMBER(m_EditWnd)   END_MSG_MAP()

Looking forward, our deskband will need to get the EditQuote member to deterimine if it has focus and also to make it function. We could just expose the EditQuote member directly by having made it a public member instead of private, but by making it private we can expose a method that will expose our member giving us flexibility later to modify the class if the need should arise. So to expose the EditQuote member, we will add a fuction to our toolbar class to return the reference to the EditQuote member. In the toolbar header file, add the method definition and implementation below in bold to it.

   CMFToolbar();   virtual ~CMFToolbar();   inline CEditQuote& GetEditBox() {return m_EditWnd;};

Now we will create our toolbar window. Our toolbar consists of the EditQuote box and a button with an icon and text on it. To house the icon, our toolbar will need an image list handle to send to the toolbar window. So we need to add a few things to our toolbar header file before we go and implement the toolbar’s creation. The first thing we will add is the member variable for our image list. Add the line in bold below to your toolbar header file.

private:   CEditQuote m_EditWnd;   HIMAGELIST m_hImageList;

Then we will add a message handler to our toolbar’s message map and define the message handlers function definition to our header file and the follow lines of code in bold to your header file.

   BEGIN_MSG_MAP(CMFToolbar)      CHAIN_MSG_MAP_MEMBER(m_EditWnd)      MESSAGE_HANDLER(WM_CREATE, OnCreate)   END_MSG_MAP()// Handler prototypes://  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);   LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

Before we can implement our toolbar’s creation, we need to create a icon resource that our toolbar button will use next to its text. So go to the resource view and add a new icon to the project resources. You can do this by right clicking on "MotleyFool resources" and selecting "Insert…" from the context menu. In the Insert Resource dialog box, select Icon from the Resource type list and click the New button. This will insert a blank icon resource into your project. Rename the icon’s resource ID by right clicking on the icon resource in the resource view and selecting the properties menu item from the context menu. Change the id to IDI_MOTLEY. Then draw or graciously borrow an icon from The Motley Fool to use on the toolbar. I graciously borrowed the icon from their website and adapted it into the icon.

Now we can implement it our toolbars creation. Open the MFToolbar source file and implement the details of the toolbar creation as described below.

First we need to include the project resource file so we can use the icon ID in our code. Add the line in bold below to our toolbar’s source file as shown.

#include "stdafx.h"#include "resource.h"#include "MFToolbar.h"

Next we need to update our constructor implementation. We need to initialize our handle to the image list by setting it to NULL. Don’t forget the colon.

CMFToolbar::CMFToolbar(): m_hImageList(NULL){}

Next we need to update our destructor, it should destroy the image list and destroy the window if it has not yet been destroyed.

CMFToolbar::~CMFToolbar(){   ImageList_Destroy(m_hImageList);   if (IsWindow()) DestroyWindow();}

Before we can implement our toolbar’s creation, we need to add a resource symbol to our project for the toolbar button’s ID. We could just use a #define statement at the top of the source file, but for cleanliness and since we are already including the resource.h file, we will add it to our resource file. Go to the "View" menu and select "Resource Symbols" menu item. Click the "New" button on the Resource Symbols dialog. Then enter a name of "IDM_GETQUOTE" and click OK. Then close the Resource Symbols dialog.

Now we can create our toolbar, we defined the OnCreate method in our header file and need to now implement it. Add the following function and its implementation to the end of the toolbar source file.

Collapse
LRESULT CMFToolbar::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){   // buttons with images and text   SendMessage(m_hWnd, TB_SETEXTENDEDSTYLE, 0, (LPARAM)TBSTYLE_EX_MIXEDBUTTONS);   // Sets the size of the TBBUTTON structure.   SendMessage(m_hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);   // Set the maximum number of text rows and bitmap size.   SendMessage(m_hWnd, TB_SETMAXTEXTROWS, 1, 0L);   // add our button's caption to the toolbar window   TCHAR* pCaption = _T("Get Quote");   int iIndex = ::SendMessage(m_hWnd, TB_ADDSTRING, 0,(LPARAM)pCaption);   // load our button's icon and create the image list to house it.   HICON hMotley = LoadIcon(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDI_MOTLEY));   m_hImageList = ImageList_Create(16,16, ILC_COLOR16, 1, 0);   int iImageIndex = ImageList_AddIcon(m_hImageList, hMotley);   DestroyIcon(hMotley);   // Set the toolbar's image   ::SendMessage(m_hWnd, TB_SETIMAGELIST, 0, (LPARAM)m_hImageList);   // add the button for the toolbar to the window   TBBUTTON Button;   ZeroMemory((void*)&Button, sizeof(TBBUTTON));   Button.idCommand = IDM_GETQUOTE;   Button.fsState = TBSTATE_ENABLED;   Button.fsStyle = BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT;   Button.dwData = 0;   Button.iString = iIndex;   Button.iBitmap = 0;   ::SendMessage(m_hWnd, TB_INSERTBUTTON, 0, (LPARAM)&Button);   // create our EditQuote window and set the font.   RECT rect = {0,0,0,0};   m_EditWnd.Create(m_hWnd, rect, NULL, WS_CHILD|WS_VISIBLE, WS_EX_CLIENTEDGE);   m_EditWnd.SetFont(static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT)));   return 0;}

If you try to compile at this point, you will see that there are unresolved externals for the image list method calls. We need to add a library to the project. To do this select the "Project|Settings" menu item. On the Project Settings dialog, Select All Configurations from the "Settings For" combo box. Then select the "Link" tab and append to the "Object/Library modules" edit box "comctl32.lib". Then click OK. If you compile the project now, it will compile successfully and the image list unresolved externals will disappear.

We still have a few things we need to do to the Toolbar window. It needs to process Command messages, resopnd to WM_GETQUOTE messages, and resize itself. Let’s conquer the latter first.

To orgainze the tooblar correctly, we should have the toolbar responsd to WM_SIZE messages. To do this, we will add to our tooblar header file a message handler for the WM_SIZE message and add a function definition for OnSize which WM_SIZE messages will be sent to. Open our toolbar header file and add the lines in bold below to it as shown.

   BEGIN_MSG_MAP(CMFToolbar)      CHAIN_MSG_MAP_MEMBER(m_EditWnd)      MESSAGE_HANDLER(WM_CREATE, OnCreate)      MESSAGE_HANDLER(WM_SIZE, OnSize)   END_MSG_MAP()// Handler prototypes://  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);   LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);   LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

Now we need to implement our OnSize function. Open the toolbar source file and add the function implementation below to the end of the file.

Collapse
LRESULT CMFToolbar::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){   // based on the size of the window area minus the size of the toolbar button,    // indent the toolbar so that we can place the edit box before the toolbar    // button. This will right justify the toolbar button in the toolbar and the    // edit box will use the vaction space to the left of the button but after the    // toolbar text as it's usable space.   RECT wndRect, btnRect;   GetClientRect(&wndRect);   ::SendMessage(m_hWnd, TB_GETITEMRECT, 0, (LPARAM)&btnRect);   wndRect.right -= (btnRect.right - btnRect.left);   SendMessage(TB_SETINDENT, wndRect.right - wndRect.left);   // put a small spacing gap between the edit box's right edge and the toolbar button's left edge   wndRect.right -= 3;   m_EditWnd.MoveWindow(&wndRect, FALSE);   return 0;}

We still need to respond to user input for the toolbar button and from the edit box when the user presses the enter key. What we want the toolbar to do is tell the web browser host to navigate to the motely fool website and retrieve the stock quotes requested. First we need for the Deskband object to tell our toolbar window what the web browser instance is so that the toolbar window can communicate with it. To do this, we will add a private member variable and a public method in which the deskband can set the web browser instance. Our window will then use the member variable set to tell the web browser where to navigate and what to retrieve.

To do this, open the toolbar header file and add the lines in bold to the file.

   CMFToolbar();   virtual ~CMFToolbar();   inline CEditQuote& GetEditBox() {return m_EditWnd;};   void SetBrowser(IWebBrowser2* pBrowser);private:   CEditQuote m_EditWnd;   HIMAGELIST m_hImageList;   IWebBrowser2* m_pBrowser;

Now, open the toolbar source file. We will update the constructor and initialize our member variable to null. Then we will update the toolbar destructor and release the member variable if it hasn’t been. Then we will implement the SetBrowser method.

Initialize the web browser member variable.

CMFToolbar::CMFToolbar(): m_hImageList(NULL), m_pBrowser(NULL){}

Release the web browser object if held.

CMFToolbar::~CMFToolbar(){   ImageList_Destroy(m_hImageList);   SetBrowser(NULL);   if (IsWindow()) DestroyWindow();}

Implement SetBrowser()

void CMFToolbar::SetBrowser(IWebBrowser2* pBrowser){   if (m_pBrowser) m_pBrowser->Release();   m_pBrowser = pBrowser;   if (m_pBrowser) m_pBrowser->AddRef();}

If you try and compile the project, you will notice that IWebBrowser2 is undefine in our header file. This is because we need to update our stdafx.h header file to include system files that define IWebBrowser2. To do this, open stdafx.h and add the following lines in bold to the file, then recompile.

extern CComModule _Module;#include <atlcom.h>#include <atlwin.h>//// These are needed for IDeskBand//#include <shlguid.h>#include <shlobj.h>

Now we can add message handlers for WM_COMMAND and WM_GETQUOTE to our toolbar class to handle the toolbar button being pressed and the enter key being pressed in the edit box by the user. To do this, we will need to add to our toolbar header file message handlers and function definitions for WM_COMMAND and WM_GETQUOTE. We will also need to add a private method which both will call if they need to to preform the same functionality (better than repeating code that does the same thing). So let’s add the message handlers to the header file.

Collapse
   BEGIN_MSG_MAP(CMFToolbar)      CHAIN_MSG_MAP_MEMBER(m_EditWnd)      MESSAGE_HANDLER(WM_CREATE, OnCreate)      MESSAGE_HANDLER(WM_SIZE, OnSize)      MESSAGE_HANDLER(WM_COMMAND, OnCommand)      MESSAGE_HANDLER(WM_GETQUOTE, OnGetQuote)   END_MSG_MAP()// Handler prototypes://  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);   LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);   LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);   LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);   LRESULT OnGetQuote(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

Now we can add the function delcaration for our GetQuote privaet method.

private:   CEditQuote m_EditWnd;   HIMAGELIST m_hImageList;   IWebBrowser2* m_pBrowser;   void GetQuote();

Now let’s switch to our source file and implement our message handler functions and the GetQuote method. Add the code below to the end of the toolbar source file.

Collapse
LRESULT CMFToolbar::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){   if (!HIWORD(wParam))   {      long lSite = LOWORD(wParam);      if ( lSite == IDM_GETQUOTE)      {         GetQuote();         return 0;      }   }   return -1;}LRESULT CMFToolbar::OnGetQuote(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){   GetQuote();   return 0;}void CMFToolbar::GetQuote(){   // if we have a web browser pointer then try to navigate to The Motley Fool site to retrieve stock quotes.   if (m_pBrowser)   {      VARIANT vEmpty;      VariantInit(&vEmpty);      m_pBrowser->Stop();      _bstr_t bsSite;      // if the user has entered stock quotes then append them to the url      if (m_EditWnd.GetWindowTextLength())      {         BSTR bstrTickers = NULL;         m_EditWnd.GetWindowText(&bstrTickers);         bsSite = "http://quote.fool.com/news/symbolnews.asp?Symbols=";         bsSite += bstrTickers;         SysFreeString(bstrTickers);      }      // if the user has not entered any stock quotes then just take them to The Motley Fool website.      else         bsSite = "http://www.fool.com";      // have the webrowser navigate to the site URL requested depending on user input.      m_pBrowser->Navigate(bsSite, &vEmpty, &vEmpty, &vEmpty, &vEmpty);   }}

If you try to compile, you will notice that _bstr_t is undefined. That is because the class is defined in comdef.h. We need to add this to our stdafx.h header file so that we can use it as well as any other class in our project (which we will need to for IInputObject). Open the stdafx.h header file and add the lines in bold to the file as indicated.

#include <shlobj.h>// needed for IInputObject and _bstr_t#include <comdef.h>

Our implementation of the toolbar window is complete. Now we can move on to the Reflection window which creates our toolbars and forwards command messages to it.

The Reflection Window Details

For the Reflection Window, it’s only purpose is to create the toolbar window (which it doesn’t need to really do, but by doing so eases message forwarding) and forward messages to it. The reflection window is not visible, it’s just a layer added so that message from the toolbar get to the toolbar. If we didn’t have this window present, toolbar messages would get sent to the parent window (which we do not control) and we would never get them. This is not good since we need to respond to WM_COMMAND messages from the toolbar. Thus the need for the reflection window. So let’s create the toolbar window and the message forwarding for it.

Open the ReflectionWnd.h header file. We will need to include the toolbar header file and add a private member variable to our reflection window to create it and to pass it to the message chain. First things first, add the include statement below so we can use the CMFToolbar class.

#include <commctrl.h>#include "MFToolbar.h"

Next add a private member variable to the end of the reflection window class for the toolbar as shown below.

	CReflectionWnd();   virtual ~CReflectionWnd();private:   CMFToolbar m_ToolbarWnd;

Next update the reflection window message map to forward messages to the toolbar window as shown below.

   BEGIN_MSG_MAP(CReflectionWnd)      CHAIN_MSG_MAP_MEMBER(m_ToolbarWnd)   END_MSG_MAP()

We will also need a public function for our deskband class to get at our toolbar window. We will do the same as we did with the EditQuote window by providing a function to get at the member variable indirectly. Add the line of code in bold below to the header file as indicated.

   CReflectionWnd();   virtual ~CReflectionWnd();   inline CMFToolbar& GetToolBar() { return m_ToolbarWnd;};

Lastly, we need to create the toolbar window and will do so in the WM_CREATE message handler for our reflection window. Add the code below in bold to the reflection window header file. Then we will implement the OnCreate method in the source file.

   BEGIN_MSG_MAP(CReflectionWnd)      MESSAGE_HANDLER(WM_CREATE, OnCreate)      CHAIN_MSG_MAP_MEMBER(m_ToolbarWnd)   END_MSG_MAP()// Handler prototypes://  LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);//  LRESULT CommandHandler(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);//  LRESULT NotifyHandler(int idCtrl, LPNMHDR pnmh, BOOL& bHandled);   LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

Now open the ReflectionWnd.cpp source file and add the implementation of OnCreate to its end.

const DWORD DEFAULT_TOOLBAR_STYLE =       /*Window styles:*/ WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | WS_TABSTOP |      /*Toolbar styles:*/ TBSTYLE_TOOLTIPS | TBSTYLE_FLAT | TBSTYLE_TRANSPARENT | TBSTYLE_LIST | TBSTYLE_CUSTOMERASE |                          TBSTYLE_WRAPABLE |      /*Common Control styles:*/ CCS_TOP | CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE;LRESULT CReflectionWnd::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled){   RECT rect;   GetClientRect(&rect);   m_ToolbarWnd.Create(m_hWnd, rect, NULL, DEFAULT_TOOLBAR_STYLE);   return 0;}

You will notice that we defined a constant for the toolbar style. This was done to make the code more readable.

The only thing left to do to the reflection window code is update the destructor to destory the window if it’s still present.

CReflectionWnd::~CReflectionWnd(){   if (IsWindow()) DestroyWindow();}

 

Finishing Off The Deskband Toolbar

All that’s left is for our deskband to create the toolbar window, have the host use the toolbar window, remove the unused IPersistStream implementation, implement IInputObject (for focus control) and do some code tweaking. So lets wrap this toolbar up. Open the StockBar.h header file. Remove the following lines of code that are in bold since we moved them to our stdafx.h for our other classes to also use.

#include "resource.h"       // main symbols//// These are needed for IDeskBand//#include <shlguid.h>#include <shlobj.h>

Next remove the following line from the class delcaration.

public IPersistStream,

The top of the class declaration should now look like this,

class ATL_NO_VTABLE CStockBar :    public CComObjectRootEx<CComSingleThreadModel>,   public CComCoClass<CStockBar, &CLSID_StockBar>,   public IDeskBand,   public IObjectWithSite,   public IDispatchImpl<IStockBar, &IID_IStockBar, &LIBID_MOTLEYFOOLLib>{

Next scroll down to the COM Map and remove the following two lines of code,

   COM_INTERFACE_ENTRY(IPersist)   COM_INTERFACE_ENTRY(IPersistStream)

Your COM Map should now look like this,

BEGIN_COM_MAP(CStockBar)   COM_INTERFACE_ENTRY(IStockBar)   COM_INTERFACE_ENTRY(IOleWindow)   COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)   COM_INTERFACE_ENTRY(IObjectWithSite)   COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)   COM_INTERFACE_ENTRY(IDispatch)END_COM_MAP()

Scroll down the header file further and remove the sections of function declarations for IPersist and IPersistStream, which includes the following lines.

// IPersistpublic:   STDMETHOD(GetClassID)(CLSID *pClassID);// IPersistStreampublic:   STDMETHOD(IsDirty)(void);   STDMETHOD(Load)(IStream *pStm);   STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty);   STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize);

There should now be nothing related to IPersist or IPersistStream between the IDockingWindow and IStockBar function declaration sections.

Now we need to remove the IPersist and IPersistStream function implementations from the StockBar.cpp source file. Find the GetClassID, IsDirty, Load, Save, and GetSizeMax function implementations and remove them from the file. They should be directly above the FocusChange Method we added earlier.

Now we can start adding code to our deskband. Open the stockbar.h header file and add the include for the reflection window class as shown below in bold.

#include "resource.h"       // main symbols#include "ReflectionWnd.h"

Next, find the protected section at the end of the file and replace the line

   HWND m_hWnd;

with

   CReflectionWnd m_ReflectWnd;

If you try to compile, you will find that it will be unsuccessful since we have removed m_hWnd and have not removed all occurances of m_hWnd from the class source file. We will replace all occurances with more appropriate code for our Reflection window and toolbar window. Open the StockBar.cpp source file, Remove the following line from the class constructor

   m_hWnd(NULL),

your class constructor should now look as follows with a SetBand call added,

CStockBar::CStockBar():    m_dwBandID(0),    m_dwViewMode(0),    m_bShow(FALSE),    m_bEnterHelpMode(FALSE),    m_hWndParent(NULL),    m_pSite(NULL){	m_ReflectWnd.GetToolBar().GetEditBox().SetBand(this);}

Next, update the RegisterAndCreateWindow function by replacing the temporary m_hWnd construction with the Reflection Window construction. Your RegisterAndCreateWindow implementation should look as follows:

BOOL CStockBar::RegisterAndCreateWindow(){   RECT rect;   ::GetClientRect(m_hWndParent, &rect);   m_ReflectWnd.Create(m_hWndParent, rect, NULL, WS_CHILD);   // The toolbar is the window that the host will be using so it is the window that is important.   return m_ReflectWnd.GetToolBar().IsWindow();}

As we scroll through the code, we should fix some other things. A toolbar has a default height of 22 so we need to update our GetBandInfo method so that all the y measurements are 22 not 20. We also want our Integral sizing to be non sizeable so we need to set the DBIM_INTEGRAL x and y values to 0. While we are at it, we should fix the title of our toolbar so it says "The Motley Fool". You’ll find this constant defined near the top of the source file, update it now.

We will now update the GetWindow call so that the toolbar window handle is returned and not the invalid m_hWnd variable. Update your GetWindow method so it looks as follows,

STDMETHODIMP CStockBar::GetWindow(HWND* phwnd){   HRESULT hr = S_OK;   if (NULL == phwnd)   {      hr = E_INVALIDARG;   }   else   {      *phwnd = m_ReflectWnd.GetToolBar().m_hWnd;   }   return hr;}

Now we need to update teh CloseDW method so that it does not destory our window buy hide it. We do this much like the MFC CToolbar class does, the class destructor will destroy the window. Your CloseDW method should look as follows,

STDMETHODIMP CStockBar::CloseDW(unsigned long dwReserved){   ShowDW(FALSE);   return S_OK;}

Working our way through our class implementation, we will update the next method that needs updating. Update the ShowDW class to show or hide the toolbar window which the host is using. Your ShowDW class should look as follows,

STDMETHODIMP CStockBar::ShowDW(BOOL fShow){   m_bShow = fShow;   m_ReflectWnd.GetToolBar().ShowWindow(m_bShow ? SW_SHOW : SW_HIDE);   return S_OK;}

We are almost done modifying the CStockBar class we need to do one last bit of updating. We need to modify the SetSite implementation to release the browser window that the toolbar may be using if we have a IInputObjectSite object and we need to query the OleCommandTarget’s ServiceProvider for the IWebBrowser2 interface which we will then set to our toolbar. The modified parts of the SetSite method implementation are below in bold.

Collapse
STDMETHODIMP CStockBar::SetSite(IUnknown* pUnkSite){//If a site is being held, release it.   if(m_pSite)   {      m_ReflectWnd.GetToolBar().SetBrowser(NULL);      m_pSite->Release();      m_pSite = NULL;   }   //If punkSite is not NULL, a new site is being set.   if(pUnkSite)   {      //Get the parent window.      IOleWindow  *pOleWindow = NULL;      m_hWndParent = NULL;      if(SUCCEEDED(pUnkSite->QueryInterface(IID_IOleWindow, (LPVOID*)&pOleWindow)))      {         pOleWindow->GetWindow(&m_hWndParent);         pOleWindow->Release();      }      if(!::IsWindow(m_hWndParent))         return E_FAIL;      if(!RegisterAndCreateWindow())         return E_FAIL;      //Get and keep the IInputObjectSite pointer.      if(FAILED(pUnkSite->QueryInterface(IID_IInputObjectSite, (LPVOID*)&m_pSite)))      {         return E_FAIL;      }        IWebBrowser2* s_pFrameWB = NULL;      IOleCommandTarget* pCmdTarget = NULL;      HRESULT hr = pUnkSite->QueryInterface(IID_IOleCommandTarget, (LPVOID*)&pCmdTarget);      if (SUCCEEDED(hr))      {         IServiceProvider* pSP;         hr = pCmdTarget->QueryInterface(IID_IServiceProvider, (LPVOID*)&pSP);         pCmdTarget->Release();         if (SUCCEEDED(hr))         {            hr = pSP->QueryService(SID_SWebBrowserApp, IID_IWebBrowser2, (LPVOID*)&s_pFrameWB);            pSP->Release();            _ASSERT(s_pFrameWB);            m_ReflectWnd.GetToolBar().SetBrowser(s_pFrameWB);            s_pFrameWB->Release();         }      }   }   return S_OK;}

If you try to compile and use the toolbar right now, it will function partially. Tabbing and input control will not work correctly since we have yet to implement IInputObject for our deskband. Let’s do that now since it’s the last bit of code we will write for our simple deskband. You may also notice that the Toolbars context menu and View|Toolbars menus still say CStockBar Class. we will fix this problem in the Finishing Touches section below.

IInputObject Implementation

To get tabbing and input control to work correctly for any deskband is quite simple. You need but to implement IInputObject. The host will query our deskband to see if this interface is implemented and if it is will call the methods to see if we require input focus and let us also process messages from the user through the host. To do this, open the stockbar.h header file. To the stockbar class declaration add the line below in bold,

class ATL_NO_VTABLE CStockBar :    public CComObjectRootEx<CComSingleThreadModel>,   public CComCoClass<CStockBar, &CLSID_StockBar>,   public IDeskBand,   public IObjectWithSite,   public IInputObject,    public IDispatchImpl<IStockBar, &IID_IStockBar, &LIBID_MOTLEYFOOLLib>{

Next scroll down to the COM Map and add an entry for IInputObject as shown below in bold,

BEGIN_COM_MAP(CStockBar)   COM_INTERFACE_ENTRY(IStockBar)   COM_INTERFACE_ENTRY(IInputObject)   COM_INTERFACE_ENTRY(IOleWindow)   COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)   COM_INTERFACE_ENTRY(IObjectWithSite)   COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)   COM_INTERFACE_ENTRY(IDispatch)END_COM_MAP()

Next add the following section of function declarations to your header file, I placed mine before the IStockBar section.

// IInputObjectpublic:   STDMETHOD(HasFocusIO)(void);   STDMETHOD(TranslateAcceleratorIO)(LPMSG lpMsg);   STDMETHOD(UIActivateIO)(BOOL fActivate, LPMSG lpMsg);

All that remains is to implement these three functions. Add the function implementations below to the end of the stockbar.cpp source file.

Collapse
STDMETHODIMP CStockBar::HasFocusIO(void){   // if any of the windows in our toolbar have focus then return S_OK else S_FALSE.   if (m_ReflectWnd.GetToolBar().m_hWnd == ::GetFocus())      return S_OK;   if (m_ReflectWnd.GetToolBar().GetEditBox().m_hWnd == ::GetFocus())     return S_OK;   return S_FALSE;}STDMETHODIMP CStockBar::TranslateAcceleratorIO(LPMSG lpMsg){   // the only window that needs to translate messages is our edit box so forward them.   return m_ReflectWnd.GetToolBar().GetEditBox().TranslateAcceleratorIO(lpMsg);}STDMETHODIMP CStockBar::UIActivateIO(BOOL fActivate, LPMSG lpMsg){   // if our deskband is being activated then set focus to the edit box.   if(fActivate)   {      m_ReflectWnd.GetToolBar().GetEditBox().SetFocus();   }   return S_OK;}

Our toolbar is functionaly done, compile, run it and see. It works as described and is fairly simple. Let’s put some finishing UI touches on it for IE and our users to use.

Finishing Touches

The are only 2 finishing touches to make, One is to fix the context menu text. The other is to add button support to the main IE toolbar. Let’s do them in order.

To fix the context menu text problem, open the StockBar.rgs project file and change all occurances of "StockBar Class" to "The Motley Fool Quotes". Compile it, run it, and see. While you only need to change one of them, it’s nicer if they all match.

Now let’s add button support for our toolbar. Update the stockbar.rgs file contents by appending the text below to it’s contents.

Collapse
HKLM{   Software   {      Microsoft      {         'Internet Explorer'         {            Extensions            {               ForceRemove	{A26ABCF0-1C8F-46e7-A67C-0489DC21B9CC} = s 'The Motley Fool Quotes'               {                  val BandClsid = s '{A6790AA5-C6C7-4BCF-A46D-0FDAC4EA90EB}'                  val ButtonText = s 'The Motley Fool'                  val Clsid = s '{E0DD6CAB-2D10-11D2-8F1A-0000F87ABD16}'                  val 'Default Visible' = s 'Yes'                  val 'Hot Icon' = s '%MODULE%,425'                  val Icon = s '%MODULE%,425'                  val MenuStatusBar = s 'The Motley Fool Stock Quote Toolbar'                  val MenuText = s 'The Motley Fool'               }            }         }      }   }}

The replace the 425 with the id from resource.h of IDI_MOTLEY. Also replace the BandClsid value with the GUID of our toolbar, the above values represent the source code for the article. Now compile the toolbar again. Then start IE and right click on the Standard Buttons toolbar, Select "Customize" from the context menu. Scroll down the Available toolbar buttons listbox and find "The Motley Fool" item, See Figure 12. Select it and click the Add button in the middle of the dialog. The item will move to the right as in Figure 13. Click the Close Button. You’ll see the button added as shown in the before figure 14 and after figure 15.

Figure 12. Customize Toolbar - Available Toolbar Buttons.
Figure 12. CustomizeToolbar – Available Toolbar Buttons.
Figure 13. Customize Toolbar - Current Toolbar Buttons.
Figure 13. Customize Toolbar – Current Toolbar Buttons.
Figure 14. IE Standard Buttons - Before.
Figure 14. IE Standard Buttons – Before.
Figure 15. IE Standard Buttons - After.
Figure 15. IE Standard Buttons – After.

Conclusion

While this tutorial is long hopefully the explaination was clear. From writing this tutorial it is easy to see that the RBDeskband ATL Object Wizard has some room for improvement but provided enough of a base for us to develop our simple example. In the end you can see that the toolbar we created is much like the Address bar. The differences lie in how MS implemented theirs versus how I implemented mine. As always feedback is welcome. Enjoy.


About Erik Thompson

Site Builder

Erik lives in Redmond, Washington. He works as a Senior Software Engineer specializing in C++, COM, ATL and the middle-tier and now .NET. When he isn’t coding for work, he can be found trying to extend Internet Explorer with yet another Desk band or simplifying his development process with ATL Object Wizards.

He spends his free time snowboarding, mountain biking, reading, dining out at those hidden finds.

Click here to view Erik Thompson’s online profile.

Other popular ATL articles:

0

Firefox 3.0 Alpha 1 已经出炉!


点击此处开始下载 (官方连接)

 

0

网页 Meta 标记全面介绍


META标签是HTML语言HEAD区的一个辅助性标签,它位于HTML文档头部的<HEAD>标记和<TITLE>标记之间,它提供用户不可见的信息。meta标签通常用来为搜索引擎robots定义页面主题,或者是定义用户浏览器上的cookie;它可以用于鉴别作者,设定页面格式,标注内容提要和关键字;还可以设置页面使其可以根据你定义的时间间隔刷新自己,以及设置RASC内容等级,等等。
下面介绍一些有关 标记的例子及解释。
  META标签分两大部分:HTTP标题信息(HTTP-EQUIV)和页面描述信息(NAME)。
※ HTTP-EQUIV
  HTTP-EQUIV类似于HTTP的头部协议,它回应给浏览器一些有用的信息,以帮助正确和精确地显示网页内容。常用的HTTP-EQUIV类型有:
  1、Content-Type和Content-Language (显示字符集的设定)
  说明:设定页面使用的字符集,用以说明主页制作所使用的文字已经语言,浏览器会根据此来调用相应的字符集显示page内容。
  用法:<Meta http-equiv="Content-Type" Content="text/; Charset=gb2312">
      <Meta http-equiv="Content-Language" Content="zh-CN">
  注意: 该META标签定义了HTML页面所使用的字符集为GB2132,就是国标汉字码。如果将其中的“charset=GB2312”替换成“BIG5”,则该页面所用的字符集就是繁体中文Big5码。当你浏览一些国外的站点时,IE浏览器会提示你要正确显示该页面需要下载xx语支持。这个功能就是通过读取HTML页面META标签的Content-Type属性而得知需要使用哪种字符集显示该页面的。如果系统里没有装相应的字符集,则IE就提示下载。其他的语言也对应不同的charset,比如日文的字符集是“iso-2022-jp ”,韩文的是“ks_c_5601”。
  Content-Type的Content还可以是:text/xml等文档类型;
  Charset选项:ISO-8859-1(英文)、BIG5、UTF-8、SHIFT-Jis、Euc、Koi8-2、us-ascii, x-mac-roman, iso-8859-2, x-mac-ce, iso-2022-jp, x-sjis, x-euc-jp,euc-kr, iso-2022-kr, gb2312, gb_2312-80, x-euc-tw, x-cns11643-1,x-cns11643-2等字符集;Content-Language的Content还可以是:EN、FR等语言代码。
  2、Refresh (刷新)
   说明:让网页多长时间(秒)刷新自己,或在多长时间后让网页自动链接到其它网页。
   用法:<Meta http-equiv="Refresh" Content="30">
      <Meta http-equiv="Refresh" Content="5; Url=http://www.xia8.net">
   注意:其中的5是指停留5秒钟后自动刷新到URL网址。
  3、Expires (期限)
   说明:指定网页在缓存中的过期时间,一旦网页过期,必须到服务器上重新调阅。
   用法:<Meta http-equiv="Expires" Content="0">
      <Meta http-equiv="Expires" Content="Wed, 26 Feb 1997 08:21:57 GMT">
   注意:必须使用GMT的时间格式,或直接设为0(数字表示多少时间后过期)。
  4、Pragma (cach模式)
   说明:禁止浏览器从本地机的缓存中调阅页面内容。
   用法:<Meta http-equiv="Pragma" Content="No-cach">
   注意:网页不保存在缓存中,每次访问都刷新页面。这样设定,访问者将无法脱机浏览。
  5、Set-Cookie (cookie设定)
  说明:浏览器访问某个页面时会将它存在缓存中,下次再次访问时就可从缓存中读取,以提高速度。

当你希望访问者每次都刷新你广告的图标,或每次都刷新你的计数器,就要禁用缓存了。通常HTML文件没有必要禁用缓存,对于ASP等页面,就可以使用禁用缓存,因为每次看到的页面都是在服务器动态生成的,缓存就失去意义。如果网页过期,那么存盘的cookie将被删除。
   用法:<Meta http-equiv="Set-Cookie" Content="cookievalue=xxx; expires=Wednesday, 21-Oct-98 16:14:21 GMT; path=/">
   注意:必须使用GMT的时间格式。
  6、Window-target (显示窗口的设定)
   说明:强制页面在当前窗口以独立页面显示。
   用法:<Meta http-equiv="Widow-target" Content="_top">
   注意:这个属性是用来防止别人在框架里调用你的页面。Content选项:_blank、_top、_self、_parent。
  7、Pics-label (网页RSAC等级评定)
   说明:在IE的Internet选项中有一项内容设置,可以防止浏览一些受限制的网站,而网站的限制级别就是通过该参数来设置的。
   用法:<META http-equiv="Pics-label" Contect="(PICS-1.1′http://www.rsac.org/ratingsv01.html’ I gen comment ‘RSACi North America Sever’ by ‘inet@microsoft.com’ for ‘http://www.microsoft.com’ on ’1997.06.30T14:21-0500′ r(n0 s0 v0 l0))">
   注意:不要将级别设置的太高。RSAC的评估系统提供了一种用来评价Web站点内容的标准。用户可以设置Microsoft Internet Explorer(IE3.0以上)来排除包含有色情和暴力内容的站点。上面这个例子中的HTML取自Microsoft的主页。代码中的(n 0 s 0 v 0 l 0)表示该站点不包含不健康内容。级别的评定是由RSAC,即美国娱乐委员会的评级机构评定的,如果你想进一步了解RSAC评估系统的等级内容,或者你需要评价自己的网站,可以访问RSAC的站点:http://www.rsac.org/
  8、Page-Enter、Page-Exit (进入与退出)
   说明:这个是页面被载入和调出时的一些特效。
   用法:<Meta http-equiv="Page-Enter" Content="blendTrans(Duration=0.5)">
      <Meta http-equiv="Page-Exit" Content="blendTrans(Duration=0.5)">
   注意:blendTrans是动态滤镜的一种,产生渐隐效果。另一种动态滤镜RevealTrans也可以用于页面进入与退出效果:
      <Meta http-equiv="Page-Enter" Content="revealTrans(duration=x,transition=y)">
      <Meta http-equiv="Page-Exit" Content="revealTrans(duration=x,ransition=y)">
       Duration  表示滤镜特效的持续时间(单位:秒)
       Transition 滤镜类型。表示使用哪种特效,取值为0-23。
       0 矩形缩小       1 矩形扩大
       2 圆形缩小       3 圆形扩大
       4 下到上刷新       5 上到下刷新
       6 左到右刷新       7 右到左刷新
       8 竖百叶窗       9 横百叶窗
       10 错位横百叶窗       11 错位竖百叶窗
       12 点扩散       13 左右到中间刷新
       14 中间到左右刷新       15 中间到上下
       16 上下到中间       17 右下到左上
       18 右上到左下       19 左上到右下
       20 左下到右上       21 横条
       22 竖条       23 以上22种随机选择一种
  9、MSThemeCompatible (XP主题)
   说明:是否在IE中关闭 xp 的主题
   用法:<Meta http-equiv="MSThemeCompatible" Content="Yes">
   注意:关闭 xp 的蓝色立体按钮系统显示样式,从而和win2k 很象。
  10、IE6 (页面生成器)
   说明:页面生成器generator,是ie6
   用法:<Meta http-equiv="IE6" Content="Generator">
   注意:用什么东西做的,类似商品出厂厂商。
  11、Content-Script-Type (脚本相关)
   说明:这是近来W3C的规范,指明页面中脚本的类型。
   用法:<Meta http-equiv="Content-Script-Type" Content="text/">
   注意:
※NAME变量
  name是描述网页的,对应于Content(网页内容),以便于搜索引擎机器人查找、分类(目前几乎所有的搜索引擎都使用网上机器人自动查找meta值来给网页分类)。
  name的value值(name="")指定所提供信息的类型。有些值是已经定义好的。例如description(说明)、keyword(关键字)、refresh(刷新)等。还可以指定其他任意值,如:creationdate(创建日期) 、document ID(文档编号)和level(等级)等。
  name的content指定实际内容。如:如果指定level(等级)为value(值),则Content可能是beginner(初级)、intermediate(中级)、advanced(高级)。
  1、Keywords (关键字)
   说明:为搜索引擎提供的关键字列表
   用法:<Meta name="Keywords" Content="关键词1,关键词2,关键词3,关键词4,……">
   注意:各关键词间用英文逗号“,”隔开。META的通常用处是指定搜索引擎用来提高搜索质量的关键词。当数个META元素提供文档语言从属信息时,搜索引擎会使用lang特性来过滤并通过用户的语言优先参照来显示搜索结果。例如:
      <Meta name="Kyewords" Lang="EN" Content="vacation,greece,sunshine">
      <Meta name="Kyewords" Lang="FR" Content="vacances,grè:ce,soleil">
  2、Description (简介)
   说明:Description用来告诉搜索引擎你的网站主要内容。
   用法:<Meta name="Description" Content="你网页的简述">
   注意:
  3、Robots (机器人向导)
   说明:Robots用来告诉搜索机器人哪些页面需要索引,哪些页面不需要索引。Content的参数有all、none、index、noindex、follow、nofollow。默认是all。
   用法:<Meta name="Robots" Content="All|None|Index|Noindex|Follow|Nofollow">
   注意:许多搜索引擎都通过放出robot/spider搜索来登录网站,这些robot/spider就要用到meta元素的一些特性来决定怎样登录。
    all:文件将被检索,且页面上的链接可以被查询;
    none:文件将不被检索,且页面上的链接不可以被查询;(和 "noindex, no follow" 起相同作用)
    index:文件将被检索;(让robot/spider登录)
    follow:页面上的链接可以被查询;
    noindex:文件将不被检索,但页面上的链接可以被查询;(不让robot/spider登录)
   nofollow:文件将不被检索,页面上的链接可以被查询。(不让robot/spider顺着此页的连接往下探找)
  4、Author (作者)
   说明:标注网页的作者或制作组
   用法:<Meta name="Author" Content="张三,abc@sohu.com">
   注意:Content可以是:你或你的制作组的名字,或Email
  5、Copyright (版权)
   说明:标注版权
   用法:<Meta name="Copyright" Content="本页版权归Zerospace所有。All Rights Reserved">
   注意:
  6、Generator (编辑器)
   说明:编辑器的说明
   用法:<Meta name="Generator" Content="PCDATA|FrontPage|">
   注意:Content="你所用编辑器"
  7、revisit-after (重访)
   说明:
   用法:<META name="revisit-after" CONTENT="7 days" >
   注意:
※Head中的其它一些用法
  1、scheme (方案)
   说明:scheme can be used when name is used to specify how the value of content should
      be interpreted.
   用法:<meta scheme="ISBN" name="identifier" content="0-14-043205-1" />
   注意:
  2、Link (链接)
   说明:链接到文件
   用法:<Link href="soim.ico" rel="Shortcut Icon">
   注意:很多网站如果你把她保存在收件夹中后,会发现它连带着一个小图标,如果再次点击进入之后还会发现地址栏中也有个小图标。现在只要在你的页头加上这段话,就能轻松实现这一功能。<LINK> 用来将目前文件与其它 URL 作连结,但不会有连结按钮,用於 <HEAD> 标记间, 格式如下:
       <link href="URL" rel="relationship">
       <link href="URL" rev="relationship">
  3、Base (基链接)
   说明:插入网页基链接属性
   用法:<Base href="http://www.csdn.net/" target="_blank">
   注意:你网页上的所有相对路径在链接时都将在前面加上“http://www.cn8cn.com/”。其中

target="_blank"是链接文件在新的窗口中打开,你可以做其他设置。将“_blank”改为“_parent”是链接文件将在当前窗口的父级窗口中打开;改为“_self”链接文件在当前窗口(帧)中打开;改为“_top”链接文件全屏显示。

<head>  
<title>文件头,显示在浏览器标题区</title>
<meta http-equiv="Content-Language" content="zh-cn">
 <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
 <meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 <meta name="ProgId" content="FrontPage.Editor.Document">
 <meta name="制作人" content="Simonzy">
 <meta name="主题词" content="HTML 网页制作 C# .NET JavaScript JS">
</head>

以上是META标签的一些基本用法,其中最重要的就是:Keywords和Description的设定。为什么呢?道理很简单,这两个语句可以让搜索引擎能准确的发现你,吸引更多的人访问你的站点!根据现在流行搜索引擎(Google,Lycos,AltaVista等)的工作原理,搜索引擎先派机器人自动在WWW上搜索,当发现新的网站时,便于检索页面中的Keywords和Description,并将其加入到自己的数据库,然后再根据关键词的密度将网站排序。

0

Rails RESTful (1) 什麼是REST?


on Rails 1.2 的一個重要進展是 RESTful,在了解怎麼用之前,我們要先了解什麼是 REST(Representational State Transfer)?

什麼是REST?

REST 是一種分散式超媒體系統(如WWW)的軟體架構風格,你可以想像它是一個良好設計的Web應用程式規則: 一組網路Web頁面(虛擬的狀態機器),其中 Client 透過點選超連結(狀態變換),結果是下個Web頁面(表示應用程式的下一個狀態)。

REST 所描述的網路系統包括三個部份:
data elements (resource, resource identifier, representation)
connectors (client, , , resolver, tunnel)
components (origin server, gateway, proxy, user agent)

幾個重點:
Data elements 由標準化介面存取
Components 透過介面傳輸 資源表徵 (representations of resources) 來溝通,而不是直接操作資源本身。
Connectors 提供 component 的抽象介面來溝通,隱藏溝通機制的實作細節。
Components 使用 connectors 來存取,connectors 提供資源的存取或居中。
所有來自 connector 的 requests 必須包含所有必要的資訊來了解該 request,不需要依靠之前的request (即 stateless)

嚴格來說REST符合以下幾個條件:
應用程式的狀態跟功能拆成 resources
每個 resource 使用獨一無二用來當作超連結的通用定位語法(在WWW中即URI)
所有 resources 共用一致的介面在 client 跟 resource 之間轉換狀態,包括:
一組有限的良好定義操作 well-defined operations
一組有限的內容格式 content types,也許包括 可執行的程式碼 code-on-demand (在WWW中即Javascript)
這種通訊協定 protocol (在WWW中即用HTTP) 包含以下特色:
使用者端/伺服器端 Client/Server
狀態無關 Stateless
可以快取 Cacheable
分層的 Layered

符合 REST principles 的系統稱做 RESTful。

一般來說REST這個詞彙常被用來描述任何使用XML (or YAML, JSON, plain text) 的簡單介面,而不須靠其他機制(如SOAP)。另外 REST 雖然是個來自 WWW 的架構概念(比WWW晚),但是這兩者並不是綁在一起,有可能設計一個大型軟體系統符合REST但是不用HTTP協定也不需跟WWW互動,也有可能設計一個簡單的 XML+HTTP 界面使用 RPC model 而不符合 REST principles。

Resources

REST的一個最重要的觀念就是 resources (特定資訊的資源),每一個 resource 由一個 global identifier (即URI)所表示。為了操作這些 resources,網路的 components (即 clients 跟servers) 透過標準化的介面 (即HTTP) 來溝通並交換這些 resources 的 representations (即實際上傳達資訊的文件).

任意數量的 connectors (如clients, servers, caches, tunnels等) 可以居中 request,但是都不可以 “seeing past” (不需要其他 layer層)。這樣的應用程式跟一個 resource 互動根據兩件事情: resource的URI 跟 要做的動作 – 它不需要知道是否有 caches, proxies, gateways, firewalls, tunnels, 或其他任何藏在sever之間的東西。這個應用程式只需要知道資訊的格式 (representation),通常是 HTML或 XML 或圖片什麼的。

REST 有什麼優點?
支援快取 caching 將改善反應時間跟server的負載能力。
因為不必維持連結狀態,大大改善 server 的 scalability 能力。這表示不同server可以處理同一串 requests。
一個瀏覽器就可以存取任一應用程式跟資源,client 端不需使用別的軟體。
在HTTP之上不依存其他機制跟軟體。
跟其他連結方式相比(如RPC),可以提供相等的功能。
不需要其他的 discovery 機制,因為使用超連結了。
提供比RPC更好的長期相容性,因為 :
如同HTML這種文件具有後前及向後的相容能力
支援新的內容格式不需要丟掉舊的

另外比起RPC-style,URL command line 有極佳的 human-friendly 優點,容易 discovered/ transmitted /scripted/bookmarked 一個 URL。請參考 The Beauty of REST 跟 Tangled in the Threads 的優點介紹。

跟 RPC 的比較

跟 REST 應用程式對比的就是 RPC (Remote procedure call,實作上有XML-RPC或SOAP等) 了。RPC 應用程式曝露一或多個網路物件,每個有特定的 functions 可以呼叫。在 client 與物件溝通之前,它必須知道這個物件的知識來操作。

REST 的設計限制了 resource 的面向,它定義了介面 (動詞 verbs 跟內容型別 content types),導致比RPC更少的型別,但是更多的resource identifiers (名詞nouns)。REST 的設計尋求定義一組 resources 讓 Clients 可以一致性的互動,而且提供超連結在資源之間可以瀏覽,而不需要了解整個 resources 的知識 。Server 提供的表單 forms 也可以被用在 RESTful 的環境來描述 clients 如何建構 URL 來跟特定的resource做溝通。

這張圖指出了REST的三位一體 : Nouns, 有限的 Verbs 跟 Content Types。

需注意的是,根據不同的用法要求跟效率,在不同的應用程式環境中,該使用哪種架構仍有很大討論的空間跟爭議(SOAP的支持者認為REST仍有其侷限,只適合簡單的應用)。REST的重要性在於它有個目前最成功的大型軟體架構應用: Wide World Web。RESTful 是 Web 的天性,也是讓 Web 成功的原因,因此 RESTful 的支持者認為使用 RESTful 架構就是 Web上最好的方法來做到有擴充性(scalable),彈性跟有威力的應用程式。在有這麼多複雜的RPC技術之後,REST因其簡單又有威力的架構近來越來越受到矚目跟重視。

舉例

一個 RPC 應用程式可能會定義以下的操作:

getUser()
addUser()
removeUser()
updateUser()
getLocation()
addLocation()
removeLocation()
updateLocation()
listUsers()
listLocations()
findLocation()
findUser()

Client 的程式碼可能會這樣存取:

exampleAppObject = new ExampleApp(”example.com:1234″)
exampleAppObject.getUser()

在 REST中,重點在 resources(或稱作 nouns)的多樣性,比如說可能有以下的用法:

http://example.com/users/
http://example.com/users/{user} (one for each user)
http://example.com/findUserForm
http://example.com/locations/
http://example.com/locations/{location} (one for each location)
http://example.com/findLocationForm

Client 的程式碼可能這樣存取:

userResource = new Resource(http://example.com/users/001)
userResource.get()

每個 resource 擁有自己的識別名詞,而 Clients 從單一 resource 開始瀏覽,透過標準操作走訪 resource ,如 GET 下載,PUT更新,DELETE刪除,POST新增,注意到每個物件有自己的URL,而且可以容易被快取,複製跟書籤化(bookmarked)。

參考資源
Representational State Transfer
RestWiki
How to Create a REST Protocol

From :http://ihower.idv.tw//archives/1542

0

JavaScript中的私有成员


Private Members in

JavaScript是世界上是被误解得最厉害的编程语言。有些人认为它不具备“信息隐藏”的能力,因为JavaScript的对象没有私有变量和方法。这是误解。JavaScript对象可以拥有私有成员,下面我们来看看怎么做。(SharkUI.com注:JavaScript并不是真正拥有私有、公有等等OOP的特性,这篇译文中提到的这些私有、公有、特权等特性,是利用JavaScript的其他特性(参看本文的“闭包”一节)“模拟”出来的。感兴趣的话可以搜索相关的文章来看,当然也可以不管这些,就当它是真正的OOP来用。Have fun!)

对象

JavaScript是建立在对象之上的。数组(Array)是对象,函数(Function)是对象,对象(Objects)当然也是对象。那什么是对象呢?对象是一组“名称:值”对(name-value pair)的集合。名称是字符串,值却可以是字符串、数值、布尔或对象(包括数组和函数)。对象通常是用哈希表来实现的,以便可以快速地取值。

如果值是一个函数,我们就可以把它当作一个“方法”。当对象的一个方法被执行,变量this就被设为对象本身。如此,方法就可以通过this变量来访问对象的实例。

对象可以通过“构造器(constructor)”来创建。构造器是一个拥有初始化对象的函数。构造器提供了类似其他语言中的“)”所提供的特性和功能,包括静态变量和方法。

公有

对象的所有成员都是公有成员。任何函数都可以访问、修改或者删除这些成员,当然也可以添加新的成员。给对象添加成员的两种主要方法:

通过构造器

这种方法一般用来初始化对象实例的公有变量。构造器的this变量被用来给对象添加成员:

function Container(param) {   this.member = param;}

构造一个新的对象:

var myContainer = new Container('abc');

然后,公有变量 myContainer.member 就拥有了值 ‘abc’。

通过原型(prototype)

这种方法通常用来添加公有方法。在对象本身搜寻一个成员但没有找到时,就使用构造器的原型(prototype)成员。这种原型机制实现了面向对象所谓的 “继承(inheritance)”,同时也节省了内存。给创建自同一个构造器的所有的对象加上一个方法,只需要给构造器的prototype增加一个函数:

Container.prototype.stamp = function (string) {   return this.member + string;}

然后我们就可以调用这个方法:

myContainer.stamp('def')

返回’abcdef’。

私有

私有(Private)成员是由构造器创建的。通常构造器中用var声明的变量和函数参数成为私有成员。

function Container(param) {   this.member = param;   var secret = 3;   var self = this;}

这个构造器创建了三个私有的实例变量:param,secret和self。

function Container(param) {   function dec() {      if (secret > 0) {         secret -= 1;         return true;      } else {         return false;      }   }   this.member = param;   var secret = 3;   var self = this;}

私有方法dec会检查实例变量secret,如果它大于0,自减1并返回true;如果它小于0,返回false。这样就实现了由这个架造器所创建对象的dec函数只能用三次的功能。

按惯例,我们创建了一个私有变量self。私有方法可以通过它来访问到对象本身。但这只是一种权宜之计,因为《ECMAScript Language Specification》中有一个错误,使得内部函数的this变量被设置成一个错误值。

公有方法(SharkUI.com注:即上文说的通过prototype创建的方法)是无法调用私有方法的,所以为了能使用私有方法,我们需要引入特权方法(privileged method)。

特权

一个特权方法可以访问私有变量和方法,而它本身可以被公有方法和外界访问。你可以删除或替换一个特权方法,但不能修改它,也不能强制它放弃自己的密秘(SharkUI.com注:原文如此,可能是指它的特权,关于这点请高手指教)。

特权方法是在构造器内部通过this来创建的。

function Container(param) {   function dec() {      if (secret > 0) {         secret -= 1;         return true;      } else {         return false;      }   }   this.member = param;   var secret = 3;   var self = this;   this.service = function () {      if (dec()) {         return self.member;      } else {         return null;      }   };}

service是一个特权方法。前三次调用myContainer.service()将返回’abc’,之后将返回null。service通过调用私有方法dec来访问私有变量secret。对于其他对象和方法来说,可以访问到service,但不能直接访问到私有的成员。

闭包

这种公有、私有和特权成员模式的存在是由于JavaScript的内在机制:闭包。这意味着一个内部函数永远可以访问它外部函数的变量和参数,即使外部函数已经返回。这是JavaScript语言非常强大的一个特性。目前还没有关于JavaScript编程的书籍展示了如何来利用它,它们甚至都没有提到这一点。

私有和特权成员只能在对象初始化的时候创建,而公有成员可以被随时添加进来。

模式

公有
function Constructor(...) {   this.membername = value;}Constructor.prototype.membername = value;
私有
function Constructor(...) {   var self = this;   var membername = value;   function membername(...) {...}}

注:这句代码:

function membername(...) {...}

事实上是以下代码的简略写法

var membername = function membername(...) {...};
特权
function Constructor(...) {   this.membername = function (...) {...};}

后记

Douglas Crockford的这篇文章为我们写出更优美的JavaSciprt程序奠定了基础,为我们创建出更合理的面向对象应用和框架带来了可能。在这篇译文快要完成的时候,惊诧的发现作者网站上出现了一个本文中文版的链接。好事!有越来越多的中国人开始关注这些“边边角角”的技术。虽然做了重复工作,但一样希望各位能从这篇文章中有所收益。也希望有更多的人能投入到原创和翻译前端技术文章中来,在多数人浮躁的时候,我们需要更多基础性的工作。一周一篇不多,一年一篇不少,只要开始了就行!

转载自: http://www.sharkui.com/articles/article.php?id=44

0

CSS标准化网页布局与重构


刚刚在BLUEIDEA上看到的,到时有空就去了,哈,学习学习嘛.         :)

活动时间:11月25日(星期六) 下午 14:00-15:30
活动主题:CSS标准化网页布局与重构
活动地点:中关村图书大厦(左岸公社) 五层多功能厅

主讲:李超(CSS网站布局实录作者)

这次的活动是上次网站设计专场讲座的延续,由于上次CSS网站布局实录的作者外地出差,没能参加,因此CSS部分没有讲解,这次出版社特地安排把CSS部分的活动做完,到时候会有一个半小时全部与大家一起交流CSS的内容

CSS方面的很多东西都有教程和图书,到时候应该不会太多废话,会找一些书中没有的东西,CSS的一些背景和网站设计中使用CSS的方法,思路,主要是思路,设计思路和实现思路,等一些较思考性的内容,并与大家一起交流一下,欢迎参加和拍砖~

主题

• 什么是Web标准?
• Web客户端表现层技术的起源与发展
• 表现(Design)与内容(Content)分离的页面技术
• (CSS网站布局技术)
• Web标准与用户体验(UE)设计
• 部分CSS布局案例

※什么是Web标准?
Web标准是网站开发中的一系列标准的集合。每一个标准对应网站开发中的每一个环节,如HTML用于表现信息结构,CSS用于表现信息的展示方式,Javascript用于表现信息的简单动态处理等
无论是HTML,还是XHTML,还是CSS,,都是Web标准其中之一

※Web客户端表现层技术的起源与发展
Web的基本架构与主要功能
Web客户端表现技术的作用
HTML与JavaScript
Gif动画
Css技术
Quicktime、ActiveX控件

Web客户端表现层技术的作用
客户端表现层技术的最终目的
客户端表现层技术的最终目的是为用户提供最优质的信息,使用户拥有最好的用户体验(User Experience)

css技术
CSS是一种专注于对信息的视觉表现进行控制的技术。CSS的目标是用来取代HTML中的“设计”部分,使HTML专注于信息整理,而CSS来专注于信息的视觉表现
优秀的CSS与HTML设计使内容与表现完全分离,以更好的结构来展示信息,使得信息易于展现并易于修改

Quicktime、ActiveX控件
网络趋向于多媒体形式的展示、通过Quicktime、ActiveX实现在网页中的视频与音乐播放。

Flash
目前最优秀的互动表现技术、丰富用户体验
通过FLASH开发环境或编程实现与用户的实时交互
丰富的媒体支持及动画制作
是目前为品牌用户建立线上推广、为用户提供优秀交互界面的强大工具

※表现(Design)与内容(Content)分离的页面技术

表现(Design)与内容(Content)分离的页面技术
什么是表现与内容?
为什么要实现表现与内容的分离?
XHTML与CSS的协同作战
高效开发
易于维护
其它方面优势
现阶段的问题

什么是表现(Design)与内容(Content)?
内容是指具体的信息,仅仅表示信息正文及各部分的名称,如标题、作者、正文、图片
表现是指信息的展示形式,如标题使用16号黑体,正文使用12号宋体、图片采用文绕图间距10px的排列方式等

什么是表现(Design)与内容(Content)?
使用传统的HTML来表现(Design)
设计方式复杂
控制区域较多
代码繁杂易读性差

※表现与内容分离的技术
设计简单
易于控制
代码简单
易于修改

什么是表现(Design)与内容(Content)?
DIV元素的掌握是表现与内容分离的基础

为什么要实现表现与内容的分离?
分离使得网站代码可维护性提高
分离使代码重用得到可能,大幅提高开发效率
重用使得代码量可以成倍减少,减轻服务器负担使得降低宽带成本成为可能
加快浏览器解析速度使用户阅读更快捷迅速

为什么要实现表现与内容的分离?
分离技术使我们在制作网站的时候能够充分对网站统一性、可用性进行思考与设计,提高网站可用性,改善用户体验

XHTML与CSS的协同作战
推荐使用XHTML+CSS的方式来对网站进行编码
我们的应用级设计对象是用户,但代码级的设计目标是机器
使用Dreamweave MX 2004或后续版本进行可视化开发

高效开发
Macromedia.com
不同排版模式的高效重用

易于维护
Macromedia.com
良好的规划与组织是维护的关键
多个CSS协调工作、层次清晰

Macromedia.com
对信息区域的合理设计是维护的关键

其它方面优势
分离使得设计人员、程序人员更好的独立工作
分离使内容转换到其它平台的成本更低

现阶段的问题
浏览器对CSS支持的不完善
相同浏览器的不同版本、不同操作系统下显示不同
不同浏览器对CSS的支持是不同的

※Web标准与用户体验(UE)设计

Web标准与用户体验(UE)设计
网站与用户体验(UE)的关系
Web标准帮助我们对用户体验进行思考
用户体验的几个思考过程
案例

网站与用户体验(UE)的关系
用户体验是什么?
What is User Experneice?
网站是一个“自服务式”的产品
通过改善用户体验使网站所有者受益

Web标准
帮助我们对用户体验进行思考
Web标准设计的难点在于对网站的信息结构进行合理分配,归纳,设计
设计合理的网站层次
设计合理的导航系统
设计合理的版式结构

只有合理的网站信息结构的设计,才能让Web标准所支持的分离式结构有用武之地

用户体验的思考过程
与用户一起走一篇

用户体验的思考过程
与用户一起做一篇

用户体验的思考过程
让用户感受细节

※案例
2006 CSS Award Winner

※CSS玩家交流

—–
PING:
NAME: 打包机
TITLE: 打包机2
IP: 221.0.56.225
URL: http://www.jnxrbz.com/212.htm
DATE: 05/19/2007 20:42:56
文章好,已被打包机用
—–
PING:
BLOG NAME: 升降机液压升降机升降平台
TITLE: 升降机液压升降机
IP: 60.208.187.18
URL: http://www.jiyangheli.com/products.htm
DATE: 05/20/2007 22:30:14
文章好,已被升降机/升降平台/液压升降机引用
—–
PING:
BLOG NAME: 灌装机
TITLE: 1灌装机
IP: 60.208.192.45
URL: http://www.jnxrbz.com/204.htm
DATE: 05/24/2007 03:19:13
好,已被灌装机引用
—–

0

【越狱】超级多的 T – BAG 在其他影片中的剧照!


Previous Page

Random Posts Recent Comments

  • 女友糖尿病害我蛀牙 Says:

    汗一个…...

  • Htj06 Says:

    zhenyouchuangyi...

  • 电商圈 Says:

    试图该怎么建立啊,,怎在程序中是吸纳...

  • edward Says:

    看得人心旷神怡,好文,情不自禁的顶一下...

  • Daniel Says:

    我也在处理这个问题,没有找到好的方法。我用了楼上兄弟的方法,还是可以的。不知道您找到好的方法了吗、我暂时楼上兄弟的方法。...

  • 卡,卡 Says:

    弱弱问一句:博主,你博客的模板这样设计pv高吗?...

  • 站长工具 Says:

    博主,兔年快乐!...

  • health Says:

    great post!!I hope I can read more in your website....

  • pdu Says:

    好博文,支持分享...

  • 站长工具 Says:

    博主的文章很不错,我是站长工具-站长精灵的作者,一款专业的SEO工具软件(可以帮您提高博客的流量),想跟您交换个链接,不知可否...

Tag Cloud

arm audio blog brew cache class debug flash google html j2me java javascript Joke linux lua mobile mtk php python ror ruby server shell stream unix web windows 优化 动态加载 女人 女生 平台 开发 手机 技术 流媒体 测试 漫画 生活 男人 男生 缓存 芯片