Archive for the ‘东东博客’ Category

zt: php下用GD生成生成缩略图的两个选择和区别

星期三, 25 6 月, 2008

PHP的GD扩展提供了两个函数来缩放图像:

ImageCopyResized(dest, src, dx, dy, sx, sy, dw, dh, sw, sh);ImageCopyResampled(dest, src, dx, dy, sx, sy, dw, dh, sw, sh);
ImageCopyResized( )函数在所有GD版本中有效,但其缩放图像的算法比较粗糙,可能会导致图像边缘的锯齿。GD 2.x中新增了一个ImageCopyResampled( )函数,其像素插值算法得到的图像边缘比较平滑(但该函数的速度比ImageCopyResized()慢)。

将图片缩小四倍的例子:
<?php
 $src = ImageCreateFromJPEG(‘php.jpg’);
 $width = ImageSx($src);
 $height = ImageSy($src);
 $x = $width/2; $y = $height/2;
 $dst = ImageCreateTrueColor($x,$y);
 ImageCopyResized($dst,$src,0,0,0,0,$x,$y,$width,$height);
 //ImageCopyResampled($dst,$src,0,0,0,0,$x,$y,$width,$height);
 header(‘Content-Type: image/jpeg’);
 ImageJPEG($dst,”,100);
?>

原贴:http://www.jb51.net/article/9528.htm

ADSL安装手记

星期五, 30 5 月, 2008

去年11月份把用了4年多的有线通停掉了,由于粥妈正怀着宝宝,所以打算今年的这段时间再安装宽带,没有安装宽带的这阵子里使用16300拨号上网。

历时半年使用16300拨号上网,强忍着因网页丰富的图片、广告资源占用带宽而打开极慢的痛苦,从今天3月中旬开始就着手安装宽带。

安装宽带过程中屡屡碰壁。因以前使用有线通觉得慢而停掉,这回首先考虑安装ADSL。

www.021adsl.com看到有1500元包年的1M套餐,打算安装,经过咨询可以使用居住证单独接线安装(自己安装到时移机方便)。经与粥妈协商,打算再过一阵子再装。两个星期后决定安装时对方答复说因领导变更该套餐暂停了。没办法,只能另寻他法。

分析现有的ADSL安装方式,发现只有E8套餐划得来,我们现在使用有房东安装的固定电话,打算在上面加装。加装的话必须要有房东的身份证复印件,经与房东协商,房东口头同意给。但是4月初房东(的老公)过来取房租时没有带过来(电话是用女方身份证安装的),后来再打电话跟房东索取时,被告知他们现在住的地方下半年可能拆迁,他们到时要过来住,说包年用不完因此没有给身份证复印件。我们感觉是房东不想给我们她的身份证复印件,我们在这里都住了5年了的。气愤但也没有办法,把房东逼急了说不定让我们立马搬家呢,这时正是关键时期可不方便呀,所以放弃此法。

后来打算安装有线通了,管它慢不慢呢,能比拨号好就行,真不想再忍受网络龟爬的痛苦了。从两个渠道申请,都被告知因没有安装闭路电视不能安装有线通。我们03年8月安装有线通时可没有这么说,所以我们用了4年,这回停掉后说什么也不能安装了,除非先把闭路电视装了。经咨询,安装闭路电视得房东来,考虑到借房东身份证的事决定放弃此法。

自己单独接线走不通(月付的话还要多交310元的初装费,放弃此法)、在房东的座机上加载行不通、安装有线通也行不通,想放弃还继续再忍受网络龟爬的痛苦。这一个月以来因上次买的16300上网卡用完了,现在直接用16300用户和密码上网,1.2元/小时,觉得钱花了但不爽。

看到粥妈在家坐月子老说无聊,我不断的在网上找新的办法,也想等到1500元包年套餐恢复,但总是失望。

最后想到个折衷的办法,自己新装一个E8套餐,7月初房东来拿房租时给他最近一次的电信帐单,让他回去叫女房东把现在的座机停了,最后一个月的费用我们下回结清,停机后的费用我们不再支付。

