选择显示字体大小

visual c++实现定制标题栏


  要想用vc编写出一个漂亮的界面通常是比较费时的,主要原因有两个,一是vc中自带的组件少而不亮,二是无法进行可视化设计。不过,这些都只是针对常用的方法罢了,如果你采用子类化,钩子等技术,可以完全改变这处局面,甚至比delphi等rad工具还要快.本文中就将介绍如何编写一个dll,如何来轻松的定制标题栏。

  为了使每个窗体的标题栏都能定制,并且不用为每一个窗体类编码,所以本方法采用钩子技术,其核心思想是监控 windows 消息,处理需要重缓标题的消息,以达到定制标题栏的思想。

  本文件介绍的方法将在应用程序中安装 wh_callwndproc 钩子,具体的代码如下所示:

  在应用程序启动时安装钩子的代码:

extern "c" bool __declspec(dllexport) installcallwndhook()
{
 g_hcallwndproc = setwindowshookex(wh_callwndproc, callwndproc, afxgetinstancehandle(),getcurrentthreadid());
 if (null == g_hcallwndproc)
  return false;
 else
  return true;
}

  installcallwndhook() 函数定义为出口函数,在需要定制标题的程序中将调用它,由于安装的是 wh_callwndproc 钩子,所以在应用程序调用自己的窗体过程之前,总会先调用 callwndproc;如果设置为 wh_callwndprocret 则顺序刚好相反
g_hcallwndproc为一内存共享变量,其它定义的方法如下所示:

#pragma data_seg("shared")
static hhook g_hcallwndproc;
#pragma data_seg()

  当然你也可以定义为其它形式,比如直接采用共享内存api创建方式。

  在应用程序退出时安装卸载钩子的代码:

extern "c" void __declspec(dllexport) uninstallcallwndhook()
{
 if (g_hcallwndproc != null)
 {
  unhookwindowshookex(g_hcallwndproc);
  g_hcallwndproc = null;
 }
}

  定制标题栏的入口函数为 callwndproc(),其代码如下:

lresult __declspec(dllexport) callback callwndproc(
int code, // hook code
wparam wparam, // undefined
lparam lparam // address of structure with message data (cwpstruct)
)
{
 dword dwthreadid = (dword)wparam;
 lpcwpstruct pcwpstruct = lpcwpstruct(lparam);
 if (hc_action == code)
 {
  if ((pcwpstruct->message == wm_mousemove)
    (pcwpstruct->message == wm_setcursor)
    (pcwpstruct->message == wm_nchittest)
    (pcwpstruct->message == wm_kickidle)
    (pcwpstruct->message == wm_ncmousemove)
    (pcwpstruct->message == wm_mouseactivate)
    (pcwpstruct->message > wm_user));
  else
   drawframe(pcwpstruct);
 }
 return callnexthookex(g_hcallwndproc, code, wparam, lparam);
}

  上面代码中的 if 语句主要用来判断收到哪些消息时需要重绘标题栏,有兴趣的朋友可以对这段代码进行改进。

  在函数 drawframe 中将实现对窗体标题栏和边框的绘制,标题的绘制有两种方法,一是直接画图,二是贴图的方式。在本文中将实现两种方法,如果在当前目录下有 active.bmp 和 inactive.bmp 两个文件,则采用它们所代表的位图作为窗体的标题栏,否则采用画图的方式。

  由于只绘制标题栏,所以需要对 callwndproc 进行过滤,对于非窗体如 button 则不进行绘制,本文中仅以如下简单的方法来处理:

char szclassname[128] = {0};
::getclassname(pcwpstruct->hwnd, szclassname, sizeof(szclassname));
if (strcmp(szclassname, "#32770") != 0)
return ;

  实际中不能这样中,因为很多窗体的类名可能不是"#32770",比较好的方法建议去判断 pcwpstruct->hwnd 所代表的对象是否有父窗体,调用 getparent 判断一下即可。

  在正式绘制之前还必须判断窗体是处于活动状态还是非活动状态,这样就可以区分在两种不同的状态下绘制不同的标题栏和边框了。

  下面这段代码就是用来绘制标题栏的:

if (bactive)
 hbitmap = (hbitmap)::loadimage(null, _t("active.bmp"), image_bitmap, nwidth, nheight, lr_loadfromfile);
else
 hbitmap = (hbitmap)::loadimage(null, _t("inactive.bmp"), image_bitmap, nwidth, nheight, lr_loadfromfile);

if (null == hbitmap)
{
 drawtitlebar(dcwin, rcncclient, 0);
}
else
{
 dcmem = ::createcompatibledc(dcwin);
 holdbitmap = (hbitmap)::selectobject(dcmem, hbitmap);

 ::stretchblt(dcwin,0,0,nwidth, nheight,dcmem,0,0,nwidth, nheight,srccopy);

 ::selectobject(dcmem, holdbitmap);
 ::deletedc(dcmem);
}

  其中变量bactive为true时表示窗体处于活动状态,为false时表示窗体处于非活动状态。两个 loadimage 函数分别用来将两种状态下的位图装载到内存中,以便下一步进行贴图.当 loadimage 不成功时,表示当前目录下没有 active.bmp 和 inactive.bmp 文件中或文件格式不正确,在这处情况下就调用 drawtitlebar 函数对标题栏进行绘画。绘画的方法可以随便,但要绘在矩形 rcncclient 内,因为这个矩形就是标题栏所在区域。

  如果 loadimage 成功,则直接将位图贴到标题栏中。接下来就是绘制边框了,在绘制之前还需要计算出边框的所在矩形,然后再在dcwin上按要求进行绘制即可。完整的示例源代码请到 http://www.megspace.com/computers/bigtime/custtitlebar.htm 上下载(注意:由于申请的是国外免费空间,所以需要将浏览器的编码改为“简体中文”),解压后运行即可看到示例的所述界面

  这种方法的关键地方是安装合适的钩子,然后对合适的消息进行处理,采用这种方法可以改变几乎任何一可见窗体的外观,包括其它程序的窗体等,对于特殊的窗体等只需要进行专门处理即可。

  由于编译成的是 dll 文件中,所以可以很轻松的运用到其它程序中。只需要在需要用到的程序中调用 installcallwndhook 安装这个钩子即可。


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons