200分求应用皮肤技术的窗口设计思路 (200分)

  • 主题发起人 主题发起人 苦海无边
  • 开始时间 开始时间

苦海无边

Unregistered / Unconfirmed
GUEST, unregistred user!
毒霸漂亮的界面,瑞星可更换皮肤的功能。
现在,界面个性化已经成为潮流。
小弟求此方面开发经验。原理、技术手段等。
以前没有这方面的经验,还请从基础指教。
感激不尽!
 
贴个文章给你:
软件SKIN技术探秘


  大家都知道,用户界面是一个软件的面子,界面好不好往往决定了一个软件的成功与否。我知道曾经有一个程序高手,作了一个非常实用的软件,但基本上没有什么界面,只是一个简单的基于对话框的应用程序。结果软件上传到Download.com和HOTFiles.com时,什么好评价也没有得到,Tucows.com甚至不肯收录该软件。一位用户email说,"A good interface will lead you to a wonder" (一个好的用户界面会给你带来奇迹)。于是他下决心改进用户界面,花钱请美术高手设计了一个很酷的界面,再投放到那些下载网站上,结果在HotFiles上得了4个星,Tucows上得了4头牛。

  好了,下面就言归正传,我要说的是当你请人设计了一个很酷的界面图片后,怎么把它集成到你的程序中去?相信很多人用过OICQ,它采用了一种称作“skin(皮肤)”的技术,

  界面比较华丽。实际上到它的程序目录里看一看,就会发现它的界面用到的图片都放在skins目录下。下面我就分析一下这些图片是怎么贴到程序窗口中去的。当然这里的分析并非针对oicq,但我想原理大同小异,不同的只是实现细节。限于小生才疏学浅,如果本文有何不妥,欢迎指正。

  首先,制作一张图片,它用来做你的程序正常显示时的skin。我们姑且称它为main.bmp。

  因此,你想象中你的程序界面是什么样子,那么图片就应是什么样子。如果你的程序需要按钮、标签等控件,在这幅图中应该把它们画出来。下图是一个MP3播放程序的界面,图中画出了所打算实现的各种控件。我想不用我一一解释了吧。
  下面还要画两张图,称为over.bmp和selected.bmp。前者用于指出鼠标移动到某个控件上面时,控件的外观(appearance)应该是什么样子;相应地,后者用于指出鼠标选中某个控件时,控件的外观应该是什么样子。这两张图中,控件的布局(指控件的坐标、尺寸)安排应该与main.bmp相同,只是在控件的外观上有些变化,以造成控件的动态效果
  最后一张图片是mask.bmp,它用来创建一个区域(region)对象(利用api CreateRectRgn),基于此区域可以实现不规则程序窗口(利用api SetWindowRgn)。生成该图片的办法是main.bmp中深色的部分全涂位黑色,其余部分为白色,黑色部分其实就是你的程序窗口最后的轮廓(另外可以在程序中生成mask.bmp,办法是把main.bmp拷贝成一个单色位图)。利用这种方法,你的程序可以是任意不规则窗口,它只局限于你的想象力。(这里就不贴出来了,否则有赚稿费之嫌)

  自然地,你会想到怎么在程序中把各种相关控件的信息从图片中提取出来呢?在这里我们的办法是预先提取出各种信息并存入一个名为skin.ini的文件中,程序中读取该文件即可。提取办法很不好意思是手工提取,比如需要某个按钮在窗口中的坐标信息,就在一个图形编辑器里确定它在图片中的坐标,然后手工写入skin.ini。这样虽然比较麻烦,一般来说还是可以忍受的。(当然可以制作一个工具来生成skin.ini,那位朋友感兴趣可以一试。)这里给出基于上述图片的一个skin.ini:



[SCREEN]

Mask=Mask.bmp

Main=Main.jpg

Down=Selected.jpg

Over=Over.jpg

Disabled=Main.jpg


[BUTTONINFO]

1=BUTTON_EXIT,349,8,17,17,关闭窗口,FALSE

2=BUTTON_MINIMIZE,342,7,17,17,最小化,FALSE

3=BUTTON_SAVEEQ,312,184,39,34,,FALSE

4=BUTTON_LOADEQ,271,184,39,34,,FALSE

5=BUTTON_USEEQ,234,184,39,34,,TRUE

6=BUTTON_LAST,341,143,35,30,最后一首,FALSE

7=BUTTON_NEXT,304,143,35,30,Sonraki,FALSE

8=BUTTON_PREV,267,143,35,30,謓ceki,FALSE

9=BUTTON_STOP,342,105,37,30,停止播放,FALSE

10=BUTTON_PAUSE,305,105,37,30,暂停,FALSE