本打算等7月份先停机后再安装呢,可今天粥妈打电话过来说有早上听到收音机说有新的免费移机的套餐(她肯定想上网了,呵),于是我又上021adsl网去查,没有结果,然后就直接问客服。

2号客服给我推荐了1680元1M包年的套餐,说是包含单独接线费、初装费、年费等,于是传资料过去登记。再细问时原来是小区宽带那种,移机的话新地方要有小区宽带才能移,我们现在住的小区好象没有小区宽带(80年代的小区)。后来客服回电话说这个套餐昨天才开始出来,现在还不能登记,所以只能放弃。

www.9orange.com网上去查,打800免费电话问,对方说新安装E8的话,需要出示房东的房产证,说是电信怕房东投诉说末经允许就安装电话,NND,这法又行不通。

快中午饭时2号客服回电话说1680元包年套餐现在不能登记的事,然后我就问新安装E8套餐的事,她说如果在房东的电话上加载的话房东身份证复印件是免不了的,新安装的话需要140元的新装电话费、130元的宽带拉线费、1958元2M年费、160元初装费,我说网上看到的这种情况130元是含在140元里的,也就是说省掉了,为此我还和她争半天,最后说双方再查查看。

打完电话我在http://www.021adsl.com/E8.htm找到不需要130元的证据,又登录在线客服问,这次是11号客服接待,我让她找2号客服,结果她说2号客服不在(我是才挂电话一会的,可能是竞争的原因)。跟11号客服问了情况,她建议我直接给她打电话说,最后确认是没有130元的,同时有身份证复印件和居住证复印件的话可以象本市户口一样安装,不需要预付费,不需要担保,不需要押金,也不需要房东的任何材料。中午吃完饭把材料传真给她,然后她说让等消息。

下午3点过收到电信的电话,让我选号码,然后预约6月1日上午安装,就此了结。在此感谢021adsl的11号客服罗小姐,周日就可以上宽带了,兴奋ing…

 

更晰:6月1日上午10点左右已经完成新电话和ADSL的安装,正在使用中…

宝宝的名字确定了

星期五, 9 5 月, 2008

经过与粥妈讨论,初步确定粥粥的大名。

男宝宝就叫“罗海天”。宝宝属于“海”字辈,粥妈说“天”是“天天向上”的意思。宝宝的哥哥叫“罗海齐”,粥爸立即想到“齐天大圣”,所以觉得“天”字不错也好记,小弟如果也生成个宝宝带“大”或“圣”字样,那啥家就是“齐天大圣”了,呵。

女宝宝就叫“罗嘉苑”。粥妈最初的想法是“罗家园”,听着怎么就象“罗家花园”。然后粥爸想到“罗佳元”,粥妈觉得“元”字不太好,但总得来说确定“jia yuan”两个拼音了。粥妈想到中间的“嘉”字,不错!粥爸想到“嫒”、“瑷”、“苑”等尾字,优先考虑“罗嘉苑”。用粥妈提供的《看谁的名字厉害.xls》拿“罗嘉苑”与粥爸粥妈对战,全是“罗嘉苑”赢,初步确认。

粥妈拿“罗海天”和“罗嘉苑”两个名字去做了测试,“罗海天”得100分,“罗嘉苑”得80分,挺不错的,因此确认了这两个名字。

咳嗽偏方和食疗

星期五, 9 5 月, 2008

止咳偏方
1、可将沸水倒入盛绿茶的茶杯中,口鼻对准杯口呼吸,蒸气吸入,润喉,止咳,化痰。
2、鸡蛋汁加冰糖蒸服,每日一只鸡蛋,分2-3次口服,连服3-5日。

