笔记(转载) - jues

linux下面禁止ipv6的方法

linux下面禁止ipv6的方法:
来自: 杨志刚 博客 (http://yangzhigang.cublog.cn)
 
这里我所做的是Redhat Linux,在系统中ifconfig或是netstat -an都会显示出IPV6的结果,如:
[root@WebServer-22 conf]# ifconfig
eth1      Link encap:Ethernet  HWaddr 00:15:C5:EF:74:1C 
          inet addr:192.168.102.22  Bcast:192.168.102.255  Mask:255.255.255.0
          inet6 addr: fe80::215:c5ff:feef:741c/64 Scope:Link
 
[root@WebServer-22 conf]# netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address            
tcp 0 576 ::ffff:192.168.102.22:22    ::ffff:192.168.12.100:3339  ESTABLISHED
tcp 0 0   ::ffff:192.168.102.22:80    ::ffff:192.168.102.25:36479 TIME_WAIT  
tcp 0 0   ::ffff:192.168.102.22:80    ::ffff:192.168.102.25:36503 TIME_WAIT  
 
在IPV6还没有广泛使用时,这有些不方便,那么在Redhat Linux下禁止IPV6的方法也很容易:
vi /etc/modprobe.conf,加入以下两行参数,
alias net-pf-10 off
alias ipv6 off
之后reboot。(注:用service network restart是不可以的)
 
重启之后,ifconfig或netstat -ant等只能显示IPV4的地址信息了。
 
对于其他的系统,可以参照以下文档:
Here's the summary of what I can think of, with alternate methods in case the first one doesn't work with you:

Debian kernel 2.4:
  • In /etc/modutils, change the line
    alias net-pf-10 ipv6
    to
    alias net-pf-10 off
    alias ipv6 off
  • Reboot.
Debian kernel 2.6/Ubuntu ("official" method)/Fedora Core (method 1):
  • In /etc/modprobe.d/aliases, change the line
    alias net-pf-10 ipv6
    to
    alias net-pf-10 off
    alias ipv6 off
  • Reboot.
Debian kernel 2.6/Ubuntu (alternate method):
  • In /etc/modprobe.d/blacklist, add a line
    blacklist ipv6
  • Reboot.
RHEL/CentOS:
  • In /etc/modprobe.conf, make sure you have
    alias net-pf-10 off
    alias ipv6 off
  • Reboot.
RHEL/CentOS/Fedora Core (method 2)/Mandriva (method 1):
  • In /etc/sysconfig/network, add a line
    NETWORKING_IPV6="no"
  • Reboot.
SuSE 9.0:
  • In /etc/modules.conf, change the line
    alias net-pf-10 ipv6
    to
    alias net-pf-10 off
    alias ipv6 off
  • Reboot.
SuSE 9.1/9.2/9.3/10.0 ("official" method):
  • In /etc/modprobe.conf, change the line
    alias net-pf-10 ipv6
    to
    alias net-pf-10 ipv6
    install ipv6 /bin/true
  • Reboot.
SuSE 9.1/9.2/9.3/10.0 (alternate method)/Mandriva (method 2)/Slackware:
  • In /etc/modprobe.conf, make sure you change
    alias net-pf-10 ipv6
    to
    alias net-pf-10 off
    alias ipv6 off
  • Reboot.
Gentoo:
  • In /etc/modules.d/aliases, make sure you change
    alias net-pf-10 ipv6
    to
    alias net-pf-10 off
    alias ipv6 off
  • Reboot.

NOTES:
  • In distros using /etc/modprobe.conf, beware that you might get overriden by /etc/modprobe.conf.local or by /etc/modprobe.d/*.
  • If you disable IPv6, I suppose you don't need tunnels either. You could also add there:
    install sit0 /bin/true
  • A last "anti-IPv6" issue: don't forget the old trick of checking if your Firefox has IPv6 disabled:
    • CTRL+L, about:config (Enter)
    • Filter by ipv6.
    • Set network.dns.disableIPv6 to true.

 

 

 

摘于:http://blog.chinaunix.net/uid-7654720-id-1742032.html

 

firefox域名解析太慢得解决方法

firefox域名解析老是要半天,上论坛查了下,有人说是firefox默认使用IPV6,禁用掉就好了。
方法是在再firefox地址栏里输入about:config,然后将network.dns.disableIPv6设为true
自己试了下速度果然变快了,贴出来供参下。

 

摘于:http://www.linuxdiyf.com/viewarticle.php?id=67553

VC++6.0中常出现的"unexpected end of file while looking for precompiled header directive"

如何解决:"fatal error C1010:VC++6.0中常出现的"unexpected end of file while looking for precompiled header directive"的问题?
我想大家在VC6.0中经常回遇到这样的问题,如何解决呢?
1、看看是否缺少“;”,“}”   
  隐藏得深的是宏、.h文件的问题就要费点心思了
2、一定是你在类的部分定义被删除了,M$在每个类中定义一些特殊的常量,是成对的,如下:   
  .h:   
  #if   !defined(AFX_CHILDFRM_H__54CA89DD_BA94_11D4_94D7_0010B503C2EA__INCLUDED_)   
  #define   AFX_CHILDFRM_H__54CA89DD_BA94_11D4_94D7_0010B503C2EA__INCLUDED_   
  .......   
  //{{AFX_INSERT_LOCATION}}   
  //   Microsoft   Visual   C++   will   insert   additional   declarations   immediately   before   the   previous   line.   
    
  #endif   //   !defined(AFX_MAINFRM_H__54CA89DB_BA94_11D4_94D7_0010B503C2EA__INCLUDED_)   
  你可以新建一个类,然后把这些拷贝过去或补上就可以了。   
3、在头部加入   #include   "stdafx.h"
4、在CPP文件第一行加上#include   "stdafx.h"。   
  或者Rebuild   All.  
5、
(1). [Project] - [Settings] - [C/C++] - [Category] 
(2). 选择 [Precomplied Headers]
(3). 单选 [Not Using Precomplied Headers]
(4). [OK]
ps:请重点注意1,2条,我就是重建工程,完全重做一遍搞定的!

 

摘于 : http://zhidao.baidu.com/link?url=GUrxryqbhNwI0uWhAqCZSFtnq0VJaK02hUzotlhdeokwZ6XqlCWQwzprJwBlWCixtIypUvKi-L_fzjCURvrbua

 

linux优化

 

基于开放源代码的Linux给用户提供了这样一个平台:可以根据自己的软、硬件环境,定制自己的Linux应用环境。因此,根据每个用户不同的应用范围定制应用环境,可以将Linux系统的性能提升到新的高度。

定制系统服务


Linux 在启动时需要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户。但是,开启不必要或有漏洞的服务则会给操 作系统带来安全和性能上的影响。对于系统安全来说,如果操作系统中的任何一个漏洞,都可能使整个系统受到攻击。所以,增加系统安全的最佳办法就是尽量监视 系统的功能。至于选择多少服务和功能,要根据工作需求和能力来决定。

下面以root身份运行:

#ntsysv

 

 

图1 将不需要的服务和进程前面的*去掉


打 开如图1所示的窗口,在此可以开启/关闭每一项系统服务(以Red Flag 3.0为例)。将不需要的服务和进程前面的*去掉(用空格键),然后重新启动系统,这样就可以使不需要的服务和进程不再启动。用这种办法可以随时根据需求 定制系统服务,不但安全有保障,而且还能提高系统的性能,一举两得。要保障Linux正常工作,有些系统服务是必须启动的,例如crond、 syslog、keytable、nfs、 kudzu。

为了高效安全地定制系统服务,下面介绍一下各项系统服务的功能。

alsasound Alsa 声卡驱动程序支持。Alsa声卡驱动程序本来是为了一种声卡Gravis UltraSound(GUS)而写的,它和OSS/Free 及OSS/Linux兼容。

apmd 用来监视系统用电状态,并将相关信息通过syslogd 写入日志,也可以用来在电源不足时关机。一般用于笔记本电脑,若是台式机建议关闭。

atd 用At命令调度的任务,也在系统负荷比较低时运行批处理任务。

autofs 需要时自动转载文件系统,不需要时自动卸载。

chargen 端口chargen字符产生的缩写,输出一个可打印字符的旋转序列,用于测试字符终端设备。

chargen udp udp格式下端口chargen字符产生的缩写,输出一个可打印字符的旋转序列,用于测试字符终端设备。

crond 根据用户要求周期地运行调度的任务。它比较安全,配置简单,类似Windows中的计划任务。

dhcpd 提供了对动态主机控制协议(Dynamic Host Control Protocol)的访问支持。

echo 端口echo简单地回应所有为测试连接发送给它的数据。

echo udp udp格式下端口echo简单地回应所有为测试连接发送给它的数据。

gpm 为文本模式下的Linux程序,如MC(Midnight Commander)提供了鼠标的支持。它也支持控制台下鼠标的拷贝、粘贴操作及弹出式菜单。

inetd 因特网操作服务程序。监控网络管理服务的需求,并在必要的时候启动相应的服务程序。通常,inetd 管理的程序有telnet、ftp、rsh和rlogin。关闭inetd也就关闭了这些由它管理的服务。

http 它是著名的WWW服务器,可用来提供HTML文件以及CGI动态内容服务。

isdn isdn的守护程序。

keytable 该程序的功能是转载/etc/sysconfig/keyboards里说明的键盘映射表。该表可以通过kbdconfig工具进行选择,应该使该程序处于激活状态。

kudzu 它是一个硬件检测程序,和Windows中的添加新硬件差不多。如果系统核心支持该硬件,并且有该驱动程序,就可自动装载。

linuxconf 它是Linux下一个有效的系统配置工具,该服务允许远程运行。

linuxconf web 在Web方式下使用linuxconf。

lpd 系统打印守护程序,负责将lpr等程序提交给打印作业。

medusa 支持Web的浏览器。

mysql 一个快速高效可靠的小型SQL数据库引擎。

ntalk 允许用户把自己的计算机和其它的计算机连接起来,然后向前或向后传送信息。

netfs 负责装载/卸载NFS、Samba、NCP(Netware)文件系统。

network 激活/关闭启动时的各个网络接口。

nfs 一个流行的、基于TCP/IP网络的文件共享协议。该服务提供了NFS文件共享服务,具体的配置在/etc/ exports文件里。

nscd 该服务负责密码和组的查询,并且缓冲查询结果。如果系统有比较慢的服务(如NIS和NIS+),则应该启动该服务。

pxe 用于远程无盘的Linux系统启动的服务程序。

pcmcia 主要用于支持笔记本电脑。

rexec 它是一个安全、分散式的远程执行系统,用于集群计算机的平行和连续运行。

random 保存和恢复系统的高质量随机数生成器。这些随机数是由系统一些随机行为提供的。

routed 该守护程序支持RIP协议的自动IP路由表维护。RIP主要使用在小型网络上,大一点的网络就需要复杂一点的协议。

rsync 叠加的Ftp Server,允许循环检查。

rsh 远程主机上启动一个shell,并执行用户命令。

rwhod 允许远程用户获得运行rwho守护程序的机器上所有已登录用户的列表,与finger类似。

swat Samba的一个工具包,使用901号端口。

sendmail 邮件服务器。

smb 启动和关闭smbd和nmbd守护程序,以提供SMB网络服务。

snmpd 简单网络管理协议(SNMP)的守护程序。

syslog 是操作系统提供的一种机制,守护程序通常使用这种机制将各种信息写到各个系统日志文件。通常应该启动该服务。

xfs X-Window系统的字体服务器。

xinetd 是inetd继承服务,监控网络对各种管理的服务的需求,并在必要的时候启动相应的服务程序。

以上这些系统服务中,安全隐患比较大的是:rsh、rwhod、rexec、snmp、named、sendmail。对于确实需要的系统服务,应该尽量选用最新的版本程序,并增加其它安全防范。

另 外,许多Linux产品在系统初始化后缺省地启动X-Window 管理器。如果只编译程序或编辑配置文件,那么启动X-Window管理器将会消耗大量系统资源。禁用X-Window管理器的方法是:编辑 /etc/inittab 文件,找到内容为id:5:initdefault的那一行,把它改为 id:3:initdefault,系统重新启动后将提供命令行登录。当需要运行X-Window管理器的时候,只要输入startx 就可以了。

根据硬件进行优化


1.CPU

CPU 是Linux主机的核心硬件,根据CPU型号在编译时优化以获得最佳性能。在/etc/profile文件中,含有系统环境和启动程序的配置信息,采用 -O9 来编译程序时,运行速度也是最快的。编译时使用-fomit-frame-poinetr选项,程序运行时访问变量会使用堆栈。使用-mcpu=cpu- type和 -march= cpu-type时,gcc会对针对CPU型号进行优化。

如果CPU是Pentium Pro、PentiumⅡ、PentiumⅢ、AMD K6-2、K6-3、Althon,那么在“/etc/profile”加入:

CFLAGS='-O9 -funroll-loops -ffast-math -malign-double -mcpu=pentiumpro
-march=pentiumpro -fomit-
frame-pointer -fno-exceptions'

 

如果CPU是Pentium 、Pentium MMX、AMD K5 、IDT、Cyrix,那么在“/etc/profile”加入:

export CFLAGS=-O3 -march=pentium -mcpu=pentium -
ffast-math -funroll-loops -fomit-frame-pointer -
fforce-mem -fforce-addr -malign-double -fno-exceptions

 

2.硬盘

采 用UDMA/33、66、100、133技术的硬盘,其最高传输速率是33MB/s、66MB/s、100MB/s、100MB/s。从理论上来说,它是 IDE硬盘(这里是指PIO MODE4模式,其传输率是16.6MB/s)传输速率的3~6倍,但是在Linux缺省设置中,DMA却是被禁用的,所以必须将它打开。我们可以使用 /sbin/hdparm程序打开它。hdparm 的一些常用选项如下:

/sbin/hdparm -c1 /dev/hda或hdb或hdc等启用 PCI 总线上的 32 位 I/O模式传输数据。
/sbin/hdparm -d1 /dev/hda启用 DMA模式传输数据。
/sbin/hdparm -d1 -X66/dev/hda启用UltraDMA模式传输数据。

 

获取系统中当前硬盘驱动器的设置列表的方法是(作为root)输入:

$/sbin/hdparm /dev/hda

 

接着再输入命令:

$/sbin/hdparm -kl /dev/hda

 

使硬盘在Reset之后仍然保持上述的设置。把一切优化到最佳状态后,请把各种命令添加到 /etc/rc.d/rc.local 文件中去,使这些命令在每次系统引导时自动运行。

3.内存

在Linux下使用free可以观察内存的使用情况。如果发现Linux只能使用其中的一部分,则在/etc/lilo.conf 加入append="mem=XXX"就可以,其中XXX是物理内存容量。这样可以告诉Linux使用全部内存。

如 果对计算速度要求很高,可以通过增加内存来实现,使用ramdisk技术。 一个A RamDisk就是把内存假设为一个硬盘驱动器,并且在它的上面存储文件。假设有几个文件要频繁的使用,如果将它们加到内存当中,程序运行速度会大幅度提 高,因为内存的读写速度远高于硬盘。划出部分内存提高整体性能,不亚于更换新的CPU。像Web服务器这样的计算机,需要大量读取和交换特定的文件。因 此,在Web服务器上建立RamDisk会大大提高网络读取速度。

$mkdir /tmp/ramdisk0
$mke2fs /dev/ram0
$mount /dev/ram0 /tmp/ramdisk0

 

上面这三个命令将会为RamDisk创建一个目录、格式化RamDisk(创建件系统),并把RamDisk装载到目录“/tmp/ramdisk0”中。现在,就可以把它作为一个磁盘分区使用了。

把下面这一行加到你的lilo.conf 文件中去:

ramdisk_size=20000

 

这样,当键入LILO命令并重新启动后,RamDisk的大小将为20MB。

如果你有512MB以上的内存,划出256MB作为暂存区/tmp,当很多程序用到/tmp,如Web服务,那么系统性能会大大提高。重新启动后,/tmp 中将被清空。注意:一定要记住保存RamDisk中有用的东西。

以上介绍了如何根据工作要求定制Linux系统应用环境,最后要强调的是一定要进行系统备份。

 

LINUX守护进程介绍

amd:自动安装NFS(网络文件系统)守侯进程
apmd:高级电源管理
Arpwatch:记录日志并构建一个在LAN接口上看到的以太网地址和IP地址对数据库
Autofs:自动安装管理进程automount,与NFS相关,依赖于NIS
Bootparamd:引导参数服务器,为LAN上的无盘工作站提供引导所需的相关信息
crond:Linux下的计划任务
Dhcpd:启动一个DHCP(动态IP地址分配)服务器
Gated:网关路由守候进程,使用动态的OSPF路由选择协议
Httpd:WEB服务器
Inetd:支持多种网络服务的核心守候程序
Innd:Usenet新闻服务器
Linuxconf:允许使用本地WEB服务器作为用户接口来配置机器
Lpd:打印服务器
Mars-nwe:mars-nwe文件和用于Novell的打印服务器
Mcserv:Midnight命令文件服务器
named:DNS服务器
netfs:安装NFS、Samba和NetWare网络文件系统
network:激活已配置网络接口的脚本程序
nfs:打开NFS服务
nscd:nscd(Name Switch Cache daemon)服务器,用于NIS的一个支持服务,它高速缓存用户口令和组成成员关系
portmap:RPC portmap管理器,与inetd类似,它管理基于RPC服务的连接
postgresql:一种SQL数据库服务器
routed:路由守候进程,使用动态RIP路由选择协议
rstatd:一个为LAN上的其它机器收集和提供系统信息的守候程序
ruserd:远程用户定位服务,这是一个基于RPC的服务,它提供关于当前记录到LAN上一个机器日志中的用户信息
rwalld:激活rpc.rwall服务进程,这是一项基于RPC的服务,允许用户给每个注册到LAN机器上的其他终端写消息
rwhod:激活rwhod服务进程,它支持LAN的rwho和ruptime服务
sendmail:邮件服务器sendmail
smb:Samba文件共享/打印服务
snmpd:本地简单网络管理候进程
squid:激活代理服务器squid
syslog:一个让系统引导时起动syslog和klogd系统日志守候进程的脚本
xfs:X Window字型服务器,为本地和远程X服务器提供字型集
xntpd:网络时间服务器
ypbind:为NIS(网络信息系统)客户机激活ypbind服务进程
yppasswdd:NIS口令服务器
ypserv:NIS主服务器
gpm:管鼠标的
identd:AUTH服务,在提供用户信息方面与finger类似

Linux各项系统开机服务的功能是什么?有哪些可以关掉?
Linux 在启动时要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户。但是,开启不必要或有漏洞的服务则会给操作 系统带来安全和性能上的影响。下面我们以BluePoint Linux 2.0的开机服务为例,列表说明各项服务的功能。

alsasound
Alsa 声卡驱动程序支持。Alsa声卡驱动程序本来是为了 一种声卡Gravis UltraSound(GUS)而写的,该程序被证 明很优秀,于是作者就开始为一般的声卡写驱动程序。 Alsa和OSS/Free 及OSS/Linux兼容,但是有自己的接 口,甚至比OSS优秀。

amd
运行automount精灵程序,该精灵在必要时自动安装一些 本地设备和NFS文件系统。

apmd
apmd用来监视系统用电状态,并将相关信息通过syslogd 写入日志。也可以用来在电源不足时关机。

arpwatch
该程序主要用来维护以太网物理地址和IP地址的对应关系。

atalk
AppleTalk精灵程序。注意不要在后台运行该程序,该程 序的数据结构必须在运行其他进程前先花一定时间初始化。

atd
运行用户用At命令调度的任务。也在系统负荷比较低时 运行批处理任务。

autofs
当您需要时自动转载文件系统,而当您不需要时自动卸载。

bootparamd
该服务允许老的Sun工作站从Linux网络启动,它和rarp 现在很少使用,基本上被bootp和dhcp取代了。

crond
cron是Unix下的一个传统程序,该程序周期地运行用户 调度的任务。比起传统的Unix版本,Vixie版本添加了不 少属性,而且更安全,配置更简单。
dhcpd 该精灵提供了对动态主机控制协议(Dynamic Host Control Protocol)的访问支持。

gated
gated通过一个数据库提供了网络路由功能支持。它支持 各种路由协议,包括RIP版本1和2、DCN HELLO协议、 OSPF版本2以及EGP版本2到4。

gpm
gpm为文本模式下的Linux程序如mc(Midnight Commander)提供了鼠标的支持。它也支持控制台下鼠标 的拷贝,粘贴操作以及弹出式菜单。

httpd
http是著名的www服务器,可用来提供HTML文件以 及CGI动态内容服务。

inetd
因特网操作服务程序。监控网络对各种它管理的服务的需 求,并在必要的时候启动相应的服务程序。通常,inetd 管理的程序有telnet、ftp、rsh和rlogin。关闭inetd也就 关闭了这些由它管理的服务。

innd
inn是最流行的用户组新闻服务器。它允许您建立起本地 新闻服务器。配置有一定的难度,可以先阅读/usr/doc/ inn*文档获得帮助。


keytable 该程序的功能是转载您在/etc/sysconfig/keyboards里说 明的键盘映射表,该表可以通过kbdconfig工具进行选 择。您应该使该程序处于激活状态。

ldap
LDAP代表Lightweight Directory Access Protocol, 实现了目录访问协议的行业标准。

linuxconf
linuxconf是Linux下的一个有效的系统配置工具,该服 务允许远程运行。

lpd
lpd是系统打印守护程序,负责将lpr等程序提交给打印 作业。

mcserv
Midnight Commander服务进程允许远程机器上的用户 通过Midnight Commander文件管理器操作本机文件。服 务进程用PAM来验证用户,需要给出“用户名/口令” 以通过验证。

mysql 一个快速高效可靠的轻型SQL数据库引擎。

named 域名服务器,将Internet主机名解析为点分的IP地址。

netfs 负责装载/卸载NFS、Samba、NCP(Netware)文件系统。

network 激活/关闭启动时的各个网络接口。

nfs
NFS是一个流行的基于TCP/IP网络的文件共享协议。该 服务提供了NFS文件共享服务,具体的配置在/etc/ exports文件里。

nscd
该服务负责密码和组的查询,并且缓冲查询结果。如果您 的系统有比较慢的服务(如NIS和NIS+),则应该启动该 服务。

pcmcia pcmcia 主要用于支持笔记本电脑。

portmap portmap 用来支持RPC连接,RPC被用于NFS以及NIS 等服务。

postgresql PostgreSQL 关系数据库引擎。

proftpd proftpd 是Unix下的一个配置灵活的ftp守护程序。

radvd 路由广播程序。

random
保存和恢复系统的高质量随机数生成器,这些随机数是系 统一些随机行为提供的。

routed
该守护程序支持RIP协议的自动IP路由表维护。RIP主要 使用在小型网络上,大一点的网络就需要复杂一点的协议。

rstatd Rstat协议允许网络上的用户获得同一网络上各机器的性能 参数。

rusersd 该服务使网络用户可以定位同一网络上的其他用户。

rwalld
Rwall协议允许远程用户向在同一系统中活跃着的终端发送 消息,类似wall的本地行为。

rwhod
允许远程用户获得运行rwho精灵的机器上所有已登录用户 的列表,与finger类似。

sendmail 大名鼎鼎的邮件服务器。

smb 启动和关闭smbd和nmbd精灵程序以提供SMB网络服务。

snmpd 简单网络管理协议(SNMP)的守护精灵。

syslog
syslog是操作系统提供的一种机制,守护程序通常使用这 种机制将各种信息写到各个系统日志文件。通常应该启动 该服务。

xfs X的字体服务器。
ypbind NIS/YP的客户端守护程序。如果您需要使用NIS/YP机 器,请启动这项服务,否则,关闭这项服务。

yppasswd
让NIS用户能够修改密码。运行在NIS域的服务器上。客 户端程序同样也叫yppasswd。

ypserv
标准NIS/YP网络协议的一个实现。允许主机名,用户名 和其他信息分布于网络各端。运行在NIS服务器上,客户 端不需要。


Linux 真的是一套很棒的操作系统,经过这样调整後,光是开机到登入窗口画面出现,从原来的 48 秒,变成 30 秒,用 top 指令(每秒)观察CPU idle 时间也从 82% 提升到 93%,而窗口程序的反应感觉上与 Windows 98 差不多了。

转贴自www.linuxsir.com 系统提速[原作:hotmanhh兄弟]
我的计算机配备如下∶

处理器∶Intel 赛扬 366 MHz
记忆体∶?128 Mb PC100 RAM
硬碟∶IBM 15Gb 7200 rpm ATA66
显示卡∶Sis 620 AGP
声卡∶CS46xx
网络卡∶D-Link DFE530TX (ver A)
显示器∶Alfscan G17 17 寸
操作系统∶安装 Windows 98 与 RH7.0 + CLE 1.0

一、开启硬盘 DMA 支持。

系统安装完毕後,硬盘的 DMA 是没有打开的,我的方法是在
/etc/rc.d/rc.local 最後面加上一行 /sbin/hdparm -d1 -c3 -m16 /dev/hda 这样每次开机後,硬盘的 DMA 就会开启,不必每次手动设定。

如 果您的硬盘机支持 ATA33 可以加上 -X66 这个参数,ATA66则是 -X68,像我的硬盘是 ATA66 那麽完整参数就是 /sbin/hdparm -d1 -X68 -c3 -m16 /dev/hda 经过我的测试 ,在 DMA 未开启以前,实际读取效率是每秒约 4.10 Mb 左右,开启 DMA 後,每秒实际读取效率跃升为 20 Mb 大约提升 5 倍之多。

§未开启 DMA 时的测试

[root@firefly /root]# hdparm -d0 /dev/hda

/dev/hda:

setting using_dma to 0 (off)
using_dma = 0 (off)

[root@firefly /root]# hdparm -Tt /dev/hda

/dev/hda:

Timing buffer-cache reads: 128 MB in 2.75 seconds = 46.55 MB/sec
Timing buffered disk reads: 64 MB in 15.58 seconds = 4.11 MB/sec

§开启 DMA 後的测试结果

[root@firefly /root]# hdparm -d1 -X68 -c3 -m16 /dev/hda

/dev/hda:

setting 32-bit I/O support flag to 3
setting multcount to 16
setting using_dma to 1 (on)
setting xfermode to 68 (UltraDMA mode4)
multcount = 16 (on)
I/O support = 3 (32-bit w/sync)
using_dma = 1 (on)

[root@firefly /root]# hdparm -Tt /dev/hda/dev/hda:

Timing buffer-cache reads: 128 MB in 2.75 seconds = 46.55 MB/sec
Timing buffered disk reads: 64 MB in 3.20 seconds = 20.00 MB/sec

由以上的数据,可以看得出来,硬盘 DMA 是否开启,对读取效率影响很大。

二、关闭多馀的系统服务。

这 是老生常谈的题目了,一般我们当作桌上型工作站的时候,只需要激活几个基本的?Service 即可,其他的不但没用,一方面会占用系统资源,另一方面则会有安全上的顾虑,我平常只用来连网、打打文件、听听音乐、看看电影,多半时间只是一个 Client 端,实在没必要激活 Server 端的服务,所以,我在 Setup System Services时,只留下以下几个 Service,其馀的都关闭。

1. crond
2. network
3. syslogd

真的,相信我,只要这四个就足够了!

三、下载 Kernel 重新编程。

因为系统所默认安装的 Kernel 是为了适用大部分的计算机而做的,并未对你的计算机作最优化,所以显得臃肿肥大,因为 Kernel 直接掌控著计算机的一切,所以对系统效率影响当然很大。

我的作法是∶下载最新的 Kernel 重新编程,将我计算机上的硬件直接编程进 Kernel 里面,不要作成 Module ,对於不需要的就不编程,这样,打造出完全面向自己环境的 Kernel ,才能完全发挥计算机的威力。

至於 Kernel 怎样编程?这就不是我的主题了,大家可以到CLDP 自行参考 KERNEL HOW-TO 中译版。

四、减少虚拟终端机的数量。

系统默认是6个,也就是 CTRL+ALT F1~F6 那六个,我关掉其中四个,只留下 CTRL+ALT F1~F2,大约省下 4 Mbytes 的记忆体,但是这样一来,X-Window 会从原来的 CTRL+ALT F7 变成 CTRL+ALT F3 。

修改 /etc/inittab 中,将 mingetty 3 ~6 全部加上 # 字号,然後下指令 #init q

五、调整 X-Windows 环境

我习惯操作 KDE ,对 GNOME 不熟,所以,以下是都是面向 KDE而设,GNOME 的使用者,我想,应该也差不多啦!

1、颜色数设为 16 Bit 就有很好的效果了,24 Bit 除了浪费资源,看不出有何好处。
2、不要使用屏幕保护程序。
3、取消动画窗口功能。
4、尽量使用同一种字型。
5、浏览器用 Mozilla 不要用 Netscape。
6、不要激活音效服务器 artd

Speed Up X by Managing Font Setting 在你抱怨 X 跑得不够快之前,
先检查字型设定, 很可能就是影响效能的一大元凶。
先看一下 /etc/X11/XF86Config-4 档案里的 FontPath 设定值, 如果是
如下∶
Section "Files"

RgbPath "/usr/X11R6/lib/X11/rgb"

# Multiple FontPath entries are allowed (they are concatenated together)
# By default, Mandrake 6.0 and later now use a font server independent of
# the X server to render fonts.

FontPath "unix/:-1"

EndSection

可参考 /etc/X11/fs/config 档案里的字型设定值, 挑选几个喜欢的字型目录(全部比较不会错)
来修改, 例如我直接设定下列几个字型目录∶
Section "Files"

RgbPath "/usr/X11R6/lib/X11/rgb"

# Multiple FontPath entries are allowed (they are concatenated together)
# By default, Mandrake 6.0 and later now use a font server independent of
# the X server to render fonts.

FontPath "/usr/X11R6/lib/X11/fonts/misc:unscaled"
FontPath "/usr/X11R6/lib/X11/fonts/75dpi:unscaled"
FontPath "/usr/X11R6/lib/X11/fonts/Type1"
FontPath "/usr/X11R6/lib/X11/fonts/mdk:unscaled"
FontPath "/usr/share/fonts/ttf/big5"

EndSection

修改之後, 重新激活 startx 感受看看棉。

原本的 FontPath "unix/:-1" 将字型由 X Font Server 来提供,
一般使用者未蒙其利、先受其害, 可以考虑等熟悉 X Font Server 功能後再使用。
如此就可以关掉xfs了
ps:试用时不要用默认开机直接进x-window,若不行会卡在x-window
ps:引用自http://twopensource.org/~marr/xfont_tip.html
六、调整应用程序优先权。

一 般时候,我们使用任何程序时,其 NICE 值都是 0,意思是CPU 的使用权值。如果我们常用程序有较高的优先权的话,自然效率就会比较好,优先权的值从 -20 到 19 ,数字越小优先权就越高,但要注意的是一般使用者只能调低( 0~19),只有 root 有权调高优先权( -20 ~ 19 )。我们可以用 ps -fel 来观察 NI 那栏就知道。

说了半天,到底如何调整呢?有一个指令 /bin/nice 就是用来作这件事的,用法如下∶nice?-n?程序名称?参数....
n 的值从 -20 到 19,这是手动操作,在 KDE 中,可以用选单编辑器来设定,方法是在你要调整优先权的程序的 [ 命令 ] 那一栏的前面,加上 /bin/nice --n 就可以了。

比 方说我常用 Mozilla 来浏览网页,我改成 /bin/nice --10 /usr/local/mozilla/mozilla 这样我的 Mozilla 执行时,就比其他程序有更高的优先权,在实际测试的时候,Mozilla 激活速度以及回应都快了不少,其他一些常用的程序,也可以比照办理。

後记

Linux 真的是一套很棒的操作系统,经过这样调整後,光是开机到登入窗口画面出现,从原来的 48 秒,变成 30 秒,用 top 指令(每秒)观察CPU idle 时间也从 82% 提升到 93%,而窗口程序的反应感觉上与 Windows 98 差不多了。

 
 
摘于: http://hi.baidu.com/injava/item/e6689a10b89475a4ffded57a

自绘控件的4种方法

在您决定开发 Windows 提供的常规免费自定义控件范围之外的控件之后,您必需确定自己的控件将有多少独到之处 — 在功能和外观两方面。例如,我们假定您正在创建一个类似于计速表的控件。由于公共控件库 (ComCtrl32.dll) 中没有类似的控件,您完全需要自己进行以下操作:编写所有控件功能需要的代码,进行绘制,默认终端用户的交互,以及控件与其父窗口之间需要的任意消息处理

(#add 两方面,公共控件库中没有类似的 完全重写;  只想调整公共控件功能,则可以部分修改)

  另一方面,还包括一些您只想调整公共控件功能的情况。例如,我们假定您想创建一个屏蔽编辑控件,它只允许接受指定的 字符。如果使用 MFC,通常涉及从 MFC 提供的类派生一个类,该类封装了一个公共控件(在屏蔽编辑控件中,通常为 CEdit),重写必需的虚函数(或处理指定的消息),然后加入自定义的代码。

  本文讨论的重点介于两者之间 — 公共控件赋予您想要的大部分功能,但控件的外观并不是您想要的。例如,列表视图控件提供在许多视图风格中显示数据列表的方式 — 小图标、大图标、列表和详细列表(报告)。然而,如果您想要一个网格控件,那结果怎样呢?尽管公共控件库里没有特别包含网格,但是列表视图控件与它较为接 近,它以行和列显示数据,并有一个相关的标头控件。因此,许多人以一个标准的列表视图控件为起点创建自己的网格控件,然后重写该控件及其子项的呈现方式或 绘制方式。

   即使“只”进行绘制,您仍然有至少四种选项可用,它们都具有鲜明的优缺点:

·处理 WM_PAINT
·所有者绘制(owner draw)
·自定义绘制(custom draw)
·处理 WM_CTLCOLOR

 

  处理 WM_PAINT

  最极端的选择是执行一个 WM_PAINT 处理程序,并且自己完成所有的绘制。这意味着,您的代码将需要进行一些与呈现控件相关的琐事 — 创建适当的设备上下文(一个或多个),决定控件的大小和位置,绘制控件等。在绘制过程中,很少需要这种级别的控件。

  所有者绘制

  控制控件绘制的另一种方法是利用所有者绘制。事实上,您也许听开发人员提到过所有者绘制控件,因为它是用于开发自定 义控件最普通的技术。该技术普遍使用的主要原因在于,Windows 可为您提供很多帮助。在呈现控件的那一刻,Windows 就已经创建并填写了设备上下文,决定了控件的大小和位置,并且向您传递信息以使您了解此刻绘制的需求。对于列表控件(例如,列表框和列表视 图),Windows 将为列表中的每一项调用绘制代码,这意味着您只需绘制这些项,而无需考虑控件的其他方面。注意,所有者绘制可用于大多数控件。然而,它不能用于编辑控件;并且考虑到列表控件,它只能用于报表视图样式

  自定义绘制

  对于绘制自己的控件而言,这可能是最少为人所知的技术。事实上,许多技术能力较高的开发人员也混淆了术语所有者绘制 (owner-draw) 和自定义绘制 (custom-draw)。关于自定义控件,首先需要了解,它仅针对于指定的公共控件:标头、列表视图、rebar、工具栏、工具提示、跟踪条和树视 图。此外,尽管所有者绘制只允许绘制报告视图风格的列表视图控件,而自定义绘制则使您能够处理列表视图控件所有视图风格的绘制。使用自定义绘制的另一个明显优势是,您可以对希望绘制的内容进行严格挑选。实现方式是,在控件绘制的每个阶段由 Windows 向代码发送一个消息。这样,您可以决定在每个阶段是自己进行所有的绘制工作,增加默认的绘制,还是允许 Windows 为该阶段执行所有的绘制。(鉴于自定义绘制是本文的一个主题,因此您很快会看到它的工作方式。)

  处理 WM_CTLCOLOR消息

这可能是帮助决定如何呈现控件最简单的方式。正如消息名所指,当要绘制一个控件,并且它能让您的代码决定要使用的画笔时,发送 WM_CTLCOLOR 消息(#add 似乎不对,应该用消息反射)。通常情况下,如果您只想更改控件的颜色(#addSetTextColor SetBkColor),并且不提供除控件本身之外的更多功能,则使用该技术。此外,对于由 Internet Explorer 引入的公共控件(列表视图、树视图、rebar 等),不发送该消息,并且它只与标准控件(编辑、列表框等)协同使用。

CTLCOLOR_STATIC               Static control

CTLCOLOR_BTN                     Button control

CTLCOLOR_EDIT                    Edit control

CTLCOLOR_LISTBOX             List-box control

CTLCOLOR_SCROLLBAR    Scroll-bar control

CTLCOLOR_DLG                    Dialog box

CTLCOLOR_MSGBOX            Message box

不会为组合框中的下拉列表框调用OnCtlColor函数,因为下拉列表框实际上是组合框的子窗口,而不是窗口的子窗口。要改变下拉列表框的颜色,创建一个CComboBox,在重载的OnCtlColor中的nCtlColor参数中检查CTLCOLOR_LISTBOX。在这个处理函数中,为设置文本的背景必须使用SetBkColor成员函数。

自定义绘制:

  既然您已经了解了绘制控件可用的各种选项(包括使用自定义绘制的好处),那么,让我们来看看实现一个自定义绘制控件需要的三个主要步骤。

·执行一个 NM_CUSTOMDRAW 消息处理程序。
·指定处理所需的绘制阶段。
·筛选特定的绘制阶段(在这些阶段中,您需要加入自己的特定于控件的绘制代码)。

 

  1,执行一个NM_CUSTOMDRAW 消息处理程序

  当需要绘制一个公共控件时,MFC 会将控件的自定义绘制通知消息(最初发送到控件的父窗口)以 NM_CUSTOMDRAW 消息的形式反馈给控件。以下是一个 NM_CUSTOMDRAW 处理程序的示例。

void CMyCustomDrawControl::OnCustomDraw(NMHDR* pNMHDR, LRESULT*pResult)
{
 LPNMCUSTOMDRAW pNMCD =reinterpret_cast(pNMHDR);
 ...
}

  正如您所见,NM_CUSTOMDRAW 处理程序将一个指针传递给 NMHDR 类型的结构。然而,该值不足以用于象 NMHDR 这样只包含三个成员(hwndFrom、idFrom 和 code)的结构。

  因此,您通常需要将该结构指针转换为信息量更大的结构 — LPNMCUSTOMDRAW。LPNMCUSTOMDRAW指向 NMCUSTOMDRAW,它包含诸如 dwDrawStage、dwItemSpec 和 uItemState 这样的成员 — 它们是决定当前绘制阶段及确切绘制(例如,控件本身、或控件的一个项目或子项)所必需的。

  这里值得注意的是,还可以将 NMHDR 指针指向特定于正在绘制控件的类型的结构。表 1 显示控件的一个列表及其相关的自定义绘制结构类型名。

  表 1:控件及其相关的自定义绘制结构

控件

结构(在 commctrl.h 中定义)

Rebar、Trackbar、AuthTicket、My.Resources、My.Settings、My.User 和 My.WebServices。

NMCUSTOMDRAW

List-view

NMLVCUSTOMDRAW

Toolbar

NMTBCUSTOMDRAW

Tooltip

NMTTCUSTOMDRAW

Tree-view

NMTVCUSTOMDRAW

  2,指定处理所需的绘制阶段

  正如我在前面提到的,绘制一个控件存在一些“阶段”。特别是,您可以将绘制过程理解为一系列阶段,其中控件通知其父窗口需要绘制的内容。事实上,控件甚至会在绘制控件及其各项前后发送一个通知,从而让编程人员更好地控制该过程。

  在所有情况下,单一的 NM_CUSTOMDRAW 处理程序在每个绘制阶段都进行调用。然而,谨记:自定义绘制允许您在自己的绘制中合并默认的控件绘制,您需要指定您将处理哪个绘制阶段。这通过设置 NM_CUSTOMDRAW 处理程序的第二个参数 (pResult) 完成。事实上,如果您从未设置该值,则用初始阶段的 CDDS_PREPAINT 调用函数后,您的函数将不再被调用!

  从技术上讲,只有两个阶段指定需要的绘制阶段(CDDS_PREPAINT 和 CDDS_ITEMPREPAINT),它们影响发送通知消息的内容。然而,通常只在处理程序的最后指定代码将处理的绘制阶段。表 2 列出用于指定所需绘制阶段(代码关注的)的值。

  表 2:自定义绘制返回标志

自定义绘制返回标志

含义

CDRF_DEFAULT

指示控件自行绘制。该值为默认值,不应该将它与其他值组合在一起。

CDRF_SKIPDEFAULT

用于指定控件根本不进行任何绘制。

CDRF_NEWFONT

当代码更改绘制项/子项的字体时使用。

CDRF_NOTIFYPOSTPAINT

使通知信息在控件或每个项/子项绘制后发送。

CDRF_NOTIFYITEMDRAW

指出项(或子项)将进行绘制。注意,它下面的值与 CDRF_NOTIFYSUBITEMDRAW 相同。

CDRF_NOTIFYSUBITEMDRAW

指出子项(或项)将进行绘制。注意,它下面的值与 CDRF_NOTIFYITEMDRAW 相同。

CDRF_NOTIFYPOSTERASE

当删除控件后需要通知代码时使用。

  以下为一个示例,其中的代码指定,当绘制控件的项 (CDRF_NOTIFYITEMDRAW) 及子项(CDRF_NOTIFYPOSTPAINT),以及绘制完成时,应该调用 NM_CUSTOMDRAW 处理程序。

void CListCtrlWithCustomDraw::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT*pResult)
{
 LPNMCUSTOMDRAW pNMCD =reinterpret_cast(pNMHDR);
 ...
 *pResult = 0; // Initialize value
 *pResult |= CDRF_NOTIFYITEMDRAW;
 *pResult |= CDRF_NOTIFYSUBITEMDRAW;
 *pResult |= CDRF_NOTIFYPOSTPAINT;
}

  3,筛选指定的绘制阶段

  一旦指定要关注的阶段后,您需要处理这些阶段。因为绘制过程的每个阶段只有一个消息要发送,惯例是执行一个 switch 语句以决定准确的绘制阶段。不同的绘制阶段由以下标志定义:

CDDS_PREPAINT
CDDS_ITEM
CDDS_ITEMPREPAINT
CDDS_ITEMPOSTPAINT
CDDS_ITEMPREERASE
CDDS_ITEMPOSTERASE
CDDS_SUBITEM
CDDS_POSTPAINT
CDDS_PREERASE
CDDS_POSTERASE

  对于一个 CListCtrl 派生的类,有一个 NM_CUSTOMDRAW 处理程序的示例,其中您可以发现,代码决定当前绘制阶段的方式:

void CMyCustomDrawControl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult)
{
 LPNMCUSTOMDRAW pNMCD =reinterpret_cast(pNMHDR);
 switch(pNMCD->dwDrawStage)
 {
  case CDDS_PREPAINT:
   ...
   break;
  case CDDS_ITEMPREPAINT:
   ...
   break;
  case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
   ...
   break;
  ...
 }
 *pResult = 0;
}

  注意,为了决定子项(例如,列表视图控件)绘制的阶段,您必需使用按位 or 操作符,它有两个值:其中一个为 CDDS_ITEMPREPAINT 或者CDDS_ITEMPOSTPAINT,另一个为 CDDS_SUBITEM。

  要说明它,我们假定您想在绘制列表视图项之前进行一些处理。将编写 switch 语句来处理 CDDS_ITEMPREPAINT。

case CDDS_ITEMPREPAINT:
...
break;

  然而,如果是您所关注子项的预绘制阶段,则将如下操作:

case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
...
break;

示例:创建一个列表视图控件自定义绘制控件

  如前面提到的,您可以完全控制控件及其项的绘制,或者仅执行一小部分特定于应用程序的绘制,并让控件继续进行。本文 的焦点更多地偏重于控件绘制技术而非高级的绘制技术,我们将演练一个简单的示例,其中列表视图控件是一个自定义的绘制,因此项的文本将在创建拼接外观的交 替单元中显示为不同的颜色。

  ·创建一个基于 Visual C++ 2005 对话框的项目,名为ListCtrlColor。

  ·从 Class View 中选择 Project 菜单选项,并单击 Add Class 调用 Add Class 对话框。

  ·从分类列表中选择 MFC,然后从模板列表中选择 MFC Class。

  ·单击 Add 按钮,调用 MFC Class Wizard 对话框。

  ·对于 Class name,键入值 CListCtrlWithCustomDraw 并选择 CListCtrl的 Base class。

  ·单击 Finish 按钮,生成类的标头和执行文件。

  ·对于 Class View,右键单击 CListCtrlWithCustomDraw 类,并选择Properties 上下文菜单选项。

  ·显示 Properties 窗口时,单击顶部的 Messages 按钮,显示一个两列的消息列表,您可以为其实现处理程序。

  ·在消息列表中单击 NM_CUSTOMDRAW 项,然后下拉第二列的组合框箭头,并选择值 OnNMCustomdraw。

  ·现在,处理绘制代码。这里,我们只简单处理项和子项预绘制阶段,指定基于当前行(项)和列(子项)的文本和背景色。要进行此操作,按如下所示修改 OnNMCustomdraw 函数:

void CListCtrlWithCustomDraw::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT*pResult)
{
 LPNMLVCUSTOMDRAW lpLVCustomDraw =reinterpret_cast(pNMHDR);
 switch(lpLVCustomDraw->nmcd.dwDrawStage)
 {
  case CDDS_ITEMPREPAINT:
  case CDDS_ITEMPREPAINT | CDDS_SUBITEM:
   if (0 == ((lpLVCustomDraw->nmcd.dwItemSpec+ lpLVCustomDraw->iSubItem) % 2))
   {
    lpLVCustomDraw->clrText =RGB(255,255,255); // white text
    lpLVCustomDraw->clrTextBk =RGB(0,0,0); // black background
   }
   else
   {
    lpLVCustomDraw->clrText =CLR_DEFAULT;
    lpLVCustomDraw->clrTextBk =CLR_DEFAULT;
   }
   break;
   default: break;
 }
 *pResult = 0;
 *pResult |= CDRF_NOTIFYPOSTPAINT;
 *pResult |= CDRF_NOTIFYITEMDRAW;
 *pResult |= CDRF_NOTIFYSUBITEMDRAW;
}

  现在,我们来测试新控件。要进行此操作,您只需使用 CListCtrlWithCustomDraw 类将列表视图控件放在对话框中,并对其进行子类派生。下面是完成该操作的步骤。

  ·在 Resource 视图中,打开应用程序的主对话框 (IDD_LISTCTRLCOLOR_DIALOG)。

  ·从 Toolbox 中,将一个 List Control 拖放到该对话框。

  ·右键单击列表控件,并选择 Properties 上下文菜单选项。

  ·将 View 属性设置为 Report。

  ·右键单击控件,并选择 Add Variable 上下文菜单选项。

  ·出现 Add Member Variable Wizard 对话框时,指定m_lstBooks 的 Variable name,并单击 Finish 按钮。

  ·这时,您就有了一个 CListCtrl 派生类 (m_lstBooks),它将对话框上的列表视图控件进行子类派生。然而,m_lstBooks 需要从最新创建的 CListCtrlWithCustomDraw 派生,以便于调用您的绘制代码。因此,打开对话框的标题文件 (ListCtrlColorDlg.h),将 m_lstBooks 更改为 CListCtrlWithCustomDraw 类型。

  ·在 CListCtrlColorDlg 类开始之前,添加以下指令。

#include"ListCtrlWithCustomDraw.h"

  ·将下面的代码添加到对话框的 OnInitDialog 成员函数,这样我们就能够看到一些列表视图行。

// Insert the columns
m_lstBooks.InsertColumn(0, _T("Author"));
m_lstBooks.InsertColumn(1, _T("Book"));
// Define the data
static struct
{
 TCHAR m_szAuthor[50];
 TCHAR m_szTitle[100];
} BOOK_INFO[] = {
 _T("Tom Archer"),_T("Visual C++.NET Bible"),
 _T("Tom Archer"),_T("Extending MFC with the .NET Framework"),
 _T("Brian Johnson"),_T("XBox 360 For Dummies")
};
// Insert the data
int idx;
for (int i = 0; i < sizeof BOOK_INFO / sizeof BOOK_INFO[0]; i++)
{
 idx = m_lstBooks.InsertItem(i,BOOK_INFO[i].m_szAuthor);
 m_lstBooks.SetItemText(i, 1,BOOK_INFO[i].m_szTitle);
}

  ·现在,建立并运行应用程序。图 1 为应用程序外观的一个示例。

  图 1. 自定义绘制示例应用程序

  小结

  当 Windows 首次作为“下一代”操作系统引入到应用程序开发之中时,它作为新图形用户界面的一个主要论据就是其一致性。该论据的要点所在是其具有一个通用的外观:统一 的菜单项、通用控件等。这一通用性的感觉可能会一直延续,直到有第二家公司想设计其自己的应用程序。简单说,提供外观与其他应用程序雷同的应用程序,任何 公司都不会逃离这一怪圈。

  要建立一个唯一的且让人过目难忘的用户界面,其中一种方式是为应用程序设计并开发自定义的控件。希望本文能对您有所帮助,现在,您了解到一种非常强大的技术,它使您的应用程序能从众多竞争对手的应用程序中脱颖而出。

OWNER DRAW实现自绘按钮

一、准备工作

 在开始编码之前,首先应该确定好,更准确的说应该是设计好按钮在各种状态下的外观。按钮控件的几中基本状态包括:

Normal状态,就是按钮一开始显示时的样子。

Over状态,鼠标指针移动到按钮上面时按钮显示的样子。

Down状态,按下按钮时显示的样子。

Focus状态,按钮按下后松开的样子,例如标准按钮按下松开之后会看到按钮内部有一个虚线框。

Disable状态,当然就是按钮被设置成无效的时候的样子啦。

 

我参考了一下WindowsXP中普通按钮的实际样子,设计出XP按钮各种状态的外观,如下图所示:

 

至于Down状态主要是在Over状态的基础上将文字往右下的方向稍微平移,以实现下压的效果。

 

 二、实现原理及难点

 

下面我们开始类的创建,在Workspace的ClassView页中右击列表树的根结点,选择New Class…

 

  

在弹出窗口中进行派生类的定义,如下图所示,注意,你需要填写的只有Name和Base class两项,其余的选项保持默认值就可以了。

  

  下面简要叙述一下按钮的实现原理

 

1. 在控件初始化时为按钮添加Owner  Draw的属性。这是因为在MFC中,要想激活控件的自绘功能,要求该控件的属性中必须包含属性值BS_OWNERDRAW,这一步我们可以通过类向导为 CXPButton类添加PreSubclassWindow()函数,在该函数中完成属性值的设置。当激活控件的自绘功能之后,每次控件状态改变的时候都会运行函数DrawItem(),该函数的作用就是绘制控件在各种状态下的外观。

 

2. 添加WM_MOUSELEAVE消息函数,当鼠标指针离开按钮时,触发该消息函数,我们在函数中添加代码,通知DrawItem函数鼠标指针已经离开了,让按钮重绘。

 

3. 添加WM_MOUSEHOVER消息函数,当鼠标指针位于按钮之上时,触发该消息函数,我们在函数重添加代码,通知DrawItem函数鼠标指针现在正在按钮的上面,让按钮重绘。

 

4. 添加DrawItem函数。在DrawItem中根据按钮当前的状态绘制按钮的外观。可以说自绘控件的大部分功能都是在这个函数中实现的。DrawItem函数包含了一个LPDRAWITEMSTRUCT的指针,本篇会在稍后予以讲解。

 

这里有两个难点,首先是WM_MOUSELEAVE和 WM_MOUSEHOVER不是标准的Windows消息函数,它们不能通过类向导来添加,所有的添加工作都需要通过手工输入代码来完成。另一个难点是 DrawItem中的LPDRAWITEMSTRUCT指针,它指向了一个DRAWITEMSTRUCT的结构,这个结构中包含了控件的各种细节,为我们 提供了实现自绘功能的必要信息。

难点一:

事实上WM_MOUSELEAVE和WM_MOUSEHOVER两个Windows消息是通过WM_MOUSEMOVE 消息触发的,而 WM_MOUSEMOVE是标准的Windows消息,因此我们可以通过类向导来为CXPButton类添加WM_MOUSEMOVE消息函数。

  

函数的代码见如下,这段代码非常有用,在其它的自绘控件中,如果想触发WM_MOUSELEAVE和WM_MOUSEHOVER消息,也是使用类似的方法实现的。

 

voidCXPButton::OnMouseMove(UINT nFlags, CPoint point)

{

       // TODO: Add your message handler codehere and/or call default

       if (!m_bTracking)

       {

              TRACKMOUSEEVENT tme;

              tme.cbSize = sizeof(tme);

              tme.hwndTrack = m_hWnd;

              tme.dwFlags = TME_LEAVE |TME_HOVER;

              tme.dwHoverTime = 1;

             m_bTracking = _TrackMouseEvent(&tme);

       }

       CButton::OnMouseMove(nFlags, point);

}

我们接着添加WM_MOUSELEAVE和WM_MOUSEHOVER消息消息函数。在CXPButton类的声明中 (即在 XPButton.h文件中)找到afx_msg void OnMouseMove(UINT nFlags, CPoint point);的函数声明,紧接其下输入

 

afx_msgLRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);

afx_msgLRESULT OnMouseHover(WPARAM wParam, LPARAM lParam);

 

然后在XPButton.cpp文件中找到ON_WM_MOUSEMOVE(),紧接其后输入

ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)

ON_MESSAGE(WM_MOUSEHOVER,OnMouseHover)

 

难点二:

下面我们看看DRAWITEMSTRUCE结构为我们提供了哪些有用信息呢?

DRAWITEMSTRUCT结构的定义如下:

 

typedefstruct  tagDRAWITEMSTRUCT

{

    UINT  CtlType;                      //控件类型

    UINT  CtlID;                        //控件ID

    UINT  itemID;                       //菜单项、列表框或组合框中某一项的索引值

    UINT  itemAction;                    //控件行为

    UINT  itemState;                     //控件状态

    HWND  hwndItem;                   //父窗口句柄或菜单句柄

    HDC   hDC;                        //控件对应的绘图设备句柄

    RECT  rcItem;                       //控件所占据的矩形区域

    DWORD itemData;                   //列表框或组合框中某一项的值

}DRAWITEMSTRUCT, *PDRAWITEMSTRUCT, *LPDRAWITEMSTRUCT;

其实不仅是按钮控件,其它控件,如ComboBox、ListBox、StaticText等都是通过DRAWITEMSTRUCT来记录控件信息的。关于这个结构的详细文档可参考本篇的附录。

 

也许你早已看到许多自绘按钮的例子,实际上自绘按钮本身的函数结构都是差不多的,它们显示效果的区别主要取决于代码编写 者对GDI作图函数的运用与掌握程度。有兴趣的朋友可以研究一下CXPButton类中DrawItem函数的数据结构,其实只要修改一下其中GDI绘图 函数的部分代码,马上又能做出另一个自绘按钮控件了。

 

 三、按钮类的使用

 

下面演示CXPButton类的使用。往对话框中添加一个按钮控件,假设它的ID值为IDC_BUTTON1。进入类向 导(Class Wizard)的Member Variables属性页,为IDC_BUTTON1添加一个变量m_btnNormal。确定退出后再进行编译,就可以看到重新定义过XP风格按钮了。

 

 如果你是之间把CXPButton的源文件引入自己的工程中的,那么在上图的Variable type中是看不到CXPButton选项的。但是可以通过以下方法加入:

 

1. 首先保存工程后退出。

2. 在工程的目录下找到一个后缀名为.clw的文件,将其删除。但是为了以防万一还是建议你实现备份一下。

3. 重新打开工程,进入类向导,此时会看到一下一个弹出对话框,我们选择“是(Yes)”。

   

4. 再选择“Add All”,这样我们就可以在类向导中使用CXPButton的变量类型了。

 

 四、小结与提示

 

对于按钮来说,当按钮上面任何可见的部分发生变换的时候,都要调用DrawItem函数进行重绘。自绘制按钮必须设定 BS_OWNERDRAW的属性,设置的代码在PreSubclassWindows函数中完成。另外为了防止系统字体设置的变化影响控件的表达效果,还 可以在该函数中为控件指定某种固定的字体。但是要注意的是这个

让我们来回顾一下实现自绘按钮的基本步骤:

a. 确定设计方案;

b. 初始化,但是记得要在函数退出前恢复先前的GDI对象,并释放所占领的资源;

c. 添加相应消息函数;

d. 添加绘图函数DrawItem,在DrawItem中作图的顺序一般是先画外边框,再上底色,接着写文字,最后是画内边框。不过有些人也喜欢把边框放到最后画,这问题不大。

 

 五、附录

 

DRAWITEMSTRUCT结构文档 (根据Msdn翻译)

 

DRAWITEMSTRUCT

 

DRAWITEMSTRUCT为需要自绘的控件或者菜单项提供了必要的信息。在需要绘制的控件或者菜单项对应的WM_DRAWITEM消息函数中得到一个指向该结构的指针。 DRAWITEMSTRUCT结构的定义如下:

 

typedef  struct  tagDRAWITEMSTRUCT

{

UINTCtlType ;

UINTCtlID ;

UINTitemID ;

UINTitemAction ;

UINTitemState ;

HWNDhwndItem ;

HDC hDC;

RECTrcItem ;

ULONG_PTRitemData ;

} DRAWITEMSTRUCT;

 

结构成员:

 

CtlType

指定了控件的类型,其取值如下表所示。

取值

描述

ODT_STATIC

静态文本控件

ODT_BUTTON

按钮控件

ODT_COMBOBOX

组合框控件

ODT_LISTBOX

列表框控件

ODT_LISTVIEW

列表视图控件

ODT_MENU

菜单项

ODT_TAB

Tab控件

 

CtlID

指定了自绘控件的ID值,而对于菜单项则不需要使用该成员

 

itemID

表示菜单项ID,也可以表示列表框或者组合框中某项的索引值。对于一个空的列表框或组合框,该成员的值为–1。这时应用 程序只绘制焦点矩形(该矩形的坐标由rcItem 成员给出)虽然此时控件中没有需要显示的项,但是绘制焦点矩形还是很有必要的,因为这样做能够提示用户该控件是否具有输入焦点。当然也可以设置 itemAction 成员为合适值,使得无需绘制焦点。

 

itemAction

指定绘制行为,其取值可以为下表中所示值的一个或者多个的联合。

 

取值

描述

ODA_DRAWENTIRE

当整个控件都需要被绘制时,设置该值

ODA_FOCUS

如果控件需要在获得或失去焦点时被绘制,则设置该值。此时应该检查itemState成员,以确定控件是否具有输入焦点。

ODA_SELECT

如果控件需要在选中状态改变时被绘制,则设置该值。此时应该检查itemState 成员,以确定控件是否处于选中状态。

 

itemState

指定了当前绘制操作完成后,所绘项的可见状态。例如,如果菜单项应该被灰色显示,则可以指定ODS_GRAYED状态标志。其取值可以为下表中所示值的一个或者多个的联合。

 

取值

描述

ODS_CHECKED

如果菜单项将被选中,则可设置该值。该值只对菜单项有用。

ODS_COMBOBOXEDIT

在自绘组合框控件中只绘制选择区域。

ODS_DEFAULT

默认值。

ODS_DISABLED

如果控件将被禁止,则设置该值。

ODS_FOCUS

如果控件需要输入焦点,则设置该值。

ODS_GRAYED

如果控件需要被灰色显示,则设置该值。该值只在绘制菜单时使用。

ODS_HOTLIGHT

Windows 98/Me, Windows 2000/XP: 如果鼠标指针位于控件之上,则设置该值,这时控件会显示高亮颜色。

ODS_INACTIVE

Windows 98/Me, Windows 2000/XP: 表示没有激活的菜单项。

ODS_NOACCEL

Windows 2000/XP: 控件是否有快速键盘。

ODS_NOFOCUSRECT

Windows 2000/XP: 不绘制捕获焦点的效果。

ODS_SELECTED

选中的菜单项。

 

hwndItem

指定了组合框、列表框和按钮等自绘控件的窗口句柄;如果自绘的对象时菜单项,则表示包含该菜单项的菜单句柄。

 

hDC

指定了绘制操作所使用的设备环境。

 

rcItem

指定了将被绘制的矩形区域。这个矩形区域就是上面hDC的作用范围。系统会自动裁剪组合框、列表框或按钮等控件的自绘制 区域以外的部分。也就是说 rcItem中的坐标点(0,0)指的就是控件的左上角。但是系统不裁剪菜单项,所以在绘制菜单项的时候,必须先通过一定的换算得到该菜单项的位置,以保 证绘制操作在我们希望的区域中进行。

 

itemData

对于菜单项,该成员的取值可以是由

CMenu::AppendMenu、

CMenu::InsertMenu或者

CMenu::ModifyMenu

等函数传递给菜单的值。

 

对于列表框或这组合框,该成员的值可以为由

ComboBox::AddString、

CComboBox::InsertString、

CListBox::AddString或者

CListBox::InsertString

等传递给控件的值。

 

如果ctlType 的取值是ODT_BUTTON或者ODT_STATIC, itemData的取值为0。

 

 

摘于: http://blog.csdn.net/weiwangchao_/article/details/6832566

MFC NM_CUSTOMDRAW

继承类的方式

BEGIN_MESSAGE_MAP(CTreeCtrlEx, CTreeCtrl)
//{{AFX_MSG_MAP(CTreeCtrlEx)
    ON_NOTIFY_REFLECT( NM_CUSTOMDRAW, On_NmCustomDraw ) 
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CTreeCtrlEx::On_NmCustomDraw(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);
	
	LPNMTVCUSTOMDRAW lpnmcd = (LPNMTVCUSTOMDRAW) pNMCD;
	if (lpnmcd ->nmcd.dwDrawStage == CDDS_PREPAINT)
	{
		
		*pResult = CDRF_NOTIFYITEMDRAW;
		return;
	}
	else if (lpnmcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT ) 
	{
#if 1
		CRect rcItem(pNMCD->rc); // Item的区域
		POINT ptItem ;
		ptItem.x = rcItem.left  ;
		ptItem.y = rcItem.top  ;
		UINT uFlags; 
		HTREEITEM hItem = HitTest(ptItem, &uFlags); // Item 句柄
		CImageList  *img_list = this->GetImageList( TVSIL_NORMAL );
		int i,i_s;
		if(!hItem)
		{
			*pResult = CDRF_DODEFAULT;
			return;
		} 
		
		HDC hdcItem = pNMCD->hdc ; // Item的dc
		CDC *dc = CDC::FromHandle( hdcItem );
		CString strText;
		strText=GetItemText(hItem); 

		this->GetItemImage( hItem,i,i_s );
		dc->DrawIcon( rcItem.left,rcItem.top,img_list->ExtractIcon( i )  );
		rcItem.left += 32;
		dc->DrawText(strText,rcItem,DT_TOP );
		rcItem.top += 16;
		dc->DrawText("副标题",rcItem,DT_TOP );
		*pResult = CDRF_SKIPDEFAULT; 
		return; 
#else
		CRect rcItem(pNMCD->rc); // Item的区域
		POINT ptItem ;
		ptItem.x = rcItem.left + 1 ;
		ptItem.y = rcItem.top + 1 ;
		UINT uFlags; 
		HTREEITEM hItem = HitTest(ptItem, &uFlags); // Item 句柄
		if(!hItem)
		{
			*pResult = CDRF_DODEFAULT;
			return;
		} 
		
		HDC hdcItem = pNMCD->hdc ; // Item的dc
		CDC dc ;//= CDC::FromHandle( hdcItem );
		CString strText;
		strText=GetItemText(hItem); 
		dc.Attach(hdcItem); 
		 int nSave = dc.SaveDC(); 
		//dc.SetBkMode(TRANSPARENT);
		dc.DrawText( "111",rcItem,DT_TOP );
		 dc.RestoreDC(nSave);
		dc.Detach(); 
		*pResult = CDRF_SKIPDEFAULT; 
		return; 
#endif
	}
	*pResult = CDRF_DODEFAULT;
	return; 
	
}

 

	afx_msg void On_NmCustomDraw(NMHDR *pNMHDR, LRESULT *pResult);

一步一步教你实现CTreeCtrl 自绘

一步一步教你实现CTreeCtrl 自绘

  -------BY wojiushi3344   

QQ:513670524  转载请说明出处

 

             源代码下载

    最近因工作需求,需要自绘CTreeCtrl。由于原来从来没有自绘过,开始在网上搜索资料,查询(因此本文有些知识可能不全面,或许还有更好的办法来实现,还请大家多多指教。)经过一段时间的编写,终于写好了。在此,感谢网友bunpkin提供的实例参考。

先贴上效果图,如果觉得还不错,那就继续往下看吧。如果觉得不行的,请飘过。

 如何你看见这句话我会很高兴,因为至少我写的东西对你还是有一点点的吸引了。在此谢过!

很好,那现在让我们来说说为什么要自绘CTreeCtrl。我总结了以下2点需要自绘的情况。

1.当系统自带的树形控件已不满足我们的要求时,我们需要自绘。就像上图一样我们需要在后面显示我们额外的图标。

2.当你是一个追求界面美观的人时,我们需要自绘

 我们需要自绘CTreeCtrl控件,我们就必须先了解一下自绘的方法,

CTreeCtrl自绘有2种方法可以实现。

第一种:通过从写NM_CUSTORMDRAW反射消息实现自绘。

第二种 通过重写   ON_PAINT实现自绘。

 二种方法都是通过继承CTreeCtrl类,然后重写虚函数实现。

  下面分别介绍每一种的方法:

 第一种:通过从写NM_CUSTORMDRAW反射消息实现自绘。从这个消息的英文单词我们翻译过来就是自定义绘制。当CTreeCtrl控件需 要绘制就会触发这个消息。需要注意的是这个函数被调用的时候只是绘制了当前的某一个节点,意思就是当我们的CTreeCtrl有10个节点需要绘制的时候 这个函数就需要调用10次。

这个是函数原型

void CMyTreeCtrl::OnNMCustomdraw(NMHDR *pNMHDR, LRESULT *pResult)

这个函数会给我们传入一个pNMHDR指针,这个指针有我们很关心的数据,如当前的HDC,RECT,和当前的节点信息,但是必须要通过转换。下面是转换语句。

NMTVCUSTOMDRAW *ptvTreeCtrl=(NMTVCUSTOMDRAW *)pNMHDR

 可能有的朋友会问为什么需要类型转换了,这是由于在我们的程序中收到NM_CUSTORMDRAW消息的不止CTreeCtrl一个,其它的控件也能收到,这里我们我为了区分是哪个控件收到的消息所以我们需要对应的类型转换。下面是常见控件的类型转换类型。

 

Control Structure
List view NMLVCUSTOMDRAW
ToolTips NMTTCUSTOMDRAW
Tree view NMTVCUSTOMDRAW
All other supported controls NMCUSTOMDRAW

 很明显我们根据上面的图一眼就能看出CTreeCtrl对应的类型是NMTVCUSTOMDRAW。

下面我们在来看看我们最关心的NMTVCUSTOMDRAW 结构里面存的是什么数据。

NMTVCUSTOMDRAW结构定义:
typedef struct tagNMTVCUSTOMDRAW {
 NMCUSTOMDRAW nmcd;//包含控件的基本信息(见下表)

 COLORREF clrText;//节点的文本颜色

 COLORREF clrTextBk;//文本背景色
}NMTVCUSTOMDRAW, *LPNMTVCUSTOMDRAW;

 NMCUSTOMDRAW结构定义:
typedef struct tagNMCUSTOMDRAWINFO {
 NMHDR hdr;//跟pNMHDR一样,我基本没用到

 DWORD dwDrawStage;//绘画段,某项被檫出前,后,绘制前,后

  HDC hdc;//控件的设备上下文句柄
 RECT rc;//要绘制的区域
 DWORD dwItemSpec;//树控件不需要这个变量
 UINT uItemState;//项的状态,只要是点击选中 

LPARAM lItemlParam //项关联的数据,通过SetItemData函数设置的。
}NMCUSTOMDRAW, FAR* LPNMCUSTOMDRAW;

  uItemState项的状态(来自MSDN)

Specifies the current item state. It can be a combination of the following values.
Value              Description
CDIS_CHECKED       The item is checked.  项被核记了

CDIS_DEFAULT       The item is in its default state. 默认状态

CDIS_DISABLED      The item is disabled.  项被禁止了

CDIS_FOCUS         The item is in focus.  项具有焦点
CDIS_GRAYED        The item is grayed.   项为灰颜色,
CDIS_HOT           The item is currently under the pointer (hot).  鼠标当前停留在这个项上

CDIS_SELECTED      The item is selected.  项被选中了

 以上就是我们自绘需要知道的数据结构,如果你了解这些数据结构所代表的意思,那下面我们就可以开始绘制了。

 

绘制方法

NMCUSTOMDRAW消息自绘,使你可以决定在什么绘画端(就是NMCUSTOMDRAW 中的DWORD dwDrawStage)来绘制,比较常用的是在绘制前的阶段来绘制,如果你只是用了这种方法来绘制画,那么恭喜你选择对了一半,但是绘制失败了,因为你将什么也看不见。不急,让我们慢慢给你说明原因,因为你在绘制前的阶段绘制了,紧接这系统还会调用一次默认绘制,那么你原来的绘制就被覆盖了。

 正确的方法是在绘制前绘制,然后过滤点系统的默认绘制,使之不在调用。这样我们所绘制就能看见了。于是乎在我们的OnNMCustomdraw函数中多了一下几句代码。(过滤系统的默认绘制)

  1. if (lpnmcd ->nmcd.dwDrawStage == CDDS_PREPAINT)    
  2.  {    
  3.     *pResult = CDRF_NOTIFYITEMDRAW;    
  4.      return;    
  5.   }    
  6. else if (lpnmcd->nmcd.dwDrawStage == CDDS_ITEMPREPAINT)    
  7.   {    
  8. //自定义绘制  
  9. *pResult = CDRF_DODEFAULT;    
  10.    return;    
  11.  }  

很好,现在你已经知道了绘制的基本方法了,那么接下来你就可以加上你自己的绘制了。

大致思路如下。

获取当前绘制节点的信息。如:节点状态,节点区域,节点文字等信息

需要掌握的函数:

CTreeCtrl::GetItemRect

BOOL GetItemRect( HTREEITEM hItem, LPRECT lpRect, BOOL bTextOnly );

返回值:
如果项是可视的则返回非零值,以及包含在lpRect中的边界矩形。否则,返回0和没有被初始化的lpRect。

参数:

hItem 一个tree view项的句柄。
lpRect 指向一个用来接收边界矩形的RECT结构的指针。其中的坐标是相对于该tree view控件的左上角的。
bTextOnly 如果这个参数是非零值,则边界矩形值包括项的文本。否则,它包括该项在tree view控件所占据的整个一行。

CTreeCtrl::GetItemText

CString GetItemText( HTREEITEM hItem ) const;

返回值:返回一个包含该项的文本的CString对象。

参数:

hItem 要获取其文本的项的句柄。

添加自己的绘制函数,如绘制图片,绘制文字等。

 CTreeCtrl::ItemHasChildren

BOOL ItemHasChildren( HTREEITEM hItem );

返回值:
如果由hItem指定的tree项有子项则返回非零值;否则返回0。

参数:

 

hItem 一个tree项的句柄。

 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


如过你讨厌记住以上的这么多数据,那么恭喜你,你可以继续网下看,下面介绍另一种实现自绘的方法.通过重写 ON_PAINT消息来实现自绘,也是我最终实现自绘的方法。因为我发现通过上面的方法来实现自绘解决不了我的问题。闪烁和热点,也许是我自己的能力有 限。大家可以分享一下你们是如何解决我遇到的问题的。

 原理:

我们获取树形控件的数据结构和DC,然后我们自己来定义绘制的规则。这里就可以发挥你的DIY兴趣了,想怎么画就怎么画。

 很好,下面让我们进入另一种方法的介绍

首先我们要明白ON_PAINT消息在什么情况下触发,在win32程序中,当窗口需要重绘的时候会触发ON_PAINT消息,还有一种情况就是我 们自己手动触发,手动触发的消息有两种,第一种是调用窗口无效函数Invalidate(FALSE),第2种是手动发送wm_paint消息。

明白了这个我们才知道我们以后需要窗口重绘的时候怎么处理,这里说点题外话,原来在做扫雷游戏的时候,鼠标单击之后要过20多毫秒才有反应,后来查了半天原因才发现是带用重绘的问题,因为我开始单机之后没有立即调用重绘,而是没隔50毫秒调用一次。

我们通过重写ON_PAINT消息就能获取当前窗口的DC,在这里我们就是整个树形控件的DC,不向上面那种方法一样只获取到树形控件某节点的DC,获取整个DC要比上面那种方法操作方便一些。

下面是onpaint方法:

void CMyCtreeCtrl::OnPaint()

CPaintDC dc(this); //这句就是获取绘制的DC

现在有了DC我们就可以绘制了,在这里我们为了让它绘制的时候不闪烁我们用双缓冲,于是乎我们有了下面的代码。

  1. CPaintDC dc(this); // device context for painting  
  2.  GetClientRect(&m_ClientRect);  
  3.  CBitmap bitmap;  
  4.  CDC MemeDc;  
  5.  MemeDc.CreateCompatibleDC(&dc);  
  6.  bitmap.CreateCompatibleBitmap(&dc, m_ClientRect.Width(), m_ClientRect.Height());  
  7.  CBitmap *pOldBitmap = MemeDc.SelectObject(&bitmap);  
  8.  DrawBack(&MemeDc);  
  9.  DrawItem(&MemeDc);  
  1. dc.BitBlt( m_ClientRect.left, m_ClientRect.top, m_ClientRect.Width(), m_ClientRect.Height(), &MemeDc, 0, 0,SRCCOPY);  
  2. MemeDc.SelectObject(pOldBitmap);  
  3. MemeDc.DeleteDC();  
  1. 可以看见我们在函数中首先绘制了背景然后再背景上绘制了控件。具体的函数实现请看下面的介绍。  

在这里我们基本的东西已经具备了现在我们就差数据了,首先我们要实现我们最开始的那种效果,我们需要定义一个结构体来存储这些数据。

struct TREE_STRUCT
{
 int s_FirstImage;                  //第一张图片的信息
 int s_SecondImage;            //第二张图片的信息
 int s_ThreeImage;                //第三张图片的信息
 int s_FourImage;                  //第四张图片的信息
 COLORREF s_TextColor;   //文字的颜色
 int    s_PeopleNum;              //人的数目
 CString  s_ItemStr;                //每一项的文字
 CString  s_StrUrl;                   //每一项对应的URL地址

我们在定义一个map

map <HTREEITEM,TREE_STRUCT>  m_mapTree; 这是为了我们以后的绘制和判断热点用。

 

有了数据结构,我们现在就可以插入数据使之成为一颗拥有节点的数,这个插入我们也需要自己重写,因为插入的数据是我们自己定义的。

 

  1. HTREEITEM CMyCtreeCtrl::InsertItemEx(TREE_STRUCT pStruct,HTREEITEM lparent,HTREEITEM  lpFont )//插入项  
  2. {  
  3.     HTREEITEM tempTreeItem;  
  4.     CString str;  
  5.     str.Format("%s(%d人)",pStruct.s_ItemStr,pStruct.s_PeopleNum);  
  6.     tempTreeItem = InsertItem(str,lparent,lpFont);  
  7.     m_mapTree.insert(pair<HTREEITEM,TREE_STRUCT>(tempTreeItem,pStruct));  
  8.     return  tempTreeItem;  
  9.   
  10. }  

 

下面是绘制树形控件的具体实现 

  1. void CMyCtreeCtrl::DrawItem(CDC* pDc)  
  2. {  
  3.  HTREEITEM currentItem,parentItem;//当前的句柄,和它的父节点的句柄  
  4.  DWORD    treeStyle;// 数的类型  
  5.  CRect    itemRect;//每一项的区域  
  6.  int      itemState;//某项的状态  
  7.  //bool selected;    //True:表示是需要高亮   
  8.   
  9.  ImageAttributes alphaAttribut;   
  10.  alphaAttribut.SetColorKey(Color::Fuchsia,Color::Fuchsia);   
  11.   
  12.  treeStyle =:: GetWindowLong( m_hWnd, GWL_STYLE );  
  1. currentItem = GetFirstVisibleItem();//获取第一个课可见的项  
  2. do   
  3. {  
  4.  if (GetItemRect(currentItem,itemRect,TRUE))  
  5.  {  
  6.   itemRect.left=itemRect.left-19;  
  7.   CRect   fillRect(0,itemRect.top,m_ClientRect.right,itemRect.bottom);  
  8.   itemState = GetItemState(currentItem,TVIF_STATE);  
  9.   if (itemRect.top>m_ClientRect.bottom)  //说明这一项已超出窗口的边界,所以不绘制,很好理解吧!不用我说了撒  
  10.   {  
  11.    break;  
  12.   }  
  13.   //绘制鼠标热点  
  14.   if (currentItem==m_MouseMoveItem&&ItemHasChildren(currentItem)==NULL)  
  15.   {  
  16.    m_Gdiplus.usFillRectangle(pDc->m_hDC,fillRect,0xB7F0FE,0xB7F0FE,edoVertical,true);  
  17.   }  
  18.   
  19.   if(itemState&TVIS_SELECTED)  
  20.   {  
  21.    m_Gdiplus.usFillRectangle(pDc->m_hDC,fillRect,0xFF00BB,0xFF00BB,edoVertical,true);  
  22.   
  23.   }  
  24.   //绘制展开图片  
  25.   if (ItemHasChildren(currentItem))  
  26.   {  
  27.    CPoint point;  
  28.    point.x = itemRect.left;  
  29.    point.y = itemRect.top+(itemRect.Height()-m_OpenHigh)/2;  
  30.   
  31.    if (itemState & TVIS_EXPANDED)  
  32.    {  
  33.     m_IconList.Draw(pDc,1,point,ILD_TRANSPARENT);  
  34.    }else  
  35.    {  
  36.     m_IconList.Draw(pDc,0,point,ILD_TRANSPARENT);  
  37.    }  
  38.   
  39.   }  
  40.   itemRect.left+=m_OpenWidth+2;  
  41.   itemRect.right+=m_OpenWidth+8;  
  42.   //绘制图标1  
  43.    m_iter=m_mapTree.find(currentItem);  
  44.    Graphics tempGraphics(pDc->m_hDC);  
  45.    Rect rcDes;  
  46.   
  47.   if (m_iter->second.s_FirstImage>=0&&m_iter->second.s_FirstImage<m_IconNum)  
  48.   {  
  49.    rcDes=Rect(itemRect.left,fillRect.top+m_IconSpacing,m_IconWidt,m_IconHigh);  
  50.   tempGraphics.DrawImag(m_IconBitmap,rcDes,m_iter>second.s_FirstImage*m_IconWidt,0,m_IconWidt,m_IconHigh,UnitPixel,&alphaAttribut);  
  51.   itemRect.left =itemRect.left+m_IconWidt;  
  52.   itemRect.right = itemRect.right+m_IconWidt;  
  53.   
  54.   }  
  1.    //绘制文字  
  2.    DrawItemText(pDc,currentItem,itemRect);  
  3.   
  4.    //绘制后面的第2,3,4项图标  
  5.    CSize  fontSize;  
  6.    fontSize= pDc->GetTextExtent(GetItemText(currentItem));  
  7.    itemRect.left+=fontSize.cx;  
  8.    if (m_iter->second.s_SecondImage>=0&&m_iter->second.s_SecondImage<m_IconNum)  
  9.    {  
  10.     rcDes=Rect(itemRect.left,fillRect.top+m_IconSpacing,m_IconWidt,m_IconHigh);  
  11.     tempGraphics.DrawImage(m_IconBitmap,rcDes,m_iter->second.s_SecondImage*m_IconWidt,0,m_IconWidt,m_IconHigh,UnitPixel,&alphaAttribut);  
  12.     itemRect.left=itemRect.left+m_IconWidt+4;  
  13.    }  
  14.   
  15.   }  
  16.  } while ((currentItem=GetNextVisibleItem(currentItem)) != NULL);  
  17. }  


 

函数的主要思路首先通过GetFirstVisibleItem();获取第一个可见的节点,如果节点存在则按照我们的绘制顺序绘制,然后调用GetNextVisibleItem获得下一个可见的节点,一直循环,直到下一个可见节点为NULL的时候退出绘制函数。

下面讲一下获取项热点的方法。同样我们需要重写消息,这次是ON_MOUSEMOVE消息。

我们首先定义一个数据来记录当前鼠标移动到的节点的句柄。具体看代码。

 

  1. HTREEITEM        m_MouseMoveItem;                                          //鼠标移动到的项  
  2. void CMyCtreeCtrl::OnMouseMove(UINT nFlags, CPoint point)  
  3. {  
  4.  // TODO: 在此添加消息处理程序代码和/或调用默认值  
  5.   m_ptOldMouse = point;  
  6.  HTREEITEM hItem = HitTest(point);  
  7.  if ( hItem != NULL && hItem != m_MouseMoveItem )  
  8.  {  
  9.   m_MouseMoveItem = hItem;  
  10.   Invalidate(FALSE);  
  11.  }  
  12. //CTreeCtrl::OnMouseMove(nFlags, point);  
  13. }  
  14.   
  15. 接下来我们通过获取当前绘制的节点和m_MouseMoveItem比对,如果相同则设置当前的背景颜色,从而实现热点时间  
  16.   
  17. //绘制鼠标热点  
  18.    if (currentItem==m_MouseMoveItem&&ItemHasChildren(currentItem)==NULL)  
  19.    {  
  20.     m_Gdiplus.usFillRectangle(pDc->m_hDC,fillRect,0xB7F0FE,0xB7F0FE,edoVertical,true);  
  21.    }  
  22.   
  23. //通过获取当前状态来判断单击事件。  
  24.   
  25.    if(itemState&TVIS_SELECTED)  
  26.    {  
  27.     m_Gdiplus.usFillRectangle(pDc->m_hDC,fillRect,0xFF00BB,0xFF00BB,edoVertical,true);  
  28.   
  29.    }  
  30. <p>这2句代码都在DrawItem函数中。</p>  

 

 之后在我们的一些常见操作之后触发WN_PAINT就可以了。

 这种重写ON_PAINT消息实现自绘的方法就是这些了,有没有觉得比我们前面的那种方法要简单好理解一些了。下面说说我为什么选择这种方法而不 用上面一种方法的原因,首先ON_PAINT可以获取到树形控件的整个DC,感觉绘制的时候方便一些,我想绘制到什么地方就绘制到什么地方,容易控制。其 次是这种方法需要掌握的数据结构比较的少就需要知道几个常见的函数就OK了。

 

需要掌握的函数:

CTreeCtrl::GetFirstVisibleItem
HTREEITEM GetFirstVisibleItem( );
返回值:如果成功则返回第一个可视项的句柄;否则返回NULL。
说明:
此成员函数用来获取该tree view控件中的第一个可视项的句柄。

CTreeCtrl::GetNextVisibleItem
HTREEITEM GetNextVisibleItem( HTREEITEM hItem );
返回值:返回下一个可视项的句柄;否则返回NULL。
参数:

 

hItem 一个tree项的句柄。

说明:此成员函数用来获取hItem的下一个可视项。

 CTreeCtrl::ItemHasChildren
BOOL ItemHasChildren( HTREEITEM hItem );
返回值:
如果由hItem指定的tree项有子项则返回非零值;否则返回0。

参数:

 

hItem 一个tree项的句柄。

 CTreeCtrl::GetItemText
CString GetItemText( HTREEITEM hItem ) const;
返回值:返回一个包含该项的文本的CString对象。
参数:

 

hItem 要获取其文本的项的句柄。

说明:
此成员函数返回由hItem指定的项的文本。

 CTreeCtrl::GetItemRect
BOOL GetItemRect( HTREEITEM hItem, LPRECT lpRect, BOOL bTextOnly );
返回值:
如果项是可视的则返回非零值,以及包含在lpRect中的边界矩形。否则,返回0和没有被初始化的lpRect。
参数:

hItem 一个tree view项的句柄。
lpRect 指向一个用来接收边界矩形的RECT结构的指针。其中的坐标是相对于该tree view控件的左上角的。
bTextOnly

如果这个参数是非零值,则边界矩形值包括项的文本。否则,它包括该项在tree view控件所占据的整个一行。

 

 

 

 

摘于: http://blog.csdn.net/wojiushi3344/article/details/7463942

Android手机代码查询命令大全

*#*#4636#*#*
  显示手机信息、电池信息、电池记录、使用统计数据、WiFi 信息
*#*#7780#*#*
  重设为原厂设定,不会删除预设程序,及SD卡档案。
*2767*3855#
  重设为原厂设定,会删除SD卡所有档案。
*#*#34971539#*#*
  显示相机相机韧体版本,或更新相机韧体
*#*#7594#*#*
  当长按关机按钮时,会出现一个切换手机模式的窗口,包括: 静音模式、飞航模式及关机,你可以用以上代码,直接变成关机按钮。
*#*#273283*255*663282*#*#*
  开启一个能让你备份媒体文件的地方,例如相片、声音及影片等
*#*#197328640#*#*启动服务模式,可以测试手机部分设置及更改设定WLAN、 GPS 及蓝牙测试的代码
*#*#232338#*#* 显示 WiFi MAC 地址
*#*#1472365#*#* GPS 测试
*#*#1575#*#* 其它 GPS 测试
*#*#232331#*#* 蓝牙测试
*#*#232337#*# 显示蓝牙装置地址
*#*#8255#*#*启动 GTalk 服务监视器
显示手机软件版本的代码:
*#*#1234#*#* PDA 及 Phone
*#*#1111#*#* FTA SW 版本
*#*#2222#*#* FTA HW 版本
各项硬件测试
*#*#0283#*#* Packet Loopback
*#*#0*#*#* LCD 测试
*#*#0842#*#* 装置测试,例如振动、亮度
*#*#2663#*#* 触控屏幕版本
*#*#2664#*#*触控屏幕测试
*#*#0588#*#* 接近感应器测试
*#*#3264#*#* 内存版本
*#06#显示手机原厂出厂串号(移动通信国际识别码)

 

 

摘于: http://bbs.anzhi.com/thread-7749842-1-1.html

Gentoo下emerge用法

避免升级覆盖掉版本更高的软件

emerge -uU world
emerge --update --upgradeonly world

查找名称包含mozilla的包

emerge -s mozilla
emerge search mozilla

查找描述包含mozilla

emerge -S mozilla
emerge --searchdesc mozilla

使用本地编好的包,没有就下源码(尽量避免编译)

emerge -k mozilla
emerge --usepkg mozilla

只使用本地编好的,否则不安装(绝对不编译,所有依赖的包都有binary才装)

emerge -K mozilla
emerge --usepkgonly mozilla

卸载
emerge -C mozilla
emerge unmerge mozilla

升级portage树

emerge sync

下载snapshot包来完成sync
emerge-webrsync

查看已安装包的changelog

emerge -pl mozilla
emerge --pretend --changelog mozilla

查看依赖关系(这个包还没装)
(--pretend保证这一次操作实际上不做任何事情,可以跟任何options组合)
emerge -p mozilla
emerge --pretend mozilla

只下载某个软件的源码(以及它所依赖的)

emerge -f mozilla
emerge --fetchonly mozilla

查看从哪下的源码

emerge -fp mozilla

安装指定版本号的

emerge "<mozilla-1.6"
emerge "=..........."
.......">..........."

emerge -k "<mozilla-1.6".....


从网上下binary包来装

emerge -g mozilla
emerge --getbinpkg mozilla
(注意,实际上没有任何binary包存在于官方的mirror中
所以这个基本上是无用,在manpage也没有出现。除非自
己用livecd来setup一个这样的站点。不知道以后会不会
出现这样的mirror。gentoo.org论坛上似乎也有讨论这个。)

查看binary包依赖

emerge -gp mozilla
emrege --getbinpkg --pretend mozilla


查看依赖关系(这个包已经装了)

emerge -ep opera
emerge --emptytree --pretend opera
(不用pretend会重新编译这所有依赖的包,glibc因为安全关系没有列出)

不使用依赖关系安装软件

emerge -O opera
emerge --nodeps opera

只安装其依赖的软件
emerge -o opera
emerge --onlydeps opera

升级软件
emerge -u opera
emerge --update opera

升级系统软件

emerge -u system

升级整个系统

emerge -u world

避免升级覆盖掉版本更高的软件

emerge -uU world
emerge --update --upgradeonly world

查看可用的USE参数

emerge -pv opera

 

 

摘于:http://blog.csdn.net/zhuyingqingfen/article/details/6825647

Gentoo的emerge命令参数用法详解

Gentoo的包管理工具称为portage。emerge是这个portage的字符界面管理工具,图形界面工具还有portato,porthole,kuroo,himerge等。

ebuild

ebuild是Portage包管理程序的根本。它是一个纯文本文件,而每一个ebuild都会对应一个包(软件包)。ebuild会告诉 portage要下载的文件、该包可运行的平台、如何编译它、它所依赖的ebuild和一些修补代码的patch。Portage内有一个ebuild大 集合,称为Portage tree,是gentoo网站所提供的ebuild。它包含了大部份常用的包,并会不时更新。如果要使用的包不在其内,也可以手动加入。

USE标志

USE标志的设置位于Gentoo系统的/etc/make.conf文档中,作用是使得Emerge在处理依赖关系的时候可以做到不安装不需要的软件包(例如安装Gnome的用户没有必要因为一个软件包的依赖关系而安装KDE与Qt),而安装指定的软件包(同样以Gnome举例,Gnome的用户基本上都会安装GTK+),把系统的设置专注化。

Gentoo的emerge命令参数用法详解

查找名称包含mozilla的包

emerge -s mozilla
emerge search mozilla


查找描述包含mozilla

emerge -S mozilla
emerge --searchdesc mozilla


使用本地编好的包,没有就下源码(尽量避免编译)

emerge -k mozilla
emerge --usepkg mozilla


只使用本地编好的,否则不安装(绝对不编译,所有依赖的包都有binary才装)

emerge -K mozilla
emerge --usepkgonly mozilla


卸载

emerge -C mozilla
emerge unmerge mozilla


升级portage树

emerge --sync

下载snapshot包来完成sync

emerge-webrsync

查看已安装包的changelog

emerge -pl mozilla
emerge --pretend --changelog mozilla


查看依赖关系(这个包还没装)
(–pretend保证这一次操作实际上不做任何事情,可以跟任何options组合)

emerge -p mozilla
emerge --pretend mozilla


只下载某个软件的源码(以及它所依赖的)

emerge -f mozilla
emerge --fetchonly mozilla


查看从哪下的源码

emerge -fp mozilla

安装指定版本号的

emerge "..........."

emerge -k "

从网上下binary包来装

emerge -g mozilla
emerge --getbinpkg mozilla


(注意,实际上没有任何binary包存在于官方的mirror中
所以这个基本上是无用,在manpage也没有出现。除非自
己用livecdsetup一个这样的站点。不知道以后会不会
出现这样的mirror。gentoo.org论坛上似乎也有讨论这个。)

查看binary包依赖

emerge -gp mozilla
emrege --getbinpkg --pretend mozilla


查看依赖关系(这个包已经装了)

emerge -ep opera
emerge --emptytree --pretend opera


(不用pretend会重新编译这所有依赖的包,glibc因为安全关系没有列出)

不使用依赖关系安装软件

emerge -O opera
emerge --nodeps opera


只安装其依赖的软件

emerge -o opera
emerge --onlydeps opera


升级软件

emerge -u opera
emerge --update opera


升级系统软件

emerge -u system

升级整个系统

emerge -u world

避免升级覆盖掉版本更高的软件

emerge -uU world
emerge --update --upgradeonly world


查看可用的USE参数
emerge -pv opera

参考文档:http://www.gentoo.org/doc/zh_cn/index.xml

: http://www.ha97.com/3192.html

 

 

 

摘于: http://www.ha97.com/3192.html