11=BUTTON_PLAY,268,105,37,30,播放,FALSE

12=BUTTON_FIRST,230,143,35,30,第一首,FALSE

13=BUTTON_EJECT,231,105,37,30,弹出,FALSE

14=BUTTON_MENU,12,8,17,17,菜单,FALSE


[PROGRESSINFO]

1=PROGRESS_POS,进度,12,66,371,28,V

2=PROGRESS_VOL,音量,16,94,103,37,V


[TEXTINFO]

1=TEXT_POS,Arial,TRUE,FALSE,-13,65535l,310,46,54,14,

2=TEXT_LEN,Arial,TRUE,FALSE,-13,65535l,260,46,54,14,

3=TEXT_HINT,Arial,FALSE,FALSE,-13,0l,19,46,200,14,

4=TEXT_SONG,Arial,FALSE,FALSE,-13,0l,19,25,352,14,

  可以看出,该文件主要存储了所需要的图片的文件名,以及各个按钮的名称、坐标以及提示信息(tool tip)等等,其实具体存储哪些信息可由程序员自己定义,比如你当然可以存储菜单的颜色(oicq中就是这样存的)。

  好了,原材料都准备好了,下面就看怎么加工了。

  程序开始执行后,我们处理WM_INITDIALOG消息,根据mask.bmp生成一个区域,并基于此区域使窗口不规则化。然后在处理WM_PAINT消息时把main.bmp贴到窗口中,这时我们的窗口实际上已经穿上了一层漂亮的skin。但它还不能响应用户事件。要想具备响应能力,下面有两种方案:

  第一种:这种方案生成了一系列控件窗口。

  根据skin.ini中存储的各控件的坐标,生成窗口(按钮、标签等等),设置其属性位自绘(OWNERDRAW),并将它们子类化(SUBCLASS),使之响应WM_DRAWITEM(某些窗口如按钮、菜单等)或者WM_PAINT消息。在这些消息的处理函数里面根据窗口的当前状态(鼠标未移动到窗口、鼠标移动到窗口中和鼠标选中)从相对应的图片(main.bmp、move.bmp和select.bmp)中提取出相应的小图片(即控件对应的图片)。提取方法是根据skin.ini保存的窗口坐标,用BitBlt函数从源图贴到控件窗口中。还要响应鼠标事件,在响应函数里面除了上述的外表绘制工作外,还应加入实际应用有关的处理。

  第二种:这种方案并不生成任何控件窗口。

  在程序的主窗口的窗口函数里响应鼠标事件,当鼠标移动到某个“控件”(实际上是控件所在的矩形区域,区域的坐标可以从skin.ini里得到)里面时,从move.bmp中提取出对应“控件”的小图片,在“控件”所在位置加以显示。提取办法与第一中方案相同。同样地,当鼠标选中某个“控件”时,则从select.bmp中提取出对应“控件”的小图片,在“控件”所在位置加以显示。

  好了,到现在我们对skin技术已经有了一定的了解。可以看出,其实现原理实际上并不困难,我们完全可以做到。当然,有些skin的实现与这里所说的看起来是不相同的,它们既没有图片,也没有skin.ini,其实它们只不过把图片放到程序的资源中去了,控件的坐标信息放到程序中去了而已,归根结底原理是大同小异的。本文偏重原理分析,如果有机会我会做一个例子来加以说明。

 
delphi现成的skin控件已经不少了,还都是成套的,呵呵
 
元元他哥
你说的控件是什么?
 
继续等待高手充实该问题!
 
元元他哥,呵呵
 
我也想知其所以然~~~~~~~~~~~~~
 
到PlayIcq,51delphi上到处都是
 
请高手们赐教。
如果像上面那三个楼层,就不要发言了
 
我有,你要控件联系我,VCL SKIN 很好用。不用改你以前的任何代码。
bill_won@hotmail.com
最好加我到MSN MESSENGER里面,我人在线,这里再线。
发邮件也可以。
 
cnsandboy给我提供的资料真是不错,
我希望高手们提供一些类似的材料或是自己的开发经验。
 
皮肤!皮肤!
一般来讲就是背景图形!
改变背景即可实现简单的皮肤更换!
提!向上!
 
最好的答案
根据上边朋友提供的线索 下载他们 品茶般品代码
 
去 www.51delphi.com 下载ThemeEngine 3.5.6 或BusinessSkinForm 2.0,可以解决你的问题。好象1stclass 4000.01 也行。
 
谢谢,结贴了。看来,好的界面,首先要有好的控件。
不用控件,会累死人。
 
多人接受答案了。
 

Similar threads

D
回复
0
查看
1K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
后退
顶部