食疗
1、冰糖炖梨:将新鲜的梨去皮,剖开去核,加入适量冰糖,放入锅中隔水蒸软即可食用。
2、烘烤橘子:在橘子底部中心用筷子打一个洞,塞一些盐,用铝铂纸包好之后放入烤箱中烤15-20分钟,取出后将橘子皮剥掉趁热吃。或把橘皮晒干成陈皮,加水煎茶,大口大口喝下,颇具奇效。
3、川贝炖梨:用去皮、去核的新鲜梨加川贝粉2钱,放在锅中隔水蒸软,趁热食用。
4、白萝卜饴:将白萝卜切成1公分大的小丁,放入干燥、干净容器中,加满蜂蜜,盖紧,浸渍3天左右会渗出水分与蜂蜜混合,放入冰箱保存;每次舀出少许加温开水饮用,止咳效果非常好。若临时要喝,没时间浸渍,可将白萝卜磨碎,加1/3量的蜂蜜拌匀,再加温水饮用。
5、糖煮金桔:将金桔洗净,用牙签戳两三个洞,加水淹没煮沸,加入冰糖,用小火熬烂,趁热食用。没喝完的放凉,存入冰箱保存,每次舀一些温热食用。
6、不要吃糖果饼干等甜食,那些冰冷、干,且易上火的食物,如花生、瓜子、油炸物等也应禁止。
7、多喝温开水,将温开水含在口中也有很好的止咳效果。

补充说明
一般来说咳嗽是不能吃鱼和蛋的,但2偏方是可以止咳,所以如果对蛋不过敏的话是可以吃的。

信息来源:bbs.bb06.com/archiver/tid-1195.html

PHP与ASP的差别

星期五, 9 5 月, 2008
最近试着把以前写的ASP小网页改成PHP,网上资料比较集全,所以好多不会的东西都可以从网上搜索得到,现把曾经遇到的差别记录一下。
1.       ASP的语句是“<% … %>”;PHP的语句是“<?php … ?>”。
2.       ASP的Session是“Session(‘…’)”;PHP的Session是“$_SESSION[‘…’]”。
3.       ASP的Request是“Request (‘…’)”;PHP的Request是“$_REQUEST[‘…’]”,PHP的Request还可以分为“$_GET”和“$_POST”两种。
4.       ASP的重定向是“Response.Redirect("login.asp")”;PHP的重定向是“header(‘location: login.php’)”,要求header调用之前不能有任何html的输出,比如PHP语句之外的字符串、PHP的echo或print语句等,PHP的header之后需要exit语句结束当前页面。
5.       ASP没有md5函数;PHP有md5函数,可以直接使用。
6.       ASP的输出用“Response.Write ‘…’”;PHP的输出用“echo ‘…’”或“print ‘…’”或“print_r(…)”。
7.       ASP生成验证码的代码:
<%
Option Explicit
Response.buffer=true
NumCode
Function NumCode()
       Response.Expires = -1
       Response.AddHeader "Pragma","no-cache"
       Response.AddHeader "cache-ctrol","no-cache"
       dim zNum,i,j
       dim Ados,Ados1
       Randomize timer
       zNum = cint(8999*Rnd+1000)
       Session("GetCode") = zNum
       dim zimg(4),NStr
              NStr=cstr(zNum)
              For i=0 to 3
                     zimg(i)=cint(mid(NStr,i+1,1))
              Next
       dim Pos
       set Ados=Server.CreateObject("Adodb.Stream")
              Ados.Mode=3
              Ados.Type=1
              Ados.Open
       set Ados1=Server.CreateObject("Adodb.Stream")
              Ados1.Mode=3
              Ados1.Type=1
              Ados1.Open
              Ados.LoadFromFile(Server.mappath("images/body.Fix"))
              Ados1.write Ados.read(1280)
              for i=0 to 3
                     Ados.Position=(9-zimg(i))*320
                     Ados1.Position=i*320
                     Ados1.write ados.read(320)
              next
              Ados.LoadFromFile(Server.mappath("images/head.fix"))
              Pos=lenb(Ados.read())
              Ados.Position=Pos
              for i=0 to 9 step 1
                     for j=0 to 3
                            Ados1.Position=i*32+j*320
        
                    Ados.Position=Pos+30*j+i*120
                            Ados.write ados1.read(30)
                     next
              next
              Response.ContentType = "image/BMP"
              Ados.Position=0
              Response.BinaryWrite Ados.read()
              Ados.Close:set Ados=nothing
              Ados1.Close:set Ados1=nothing
