抛弃 Delphi 4年后由于工作关系,又重新开始使用这个工具。为了尽快找回感觉,花了1天半时间试手写了一个类,只提供一个看上去很愚蠢的功能, 那就是能让form产生类似Vista和Win7中窗口的那种阴影, 呃, 加一点点微不足道的扩展--对不规则形状窗口照样有效. 效果还可以:
源代码:
http://download.csdn.net/sort/tag/Delphi/1168由于是试手作品,所以源码当中没有注释。为了便于大家理解,我这里说一下设计思路:
原理极简单:偷偷生成一个新的带Layered属性的窗口,比目标Form大一圈,然后悄悄插到目标Form后边,位置几乎重叠稍稍偏出一点,然后保持一直躲在那。
这个新窗口通过API UpdateLayeredWindow() 设置了一幅带per pixel alpha channel的动态生成的32位bmp。这个bmp其实就是阴影啦。总的来说,实现起来还是比较容易没什么难度的。
代码当中稍微值得显摆一下的也只剩下这个32位bmp的生成和更新时机而已。
生成时首先用黑色充填整个bmp, 然后试图用GetWindowRgn()获取目标窗口的region, 如果有,那么用白色将这个region画到bmp合适位置上,没有region则用白色画一个方形(比窗口大一点点,原因后面会说到), 接着判断目标Form是否使用TransparentColor,如果用了,那说明目标也可能不那么规矩是个异型,呃,窗口。接下来就要想办法获取这个形状,这步是通过Form.PaintTo画到一个临时的tempbmp上,然后调用tempbmp.Mask(Form.TransparentColorValue)生成黑白图,将其画到32位bmp相应位置上。这步后有棱有角的阴影已经生成,接着逐像素处理bmp模糊化所有棱角和边框(为了追求速度,这段模糊化代码有个很不好的习惯, 那就是不规则图案看上去是向外圈扩张模糊的,而方形却是向内部收缩模糊, 这也就是为什么对规规矩矩的Form我们画阴影时要大上一圈的原因)。至此,阴影图案已经生成完毕。 不过这个只是24位的阴影,我们还需要将它扩展到32位的。因为我们刚才画的都是黑白色,因此每个像素中的rgb值正好都相等,我们只要逐像素过一遍,将该像素rgb中的任意一个复制到alpha位,并在复制的同时顺手将rgb颜色值改成设置的阴影颜色即可大功告成。最后将目标Form.AlphaBlendValue也顺过来一起调用UpdateLayeredWindow()更新界面. 好了, 酷酷胖胖的阴影就出现在屏幕上了.
为了保证我们的阴影窗口一直躲在目标Form下正确的位置上并保持正确的形状,我们还需要截获目标Form移动,改变大小和ZOrder变化的消息并对我们的阴影Form进行相应操作(需要判断是偷偷跟着一起跑就够了还是要重新生成). 为了省事, 在我们的阴影控件初始化时就偷换了目标Form.WindowProc,这样目标Form所有的消息都会先被我们得到. 我们感兴趣的其实只有两个消息--WM_WINDOWPOSCHANGING和WM_WINDOWPOSCHANGED, 因为所有目标Form位置,大小, 显示/隐藏等变化都会通过这两个消息得到反映。其实我们真正感兴趣的只有一个:WM_WINDOWPOSCHANGED, 此时对阴影进行调整就足够了。截获WM_WINDOWPOSCHANGING的目的是为了在目标窗口最大/最小前我们可以先一步隐身(为了执行效率,最大化时不生成阴影--因为大部分跑屏幕外边去了看不见),省得在目标Form往任务条上跑时我们的阴影还傻傻待在原地造成走光。还有,使用这玩意还是比较简单的, 如果你想哪个Form飘起来,只要uses ufrmShadowFrame; 然后在Form.OnCreate中创建一个 Shadow := TFormShadow.Create(Application); Shadow.ParentForm := Self; 再在需要它起作用时设置Shadow.Active := True; 就行了。
BUT! 千万不要在Form.OnShow中调用Active := True; 如果你设置了TransparentColor, 那么就会得不到正确的阴影, 因为在OnShow中无法用Form.PaintTo()得到正确的界面图片.最后, 我没有把它写成一个component而是做成一个需要你手工写代码调用的类. 因为我最讨厌的事就是: 为了阅读某个人写的程序, 我不得不安装一大堆我从来都用不上的控件, 还常常遇到它用的是针对某个版本delphi的没有源码地控件, 为了5分钟的阅读我可能要花几个小时才能建立起相同的编译环境才得以顺畅地看到对方的代码, 大多看完的感觉却是:"没这么玩人的".因此, 我不玩你.

解决方案 »

  1.   

    源代码地址错误~~~这个才是
    http://download.csdn.net/source/1576318
      

  2.   

    用Delphi 2007 打开 提示缺少Unit2.pas 把Unit2.pas 去除,成功运行!
    很好玩!
      

  3.   

    支持
    能继续使用delphi
      

  4.   

    这么多人啊.......
     恋爱兵法32集高清晰下载http://www.dingweiqi.net/forum-11-1.html
      

  5.   

    不愧是学了四年的Delphi。比起我们学了以年的不只强了多少倍
      

  6.   

    今天仔细读了下程序,很简捷扼要。自己做了个Demo,发现在移动窗口或调整窗口大小时,有时阴影大小会算错。不知什么原因,是否还需要捕获其它Windows消息?楼主可否赐教?