End Function
%>
还需要外部文件:body.Fix、head.fix。
 
PHP生成验证码的代码:
<?php
// Create image
header(‘content-type: image/png’);
srand((double)microtime() * 1000000);
$img = imagecreate(54, 20);
$black = imagecolorallocate($img, 0, 0, 0);
$gray = imagecolorallocate($img, 127, 127, 127);
imagefill($img, 0, 0, $gray);
while (($code = rand() % 100000) < 10000);
$_SESSION[‘getcode’] = md5($code);
 
// Write code to image
imagestring($img, 5, 6, 3, $code, $black);
for($i = 0; $i < 200; $i++)
{
       $randcolor = imagecolorallocate($img, rand(0, 255), rand(0, 255), rand(0, 255));
       imagesetpixel($img, rand() % 70, rand() % 30, $randcolor);
}
imagepng($img);
imagedestroy($img);
?>
php.ini文件需要把“;extension=php_gd2.dll”之前的分号删除,以支持imageXXX函数。
 
8.       ASP的Session默认情况就启用;PHP的Session默认情况未启用,启用方法是打开php.ini文件,找到“session.save_path”,在E:\php5.2新建一个目录tmp,把“session.save_path”的值设成tmp目录,比如:session.save_path = "E:/php5.2/tmp",如果想让Session自动启用则设置“session.auto_start”的值为1(默认值是0),否则需要调用session_start方法启用Session。

Apache+PHP+MySQL配置

星期四, 8 5 月, 2008
出于好玩,也想试试基于PHP的Web开发,在网上搜到相当多的这方面的文章,其中Apache+PHP+MySQL是最适合的搭配,主要原因是全部免费。
根据别人的文档加上自己的实践,现以成功配置,在这里把自己所做的用简单的文字记录一下,便于以后自己翻出来用用,也希望能给别人一些参考。
本次只在Windows系列下完成配置,Linux或其它的配置以后有空再玩玩。
 
首先是软件的准备:
apache_2.2.8-win32-x86-openssl-0.9.8g.msi   来源:Apache.org
php-5.2.6-Win32.zip     来源:php.net
mysql-5.0.22-win32.zip 来源:mysql.com
 
1.    安装并配置Apache
直接双击安装包,为了方便管理我选择安装到E:\apache2.2目录。
Server Information窗体可以根据需要随便输入,可以是无效的字符串,不过最好是符合它的格式,比如Network Domain我输入“lordong.cn”、Server Name我输入“home.lordong.cn”、Administrator’s Email Address我输入“webmaster@lordong.cn”。
选择“for All User, on Port 80, as a Service — Recommended”项,如果之前安装了IIS占用了80端口,想配置Apache使用8080端口,可以先把IIS服务停掉然后继续安装而不要选择“only for the Current User, on Port 8080, when started Manually”,因为后者不会将Apache安装成服务(手动启动,不方便)。可以在安装完之后再修改配置文件使用8080端口,而IIS继续使用80端口。
安装完之后Apache服务自己启动,可以在浏览器中输入“http://127.0.0.1,如果成功安装的话会显示内容“It works!”的简单页面(以前的版本显示内容比较多的页面)。
安装后在程序组菜单里会多出一项“Apache HTTP Server 2.2,选择“Configure Apache Server”菜单下的“Edit the Apache httpd.conf Configuration File”打开配置文件E:\apache2.2\conf\httpd.conf,然后分别修改:
1)     修改端口:把“Listen 80行改为“Listen 8080”行即可。
2)     修改Web根目录:比如我想把Web根目录放在F:\Webs目录下,则把“DocumentRoot "E:/apache2.2/htdocs"”行改为“DocumentRoot "F:/Webs"”、“<Directory " E:/apache2.2/htdocs ">”行改为“<Directory "F:/Webs">”即可。
修改好后重启Apache服务,在浏览器中输入“http://127.0.0.1,如果F:\Webs目录下是空的会看到内容是“Index of /”的简单页面。
 
2.    安装并配置PHP
直接把zip文件解压到需要安装的位置,为了方便管理我解压到E:\php5.2目录。
E:\php5.2目录下的“php.ini-dist”改名为“php.ini”,这就是php的配置文件,双击打开进行配置。
现在将PHP以module方式整合进Apache:
1) 打开Apache的配置文件,在已有的“LoadModule”之后添加两行:
LoadModule php5_module E:/php5.2/php5apache2_2.dll
PHPIniDir "E:/php5.2"
其中第一行是指定Apache加载的PHP Module,这里Apache是2.2版本,PHP是5版本,所以选择“E:/php5.2/php5apache2_2.dll”,第二行指定“php.ini”的路径。
2) 在“AddType application/x-gzip .gz .tgz”之后添加三行:
    AddType application/x-httpd-php .php
    AddType application/x-httpd-php .html
    AddType application/x-httpd-php .htm
说明“.php”、“.html”、“.htm”文件使用“application/x-httpd-php”加载,即上面的php5_module,也可以添加其它类型。
3) 修改DirectoryIndex,增加默认的通过目录访问打开的文件顺序,即默认主页顺序,这里把“index.php”放到最前面“DirectoryIndex index.php index.asp index.html index.htm”,当然也可以根据需要定义成其它的文件或顺序。
4) 为了Apache能加载PHP及PHP的扩展模块,把“E:\php5.2和“E:\php5.2\ext”路径添加到系统路径。为了让Apache服务能够从系统路径找到欲加载的模块,这时应该重新启动机器。(注:修改系统路径后必须重启机器服务才能使用新添加的路径)
 
3.    安装并配置MySQL
解压zip包,双击运行解压出来的“Setup.exe”进行安装,在“MySQL.com Sign-Up”页选择“Skip Sign-Up”继续,在最后一页钩选“Configure the MySQL Server now”,然后进行MySQL的配置:
1) 在configuration type页选择“Detailed Configuration”。
2) 在server type页选择“Server Machine”。
3) 在database usage页选择“Transactional Database Only”。
4) 在InnoDB Tablespace Settings页保持默认项。
5) 在concurrent connections页选择“Online Transaction Processing (OLTP)”。
6) 在networking options页选择“Enable TCP/IP Networking”,默认端口保持不变,其它选项也保持默认。
7) 在default character set页选择“Manual Selected Default Character Set / Collection”项并选中“gbk”字符集。
8)接着选择“Install As Windows Service”并钩选“Launch the MySQL Server automatically”。
9) 钩选“Include Bin Directory in Windows PATH”。
10) 钩选“Modify Security Setting”,输入超级管理员root用户的密码, 根据情况决定是否钩选“Enable root access from remote machines”。
接着配置在PHP中配置MySQL的支持:打开php.ini,把“;extension=php_mysql.dll”和“;extension=php_mysqli.dll”前面的分号去掉,重启Apache即可支持MySQL。
 
更多的图标内容参见网友的贴子:http://www.qqread.com/php/n652282101.html

CListCtrl在LVS_SMALLICON模式下显示不正常的解决办法

星期四, 8 5 月, 2008

前段时间写的贴子《CListCtrl在LVS_ICON和LVS_SMALLICON模式下的显示问题》解决了CListCtrl在LVS_ICON和LVS_SMALLICON两种模式下插入记录不正常显示的问题,但有个问题当时没有发现:在LVS_SMALLICON模式下,当数据点的标签比较长时,左边的标签就覆盖了右边的图标和标签,如下图:

试了好几种方法:
m_lvwAlarmList.Arrange(LVA_DEFAULT);
m_lvwAlarmList.RedrawItems(0, m_lvwAlarmList.GetItemCount());
m_lvwAlarmList.RedrawWindow();
m_lvwAlarmList.UpdateWindow();

m_lvwAlarmList.ModifyStyle(LVS_TYPEMASK, LVS_ICON, 0);
m_lvwAlarmList.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON, 0);
只有最后两句一起用时才有效,只用上面的4句仍然无效。

最后通过观察资源管理器的情况,使用LVS_LIST来替找LVS_SMALLICON来解决这个问题的:
把“m_lvwAlarmList.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON, 0);”改成“m_lvwAlarmList.ModifyStyle(LVS_TYPEMASK, LVS_LIST, 0);”。

发贴的链接与上回的贴子是同一个。

刚升级完洗衣机

星期五, 2 5 月, 2008

2004年1月,在住满半年的情况下跟房东要了个洗衣机,房东从二手市场花了230元买了个波轮全自动洗衣机,刚拿来时试的好好的,第二天准备用时不行了,后来让二手市场的换了一个能用的。

用了没多久又出问题了,卖家来了个人用吹风机吹干控制板里的线路板就好了(地方有限制只能安装在厕所,洗澡的旁边,每次洗完澡必湿)。后来再出现这种情况,有时是造成短路全屋断电,都是自己用吹风机搞定的。

发现最容易坏的地方就是水位调节阀,每次洗完澡水位调节阀旋钮总是湿漉漉的,长年累月就生锈然后不工作了。曾经花了20元从二手市场买过一个水位调节阀来自己换上,一年前那个水位调节阀又不好好工作了,往里面滴点机油,有时用牙签往阀里面捅让阀能恢复控制,这么用了半年后就不再好使了。然后改成不用水位调节阀了(到二手市场问过还是20元一个),自己把两根线引出来,用个手动开关接上,然后这个洗衣机彻底的变成了半自动洗衣机,使用过程经常忘了拨动开关通或断(相当于水位调节阀的水位到位或水位下降断开)而导致桶内水漫出来(开关没通上相当于水没有到位,总在放水)或没能甩水然后报警(开关没断开相当于水位没有下降到断开状态,总在排水)。

长痛不如短痛,反正都是生活嘛,租房子也是生活,干嘛不过得好点呢,索性就花点钱买个新的。

4月27日,在苏宁电器买了一个西门子的WM 1078XS滚筒全自动洗衣机,因为五一搞活动可以比平时少200元,还价时又让他们想办法把零头90元省掉,最后的卖价是2400元(标价是3099元,平时的卖价是2690元,售货员拿了个清单给我看的,也不知道真的假的,但能少点则少点),还送了个锅。

由于买洗衣机的店没货,他们改成从浦西调货,只能5月1日送过来。

昨天中午的时候送到了,可送货的不负责安装,打售后服务电话,说是没有预约当天下午没办法安排人过来安装,得安排到今天下午了。哪能等得了呀,老洗衣机自从4月26日最后一次用后再也不想用了(想等新的一块洗),衣服已经堆了一大堆了。跟售后服务接电话的问情况决定自己动手安装,更何况说明书也都写着呢。一切顺利,已经连洗了两天的衣服,把冬天的衣服也都洗了,好收起来。

说明一下,我在拿到洗衣机之前就估计好距离自己从网上买了插座和进水管了,不然的话安装也不会那么顺利。西门子洗衣机自带的进水管根本不适合现在常用的洗衣机专用水龙头,不过排水管长度刚好用。

买洗衣机那天才发现滚筒洗衣机的排水管是从上面出来的,根据水往低处走的原则,自己估计是带有排水泵的,说明书里确实有一节说关于清洗排水泵的,这种设计很适合排水口在洗衣机底部以上的情况。老式的波轮就不适合这种了,所以我这里老洗衣机得放厕所里,用砖块垫高(为此洗衣服时还倒过好多次),现在的新洗衣机改放到厕所外面了。

用了两天的感觉是很不错,用的水不是很多,衣服少也能洗,以后就不会有堆衣服到周末一块洗的情况了,生活会越来越方便了。

粥粥的姓名打算用“罗海天”了

星期六, 26 4 月, 2008

歪歪同学不知从哪弄了个《看谁的名字厉害.xls》的文档,用它分别拿粥粥小朋友与爸妈对战,竟然爸妈全被打败了,呵呵

粥粥小朋友与老爸的对战记录:

粥粥小朋友与老妈的对战记录:

“罗海天”的名字不错,重名也不少,可这年头不重名的可太少了,只要跟屯里两三百号人不重名就行了,管他呢,这些先落一脚。

WTL::CListViewCtrl动态显示Tooltip的实现

星期四, 13 3 月, 2008

在WTL::CListViewCtrl控件实现Tooltip显示的实例:

1. 从CListViewCtrl类重载,创建CTooltipCtrl控件,处理鼠标事件。

重载类头文件:
class CListViewCtrlTip : public CWindowImpl<CListViewCtrlTip, CListViewCtrl>
{
public:
 CListViewCtrlTip()
 {
  m_nCurItem = -1;
  m_dwCurItemData = 0;
 }

 BEGIN_MSG_MAP(CListViewCtrlTip)
  MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
  MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
 END_MSG_MAP()

 LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
 LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

 void Attach(HWND hWnd);
 void Detach();
 void DeactivateTip();
 int GetCurItem()
 {
  return m_nCurItem;
 }

 DWORD GetCurItemData()
 {
  return m_dwCurItemData;
 }

private:
 CToolTipCtrl m_ctrlTip;
 int m_nCurItem;
 DWORD m_dwCurItemData;
};

重载类实现:
void CListViewCtrlTip::Attach(HWND hWnd)
{
 // Use subclass window to support message event instead of attach
 if (CWindowImpl<CListViewCtrlTip, CListViewCtrl>::SubclassWindow(hWnd))
 {
  m_ctrlTip.Create(m_hWnd);
  m_ctrlTip.Activate(FALSE);
  m_ctrlTip.AddTool(m_hWnd);
  m_ctrlTip.SetMaxTipWidth(260); // Set the max tip width to 260 characters
  m_ctrlTip.SetDelayTime(TTDT_AUTOPOP, 10000); // Set auto pop delay time to 10s
 }
}

void CListViewCtrlTip::Detach()
{
 if (::IsWindow(m_hWnd))
 {
  m_ctrlTip.Activate(FALSE);
  m_ctrlTip.DelTool(m_hWnd);
  CWindowImpl<CListViewCtrlTip, CListViewCtrl>::UnsubclassWindow(TRUE);
 }
}

void CListViewCtrlTip::DeactivateTip()
{
 m_nCurItem = -1;
 m_dwCurItemData = 0;
 m_ctrlTip.Activate(FALSE);
}

LRESULT CListViewCtrlTip::OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
 MSG msg = { m_hWnd, uMsg, wParam, lParam };

 if (m_ctrlTip.IsWindow())
 {
  m_ctrlTip.RelayEvent(&msg);
 }
 bHandled = FALSE; // Leave the message to next case

 return 0;
}

LRESULT CListViewCtrlTip::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
 int xPos = GET_X_LPARAM(lParam);
 int yPos = GET_Y_LPARAM(lParam);
 POINT pt = { xPos, yPos };
 int nCurItem = HitTest(pt, NULL);
 
 // Check and active the tool tip control
 if (nCurItem >= 0)
 {
  if (m_nCurItem != nCurItem)
  {
   m_ctrlTip.Activate(FALSE); // Deactivate first
   m_nCurItem = nCurItem;
   m_dwCurItemData = (ULONG)GetItemData(m_nCurItem);
   m_ctrlTip.Activate(TRUE);
  }
 }
 else
 {
  DeactivateTip();
 }
 bHandled = FALSE; // Leave the message to next case

 return 0;
}

2. 修改调用类中CListViewCtrl类型为重载的类型,在初始化函数中调用Attach方法,在OnDestroy调用Detach方法。

CListViewCtrlTip m_lvw;

m_lvw.Attach(GetDlgItem(IDC_IST));

m_lvw.Detach();

3. 调用类处理TTN_GETDISPINFO通知,更新Tooltip的数据。

char m_szCurToolTip[MAX_TOOLTIP_LEN];

LRESULT CTestDlg::OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam,
          BOOL& /*bHandled*/)
{
 switch (((LPNMHDR)lParam)->code)
 {
 case TTN_GETDISPINFO: // Notify event from list view control to get the tool tip string
  LPNMTTDISPINFO pInfo = (LPNMTTDISPINFO)lParam;
  // Make dynamic tool tip string here
  pInfo->lpszText = m_szCurToolTip;

  break;
 }

 return 0;
}