2010年6月10日星期四

How to select a row in DataGridView

the C++.Net solution is :
this->dataGridView1->ClearSelection();
this->dataGridView1->SelectionMode = DataGridViewSelectionMode::FullRowSelect;
this->dataGridView1->Rows[i]->
Selected=true;
this->dataGridView1->
CurrentCell=this->dataGridView1->Rows[i]->Cells["ColumnName"];
这几步的作用分别是:
清除当前选择;设定选择模式为整行选取;设定某行为选定;设定当前网格

2009年4月6日星期一

将U盘格式化为NTFS格式

Windows系统默认只能将U盘格式化为FAT或者FAT32格式,这些格式有个最大文件的限制,还有其他,如保存大量小体积文件时,占用空间比较大。
怎样将U盘格式化为NTFS格式呢?
1. 打开设备管理器
操作方法是我的电脑点击右键,选择管理,在打开的窗口的左边的树中选择“设备管理器”
2. 在设备管理器的树中选择“磁盘驱动器”
3. 在磁盘驱动器中选择USB盘,点击右键,选择属性
4. 在属性窗口中选择策略,选择为性能优化。

好了,这样就可以格式化优盘为NTFS格式了。

2009年3月19日星期四

Using Resources in .NET

我有个C++.NET程序。
在修改Form自带的resx文件时会弹出 警告菜单"You are trying to edit a resources file that ..."
如果强制进行修改,当对Form进行其他修改后,resx会更新,手工进行的修改就会消失。
这是Visual Studio的一个BUG。
但是怎样添加自己想要的resources呢,如运行时载入的图片等等。
这里是一个可行的步骤:

1. 在名为MyProject的Project里添加MyResources.resx
2. 在MyResources.resx中添加你想要添加的Image如MyImage.png等resources资源文件。
注意,图片导入后,后缀就消失了。
3. 在代码中添加如下的代码进行操作:
using namespace System::Resources; // for ResourceManager and MissingManifestResourceException
using namespace System::Reflection; //for Assembly::GetExecutingAssembly()
try{
ResourceManager^ resources = gcnew ResourceManager("MyProject.MyResources", Assembly::GetExecutingAssembly());
this->toolStripMenuItem1->Image = (cli::safe_cast(resources->GetObject(L"MyImage")));

}catch(MissingManifestResourceException^ ex){
MessageBox::Show(ex->Message);
}
上述代码中的MyProject.MyResources是对应的MyProject.MyResources.resources文件名,这个文件在编译后存在于你的Debug和Release文件夹中,如果名字写错了,将会抛出MissingManifestResourceException异常。

好,祝你好运。

2009年3月14日星期六

Is it possible to deploy a .NET exe without installing .NET framework

在没有安装.NET Framework的平台上运行.NET程序,问题是可能吗?
答案是:没有不可能。
C#的出现是为了与Java抗衡,和Java一样,需要安装虚拟机平台来运行。如果没有CLR,似乎是不行的。但是如果将所有需要的dll都拷贝过来,将其他的所有设置相关的内容都拷贝过来,集成到exe中,不就可以了吗?

怎么做呢?Google Thinstall to Check the detail.
其他的包括

Static Compilation in Mono

Xenocode(Deploy your .NET app securely, with no Framework install ),
Remotesoft(Salamander .NET Linker, Native Compiler and Mini-Deployment Tool)

Thinstall软件已经被VMWare收购了。

.NET framework virtualization

Deploy and run .NET applications - with out installing the .NET framework. Run applications that require different versions of .NET, concurrently, without conflicts and protect code from dissassembly.

Challenges

Developing with the latest release of the .NET framework offers clear advantages. However, deploying an application requiring the latest .NET can present challenges due to a number issues including:

  • Other applications require an earlier version of .NET
  • Locked down desktops can not be upgraded immediately
  • Computers may need to have different versions of .NET installed concurrently

Whether a commercial application distributed to home computers or a custom application to corporate locked down computers, the correct version of the .NET framework - or any of the .NET components - may not be installed. This presents challenges in terms of updating, running, and installing applications and also problems when applications require different .NET versions to be installed.

VMware ThinApp Solution (Formerly Thinstall)

ThinApp provides essential features that make .NET deployments conflict free and secure. Benefits include:

  • Not requiring the .NET Framework to be installed. By packaging the application and linking the .NET framework with ThinApp, no installation of the .NET framework is required. The application runs without modifying the host computer.
  • Eliminating all installation errors and conflicts. ThinApp enables applications to run concurrently that each require a different version of .NET to be installed.
  • Reducing download and installation time. ThinApp packages all of the .NET framework or only the components that the program needs into a single, compressed EXE. This not only reduces the size of the components that need to be installed (and downloaded), but also makes ‘installation’ significantly faster. Nothing is installed, rather the program is run via the ThinApp Virtual Operating System.

Additionally, even applications created for internal corporate use at some point may be distributed externally. .NET applications can be easily disassembled with readily available developer tools that make inspection of source code easy, enabling hacking and reverse engineering relatively simple for any experienced programmer.

ThinApp also protects against hacking and disassembly. Rather than using obfuscation, ThinApp instead encrypts the .NET Program inside of secure loader which prevents disassembly. The resulting EXE no longer appears to be a .NET Program so codedisassemblers are unable to decrypt the program stored inside.

2009年3月4日星期三

error C2143: syntax error : missing ')' before 'constant'

翻译为汉语就是:在常数的前面缺少')'
例如,你在某处 #define A 1
但是在程序中某处又忘记了常数的定义,而使用了int A;等,就会得到这个错误。

一个可能的原因:Additional information: Cannot access a disposed object.

编译正常,但是在执行CSharp程序的时候却出现了Additional information: Cannot access a disposed object.

检查错误,是自己在Load程序中新建了一个Form对象,使用了Show(),改为ShowDialog()后正常。

Built successfully, but fail to run.
change the frmSomething.Show()
into frmSomething.ShowDialog();
Things are OK.

2009年2月28日星期六

How to open multiple files through single ifstream object?

怎样在定义了一个ifstream对象的情况下,打开多个文件。
重点:
每次打开新文件前,确保上一次的文件对象在close()之前被clear()!
// declare one ifstream object for every file

ifstream FileObject;

//open a input file which contain names of all files

ifstream InputFile("Input.txt");

while(std::getline(InputFile,buf)){
std::string name=buf;
FileObject.open(name.c_str());
if (!FileObject.is_open()){
//report error here.
continue;
}
while(std::getline(FileObject,buf2))
{ //doing some validation operations. }
//Clear the fileobject for next use
FileObject.clear();
//Prepare for next open,每次打开前都要clear和close
FileObject.close();
}

2009年2月27日星期五

怎样转换各种String 类型

How to: Convert Between Various String Types
这是MSDN中的内容,在各种不同的string类型间转换,包括System::String和标准C++中的std::string间的转换。
This topic demonstrates how to convert various Visual C++ string types into other strings. The strings types that are covered include char *, wchar_t*, _bstr_t, CComBSTR, CString, basic_string, and System..::.String. In all cases, a copy of the string is made when converted to the new type. Any changes made to the new string will not affect the original string, and vice versa.

// convert_from_char.cpp
// compile with: /clr /link comsuppw.lib

#include
#include
#include

#include "atlbase.h"
#include "atlstr.h"
#include "comutil.h"

using namespace std;
using namespace System;

int main()
{
char *orig = "Hello, World!";
cout << orig << " (char *)" << endl; // Convert to a wchar_t*
size_t origsize = strlen(orig) + 1;
const size_t newsize = 100;
size_t convertedChars = 0;
wchar_t wcstring[newsize];
mbstowcs_s(&convertedChars, wcstring, origsize, orig, _TRUNCATE);
wcscat_s(wcstring, L" (wchar_t *)");
wcout << wcstring << endl;
// Convert to a _bstr_t
_bstr_t bstrt(orig);
bstrt += " (_bstr_t)";
cout << bstrt << endl;
// Convert to a CComBSTR
CComBSTR ccombstr(orig);
if (ccombstr.Append(L" (CComBSTR)") == S_OK)
{ CW2A printstr(ccombstr); cout << printstr << endl; }
// Convert to a CString
CString cstring(orig);
cstring += " (CString)";
cout << cstring << endl;
// Convert to a basic_string
string basicstring(orig);
basicstring += " (basic_string)";
cout << basicstring << endl;

// Convert to a System::String
String ^systemstring = gcnew String(orig);
systemstring += " (System::String)";
Console::WriteLine("{0}", systemstring);
delete systemstring;
}

2009年2月26日星期四

修改堆栈的大小,避免程序调用函数时出现System.StackOverflowException错误

System.StackOverflowException异常通常出现在死循环处。
但是这次我的程序显示异常出现在程序定义行,因为我有一个类里面定义了一个很大的数组。
C#等编译器在编译的时候并没有修改堆栈大小的选项,默认的堆栈大小是1MB,但是可以通过
EditBin.exe程序修改默认的堆栈大小。
如某人的测试:

That works.

Test:

class App {
private static long _Depth = 0;

private static void GoDeep() {
if ((++_Depth % 10000) == 0) System.Console.WriteLine("Depth is " +
_Depth.ToString());
GoDeep();
return;
}

public static void Main() {
try {
GoDeep();
} finally {
}
return;
}
}




editbin /stack:100000,1000 q.exe
Depth is 10000
Depth is 20000

Unhandled Exception: StackOverflowException.

editbin /stack:1000000,1000 q.exe
Depth is 10000
Depth is 20000
Depth is 30000
Depth is 40000
Depth is 50000
Depth is 60000
Depth is 70000
Depth is 80000

Unhandled Exception: StackOverflowException.

2009年2月16日星期一

破解封杀ADSL路由器解决办法全剖析(1)

http://hi.baidu.com/zhxliang521/blog/item/67b2db178da9650cc93d6db5.html

菏泽这边终于开始也封路由器了(为什么要说“终于”?)公司的宽带停了三天,在答应一台线路上一台主机之后,又开通了。

现在我用的是安装共享神盾的方法,17台机器,没问题。如果这方法不行,建议用一下共享卫士(我暂时还没试用,等试用之后再发测试结果)

长久来看,没有什么特别好的办法可以破解,因为网尖(网络尖兵)、南信(南京信风)均属于新兴产品,官方也属于测试阶段,也在不断的升级其自身程 序。就济南而言,没有用网尖就是大幸了,那个东西很据说BT(根椐同一时间内连接数),早在3月份的时候就有外地网友向我求助,当时还有星空极速(对密码 二次加密)拔号软件的。后来也上网查了一些资料,可以说当时那些软件极不成熟,随着破解方法在网络上公布,官方也及时升级了软件。这是一场没有硝烟的战 争。

以下内容是整理的对付网通、电信、铁通封路由、禁止共享上网的最新办法!供大家参考。

最新:常规方法已经无法突破电信ADSL共享封杀

最近桂林市网通、电信、铁通开始对桂林几个重点片区封路由了。这些片区一旦使用路由,TCP连接马上会返回到自己机子(127.0.0.1)来阻止 你上网两分钟。UDP连接,比如说QQ,浩方,可以正常使用。网上传说的方法都已无效。个人做过了一些尝试,现将经历写下,希望高手们能够发现问题。

1、关闭snmp161,162端口,无效,电信立刻能发现你还是在使用路由。

2、把内网机器的网卡MAC都设置成猫的MAC,保持整个网络只有两个MAC地址(PPPOE拨号最少需要两个MAC,一个是网卡MAC,一个是虚拟拨号MAC),无效,还是马上被封掉。已证明电信不是通过侦查MAC来发现路由。

3、通过路由器,只用一台机子A上网,网络OK;用两台A和B同时上网,则会被封。在机器A上打开共享和虚拟网卡,设置网关使机器B通过机器A,机 器A则经过路由来上网,(这样对于路由器来说,只有一台机器连接上网)还是被封。这说明,电信不是通过扫描终端电脑端口来发现是否使用路由,而应该是拦截 数据包进行分析来反路由。

4、使用机器A直接上网,没有使用原带的ICS和NAT协议,而是用另外下载的NAT32增强协议来制作网络共享,机器B通过A上网,马上被封。所 有机器安装防火墙,开到最高级防护,关闭了几乎所有端口,无效,同样被封。使用其他第三方共享协议,比如使用过Homeshare里的Inet制作共享, 同样被封。

5、机器A上网,使用CCproxy软件打开Http和Socks5代理,机器B网页使用Http代理,程序使用Socks代理转换,两个机器都可以上网,没有被封,但使用起来相当麻烦,而且Sock5代理转换不适用于所有程序。

6、机器A单机上网,打开共享,在机器A上安装Vmware和Virtual PC,虚拟的电脑使用真实网卡共享连接(不是使用虚拟机默认的虚拟网卡,而是把虚拟的电脑修改成为真实的局域网里的一部分),虚拟的电脑都有自己不同的网 卡,使用不同的MAC,按理说应该被封,但是却能正常上网。这说明电信对数据包的分析已经达到了最底层,甚至与协议、系统可能都没有关系,应该和机器的真 实物理硬件上的某些数据有关系。(再次申明不是网卡MAC和网卡的牌子等等)

7、以上各种方法综合使用,同样无效。现在可以解决的方法只有:能否用UDP协议通过某种代理完全代替TCP(像QQ那样),或者我们从底层去掉不 同电脑之间的数据的不同,用端口来区分内网机器(电信不是通过端口来侦测,我曾在一台机器上运行老式BT软件打开近千个端口同时连接也没有被封)

希望对网络底层协议有了解和有经验的朋友,根据我提供的信息,进行一下分析,共同寻找解决办法。网上写的一些方法都已无效。全国大面积封路由的时代 很快就要来了。现在电信,网通正在各地进行试点,他们使用的也不是网络尖兵,而是他们内部称为反代理服务器的东西。开发共享软件的朋友,也有一个很好的机 遇在等着你们。

破解封杀ADSL路由器解决办法全剖析(2)

破解方法一:用共享神盾软件

共享神盾(ShareShield),它的功能很专一,就是为了破解电信和网通等运营商对用户的宽带共享的限制。官方下载地址:http://www.sd002.com/shareshield.htm

如果对宽带共享比较关注一点的兄弟应该听说过,有很多运营商都上了一套叫“网络尖兵”的设备,这种设备很神奇,通过它运营商就可以知道一条宽带下面带了多少台机器,如果机器数比较多,运营商就会找上门了。

对于运营商的这种限制,大家都表示很气愤,但是又拿不出一个解决问题的技术手段来,所以说,这个软件是生逢其时阿。

软件的帮助很简单,里面提到每台共享上网的机器都需要安装这个软件(这个是自然啦),然后如果是代理服务器的话,那么代理服务器上不需要安装,如果是宽带路由器,那就更不用做特殊处理了。

被运营商限制的兄弟们,赶紧来体验一下,看看效果如何吧!

步骤1:关闭路由器或者代理服务器SNMP服务。
--如果你是使用宽带路由器上网,那么在宽带路由器中要关闭SNMP协议,具体请参考路由器使用手册。
--如果你是使用代理服务器上网,那么在代理主机中要关闭SNMP协议,可以通过卸载SNMP服务也可以通过防火墙来禁用161端口来实现。

步骤2:在每台使用共享宽带上网的主机上安装“共享神盾”。
--共享神盾完全免费。
--共享神盾专门针对“网络尖兵”设备开发,可以对用户的数据进行隐藏和整流,从而使得“网络尖兵”无法探测到共享主机数量。

“共享神盾”突破共享上网限制的原理是这样:ISP主要是通过类似“网络尖兵”、“信风”等检测软件来限制用户共享上网,当用户主机被检测到发送的 数据报文不一致时,检测软件将会认为有多台主机共享上网,于是进行封锁。“共享神盾”的原理就是让共享上网的所有主机以一致的方式进行报文伪装,“骗 ”ISP以为只有一台电脑在上网。

目前,“共享神盾”最新版本是1.3Beta,不过在安装过程可能会出现微软硬件驱动程序检测的警告而无法安装,我们可以在安装前关闭驱动程序检测 功能,方法是:在桌面上右击“我的电脑”,然后依次点击“属性”→“硬件”→“驱动程序签名”,最后在打开的“驱动程序签名”窗口中选中“忽略-安装软 件,不用征求我的同意”项即可。

所有共享上网的电脑安装好“神盾”后,需要共同启动“共享神盾”,成功启动后保持默认设置即可突破ISP共享上网的限制。在其中一个主机中可以在软件主窗口中看到网络的运行状态。

不过,有的用户在启动“神盾”时并非一帆风顺,可能会出现“启动转发器失败”的提示,这主要是由于主机中不止有一个网卡,这时在出现“启动共享神盾 转发器失败”提示窗口中点击“确定”,进入该界面后点击左侧“突破共享限制”项,然后在右侧“请选定用来上网的网络接口”下选择用来上网的网卡,最后保存 配置并重新启动“共享神盾”即可。

如果仍然不能解决问题,那么请到系统SYSTEM32文件夹中删除wpcap.dll和packet.dll文件,另外在SYSTEM32文件夹下 的 “drivers”子文件夹中删除npf.sys文件,重新启动系统后,再到共享神盾安装目录中运行winpcap.exe程序。

破解封杀ADSL路由器解决办法全剖析(3)

破解方法二:升级路由器软件,采用特殊拨号

注意:这种方法不是所有的路由器都可以,具体的去你品牌的官方网站查询,或打电话给客服。升级软件有危险,各位同志谨慎行事!

【以下方法经本人测试,在菏泽只有正常拨号才能上去,特殊拨号模式1、2、3都不行。】

今天去TP-LINK的官方站点看有没有新的升级文件出来,果然看到了20070110的新版本,升级后里面多了《IP与MAC绑定》,但更让我惊喜的特殊拨号模式已经细分了特殊拨号模式1和特殊拨号模式2,估计是针对不同地区的拨号方法。

经过测试发现特殊拨号模式1是XIAN Vnet authentication(估计是西安地区),特殊拨号模式2是HUBEI Vnet authentication,因为我是湖北地区,在我选择了模式2后不需要加前缀~就可以直接拨号上网,看来对中国电信的流氓行径看不惯大有人在。

因为根据测试和收集的信息,好像每个地区甚至每条线路的前缀都不一样,这样就不需要抓包探测或者测试加前缀就能直接上网了哦,的确方便了许多,配合以前升级时就有的主机伪装功能,破解了对多机共享的限制,宣告了中国电信星空极速和南京信风软件的彻底失败。

感谢TP-LINK为用户想的更多,因为我的影响,至此,我家,办公室,老婆家,老婆办公室,我舅舅家,舅舅公司,表哥家全部都使用TP-LINK 的产品:TL-WR541,版本从V1到V4,TL-WR541+,版本V1。(TL-WR541 V1版本可能是因为硬件原因而不支持特殊拨号模式和主机伪装功能)

破解封杀ADSL路由器解决办法全剖析(4)

破解方法三:共享卫士

共享卫士是树丫工作室研发的新一代共享上网软件,设计简单、安全、易用。软件采用最新网络安全防护技术,提供给用户一种全新的共享上网接入方式,“ 让您充分享受上网冲浪带来的非凡乐趣”。下载地址:http://www.shuyanet.com/download.php

在由共享卫士搭建成的局域网环境内,安装在服务器上的软件会修改各接入主机的Windows底层及IP数据报文做伪装处理,保护用户共享上网安全, 确保用户网络应用不受限制或干扰。本软件支持Windows 2000/Windows XP/Windows 2003等操作系统平台上的ADSL拨号或固定IP接入共享应用,支持单网卡或多网卡共享接入方式。

共享卫士软件无广告,无插件,提供完全免费下载和使用,用户可在本网站或到指定网站下载并享受及时的软件更新服务。

其他方法:

此外,还可以考虑多路由伪装主机(测试成功)。猫现在也带路由功能,于是可以配合本来的路由,开两个路由,使数据两次打包,伪装为一台主机。

另外还有匿名代理突破共享限制(未测试)。即一台主机做代理,使用匿名代理软件,这样信风软件就无法探测到数据包了,我们可以用多台上网了。

最后一种方法不知道算不算破解:你找多些笔记本电脑放到你家里,布好线,之后给网通打电话(语气要硬一些,别让看出破绽),说就是一家人在上,我家 有钱电脑多你管不着,让他上门来看,正常来说他看到后会把你的帐号放到白名单里面,你就可以共享上网了,以下的就不用我说了吧,知道该怎么做了吧。这招不 知道有没有效,个人认为成功机率70%以上。试好了,给个反馈信息!

2009年2月8日星期日

http://mediaplayer.yahoo.com/

可以插入网页的播放器,非常好的播放效果。

2008年12月7日星期日

How do I disable deprecation in VC++ ?

类似这样的警告:
warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

有时(我也搞不明白)在做多个文件的项目时,文件中虽然定义了 #define _CRT_SECURE_NO_WARNINGS 仍然无法排除一大堆的warning.

这样,可以在
Project properties->Configuration Properties->C/C++->Preprocessor->Preprocessor Definitions中,添加一个_CRT_SECURE_NO_WARNINGS行。
这样就不必要在各个头文件中都添加这个预处理了。

2008年11月7日星期五

函数

函数
http://blogger.org.cn/blog/more.asp?name=newqiang&id=10957
作者:fengshaoyang 发表时间:2003-9-9 15:33:00

本人对库函数中的一些函数不太清楚。请高手列出一些,并指出其功能!谢谢!
作者:s_tiger
 第1楼

图形函数
Turbo C提供了非常丰富的图形函数, 所有图形函数的原型均在graphics. h
中, 本节主要介绍图形模式的初始化、独立图形程序的建立、基本图形功能、图
形窗口以及图形模式下的文本输出等函数。另外, 使用图形函数时要确保有显示
器图形驱动程序*BGI, 同时将集成开发环境Options/Linker中的Graphics lib选
为on, 只有这样才能保证正确使用图形函数。
1. 图形模式的初始化
不同的显示器适配器有不同的图形分辨率。即是同一显示器适配器, 在不同
模式下也有不同分辨率。因此, 在屏幕作图之前, 必须根据显示器适配器种类将
显示器设置成为某种图形模式, 在未设置图形模式之前, 微机系统默认屏幕为文
本模式(80列, 25行字符模式), 此时所有图形函数均不能工作。设置屏幕为图形
模式, 可用下列图形初始化函数:
void far initgraph(int far *gdriver, int far *gmode, char *path);
其中gdriver和gmode分别表示图形驱动器和模式, path是指图形驱动程序所
在的目录路径。有关图形驱动器、图形模式的符号常数及对应的分辨率见表2。
图形驱动程序由Turbo C出版商提供, 文件扩展名为.BGI。根据不同的图形
适配器有不同的图形驱动程序。例如对于EGA、 VGA 图形适配器就调用驱动程序
EGAVGA.BGI。

表2. 图形驱动器、模式的符号常数及数值
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
图形驱动器(gdriver) 图形模式(gmode)
─────────── ─────────── 色调 分辨率
符号常数 数值 符号常数 数值
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CGA 1 CGAC0 0 C0 320*200
CGAC1 1 C1 320*200
CGAC2 2 C2 320*200
CGAC3 3 C3 320*200
CGAHI 4 2色 640*200
───────────────────────────────────
MCGA 2 MCGAC0 0 C0 320*200
MCGAC1 1 C1 320*200
MCGAC2 2 C2 320*200
MCGAC3 3 C3 320*200
MCGAMED 4 2色 640*200
MCGAHI 5 2色 640*480
───────────────────────────────────
EGA 3 EGALO 0 16色 640*200
EGAHI 1 16色 640*350
───────────────────────────────────
EGA64 4 EGA64LO 0 16色 640*200
EGA64HI 1 4色 640*350
───────────────────────────────────
EGAMON 5 EGAMONHI 0 2色 640*350
───────────────────────────────────
IBM8514 6 IBM8514LO 0 256色 640*480
IBM8514HI 1 256色 1024*768
───────────────────────────────────
HERC 7 HERCMONOHI 0 2色 720*348
───────────────────────────────────
ATT400 8 ATT400C0 0 C0 320*200
ATT400C1 1 C1 320*200
ATT400C2 2 C2 320*200
ATT400C3 3 C3 320*200
ATT400MED 4 2色 320*200
ATT400HI 5 2色 320*200
───────────────────────────────────
VGA 9 VGALO 0 16色 640*200
VGAMED 1 16色 640*350
VGAHI 2 16色 640*480
───────────────────────────────────
PC3270 10 PC3270HI 0 2色 720*350
───────────────────────────────────
DETECT 0 用于硬件测试
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

例4. 使用图形初始化函数设置VGA高分辨率图形模式
#include
int main()
{
int gdriver, gmode;
gdriver=VGA;
gmode=VGAHI;
initgraph(&gdriver, &gmode, "c:\\tc");
bar3d(100, 100, 300, 250, 50, 1); /*画一长方体*/
getch();
closegraph();
return 0;
}

有时编程者并不知道所用的图形显示器适配器种类, 或者需要将编写的程序
用于不同图形驱动器, Turbo C提供了一个自动检测显示器硬件的函数, 其调用
格式为:
void far detectgraph(int *gdriver, *gmode);
其中gdriver和gmode的意义与上面相同。

例5. 自动进行硬件测试后进行图形初始化
#include
int main()
{
int gdriver, gmode;
detectgraph(&gdriver, &gmode); /*自动测试硬件*/
printf("the graphics driver is %d, mode is %d\n", gdriver,
gmode); /*输出测试结果*/
getch();
initgraph(&gdriver, &gmode, "c:\\tc");
/* 根据测试结果初始化图形*/
bar3d(10, 10, 130, 250, 20, 1);
getch();
closegraph();
return 0;
}

上例程序中先对图形显示器自动检测, 然后再用图形初始化函数进行初始化
设置, 但Turbo C提供了一种更简单的方法, 即用gdriver= DETECT 语句后再跟
initgraph()函数就行了。采用这种方法后, 上例可改为:

例6.
#include
int main()
{
int gdriver=DETECT, gmode;
initgraph(&gdriver, &gmode, "c:\\tc");
bar3d(50, 50, 150, 30, 1);
getch();
closegraph();
return 0;
}
另外, Turbo C提供了退出图形状态的函数closegraph(), 其调用格式为:
void far closegraph(void);
调用该函数后可退出图形状态而进入文本方式(Turbo C 默认方式), 并释放
用于保存图形驱动程序和字体的系统内存。

2. 独立图形运行程序的建立
Turbo C对于用initgraph()函数直接进行的图形初始化程序, 在编译和链接
时并没有将相应的驱动程序(*.BGI)装入到执行程序, 当程序进行到intitgraph()
语句时, 再从该函数中第三个形式参数char *path中所规定的路径中去找相应的
驱动程序。若没有驱动程序, 则在C:\TC中去找, 如C:\TC中仍没有或TC不存在,
将会出现错误:
BGI Error: Graphics not initialized (use 'initgraph')
因此, 为了使用方便, 应该建立一个不需要驱动程序就能独立运行的可执行
图形程序,Turbo C中规定用下述步骤(这里以EGA、VGA显示器为例):
1. 在C:\TC子目录下输入命令:BGIOBJ EGAVGA
此命令将驱动程序EGAVGA.BGI转换成EGAVGA.OBJ的目标文件。
2. 在C:\TC子目录下输入命令:TLIB LIB\GRAPHICS.LIB+EGAVGA
此命令的意思是将EGAVGA.OBJ的目标模块装到GRAPHICS.LIB库文件中。
3. 在程序中initgraph()函数调用之前加上一句:
registerbgidriver(EGAVGA_driver):
该函数告诉连接程序在连接时把EGAVGA的驱动程序装入到用户的执行程序中。
经过上面处理,编译链接后的执行程序可在任何目录或其它兼容机上运行。
假设已作了前两个步骤,若再向例6中加 registerbgidriver()函数则变成:
例7:
#include
#include
int main()
{
int gdriver=DETECT,gmode;
registerbgidriver(EGAVGA_driver): / *建立独立图形运行程序 */
initgraph( gdriver, gmode,"c:\\tc");
bar3d(50,50,250,150,20,1);
getch();
closegraph();
return 0;
}
上例编译链接后产生的执行程序可独立运行。
如不初始化成EGA或CGA分辨率, 而想初始化为CGA分辨率, 则只需要将上述
步骤中有EGAVGA的地方用CGA代替即可。
iver, gmode;

 

作者:s_tiger 发表时间:2003-9-9 16:28:00


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

 第2楼

3.屏幕颜色的设置和清屏函数
对于图形模式的屏幕颜色设置, 同样分为背景色的设置和前景色的设置。在
Turbo C中分别用下面两个函数。
设置背景色: void far setbkcolor( int color);
设置作图色: void far setcolor(int color);
其中color 为图形方式下颜色的规定数值, 对EGA, VGA显示器适配器, 有关
颜色的符号常数及数值见下表所示。
表3 有关屏幕颜色的符号常数表
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
符号常数 数值 含义 符号常数 数值 含义
───────────────────────────────────
BLACK 0 黑色 DARKGRAY 8 深灰
BLUE 1 兰色 LIGHTBLUE 9 深兰
GREEN 2 绿色 LIGHTGREEN 10 淡绿
CYAN 3 青色 LIGHTCYAN 11 淡青
RED 4 红色 LIGHTRED 12 淡红
MAGENTA 5 洋红 LIGHTMAGENTA 13 淡洋红
BROWN 6 棕色 YELLOW 14 ***
LIGHTGRAY 7 淡灰 WHITE 15 白色
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
对于CGA适配器, 背景色可以为表3中16种颜色的一种, 但前景色依赖于不同
的调色板。共有四种调色板, 每种调色板上有四种颜色可供选择。不同调色板所
对应的原色见表4。
表4 CGA调色板与颜色值表
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
调色板 颜色值
─────────── ──────────────────
符号常数 数值 0 1 2 3
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
C0 0 背景 绿 红 黄
C1 1 背景 青 洋红 白
C2 2 背景 淡绿 淡红 黄
C3 3 背景 淡青 淡洋红 白
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

清除图形屏幕内容使用清屏函数, 其调用格式如下:
voide far cleardevice(void);
有关颜色设置、清屏函数的使用请看例8。
例8:
#include
#include
int main()
{
int gdriver, gmode, i;
gdriver=DETECT;
registerbgidriver(EGAVGA_DRIVER);/*建立独立图形运行程序*/
initgraph(&gdriver, &gmode", "");/*图形初始化*/
setbkcolor(0); /*设置图形背景*/
cleardevice();
for(i=0; i<=15; i++)
{
setcolor(i); /*设置不同作图色*/
circle(320, 240, 20+i*10); /*画半径不同的圆*/
delay(100); /*延迟100毫秒*/
}
for(i=0; i<=15; i++)
{
setbkcolor(i); /*设置不同背景色*/
cleardevice();
circle(320, 240, 20+i*10);
delay(100);
}
closegraph();
return 0;
}

另外, TURBO C也提供了几个获得现行颜色设置情况的函数。
int far getbkcolor(void); 返回现行背景颜色值。
int far getcolor(void); 返回现行作图颜色值。
int far getmaxcolor(void); 返回最高可用的颜色值。

4. 基本图形函数
基本图形函数包括画点, 线以及其它一些基本图形的函数。本节对这些函数
作一全面的介绍。

一、画点
1. 画点函数
void far putpixel(int x, int y, int color);
该函数表示有指定的象元画一个按color所确定颜色的点。对于颜色color的
值可从表3中获得而对x, y是指图形象元的坐标。
在图形模式下, 是按象元来定义坐标的。对VGA适配器, 它的最高分辨率为
640x480, 其中640为整个屏幕从左到右所有象元的个数, 480 为整个屏幕从上到
下所有象元的个数。屏幕的左上角坐标为(0, 0), 右下角坐标为(639, 479), 水
平方向从左到右为x轴正向, 垂直方向从上到下为y轴正向。TURBO C 的图形函数
都是相对于图形屏幕坐标, 即象元来说的。
关于点的另外一个函数是:
int far getpixel(int x, int y);
它获得当前点(x, y)的颜色值。

2. 有关坐标位置的函数

int far getmaxx(void);
返回x轴的最大值。

int far getmaxy(void);
返回y轴的最大值。

int far getx(void);
返回游标在x轴的位置。

void far gety(void);
返回游标有y轴的位置。

void far moveto(int x, int y);
移动游标到(x, y)点, 不是画点, 在移动过程中亦画点。

void far moverel(int dx, int dy);
移动游标从现行位置(x, y)移动到(x+dx, y+dy)的位置, 移动过程中不画点。

二、画线
1. 画线函数
TURBO C提供了一系列画线函数, 下面分别叙述:

void far line(int x0, int y0, int x1, int y1);
画一条从点(x0, y0)到(x1, y1)的直线。

void far lineto(int x, int y);
画一作从现行游标到点(x, y)的直线。

void far linerel(int dx, int dy);
画一条从现行游标(x, y)到按相对增量确定的点(x+dx, y+dy)的直线。

void far circle(int x, int y, int radius);
以(x, y)为圆心, radius为半径, 画一个圆。

void far arc(int x, int y, int stangle, int endangle, int radius);
以(x, y)为圆心, radius为半径, 从stangle开始到endangle结束(用度表示)
画一段圆弧线。在TURBO C中规定x轴正向为0度, 逆时针方向旋转一周, 依次为
90, 180, 270和360度(其它有关函数也按此规定, 不再重述)。

void ellipse(int x, int y, int stangle, int endangle, int xradius,
int yradius);
以(x, y)为中心, xradius, yradius为x轴和y轴半径, 从角stangle 开始到
endangle结束画一段椭圆线, 当stangle=0, endangle=360时, 画出一个完整的
椭圆。

void far rectangle(int x1, int y1, int x2, inty2);
以(x1, y1)为左上角, (x2, y2)为右下角画一个矩形框。

void far drawpoly(int numpoints, int far *polypoints);
画一个顶点数为numpoints, 各顶点坐标由polypoints 给出的多边形。
polypoints整型数组必须至少有2倍顶点数个无素。每一个顶点的坐标都定义为x,
y, 并且x在前。值得注意的是当画一个封闭的多边形时, numpoints 的值取实际
多边形的顶点数加一, 并且数组polypoints中第一个和最后一个点的坐标相同。
下面举一个用drawpoly()函数画箭头的例子。
例9:
#include
#include
int main()
{
int gdriver, gmode, i;
int arw[16]={200, 102, 300, 102, 300, 107, 330,
100, 300, 93, 300, 98, 200, 98, 200, 102};
gdriver=DETECT;
registerbgidriver(EGAVGA_driver);
initgraph(&gdriver, &gmode, "");
setbkcolor(BLUE);
cleardevice();
setcolor(12); /*设置作图颜色*/
drawpoly(8, arw); /*画一箭头*/
getch();
closegraph();
return 0;
}

2. 设定线型函数
在没有对线的特性进行设定之前, TURBO C用其默认值, 即一点宽的实线,
但TURBO C也提供了可以改变线型的函数。线型包括:宽度和形状。其中宽度只有
两种选择: 一点宽和三点宽。而线的形状则有五种。下面介绍有关线型的设置函
数。

void far setlinestyle(int linestyle, unsigned upattern, int
thickness);
该函数用来设置线的有关信息, 其中linestyle是线形状的规定, 见表5。
表5. 有关线的形状(linestyle)
━━━━━━━━━━━━━━━━━━━━━━━━━
符号常数 数值 含义
─────────────────────────
SOLID_LINE 0 实线
DOTTED_LINE 1 点线
CENTER_LINE 2 中心线
DASHED_LINE 3 点画线
USERBIT_LINE 4 用户定义线
━━━━━━━━━━━━━━━━━━━━━━━━━
thickness是线的宽度, 见表6。

表6. 有关线宽(thickness)
━━━━━━━━━━━━━━━━━━━━━━━━━
符号常数 数值 含义
─────────────────────────
NORM_WIDTH 1 一点宽
THIC_WIDTH 3 三点宽
━━━━━━━━━━━━━━━━━━━━━━━━━
对于upattern, 只有linestyle选USERBIT_LINE 时才有意义( 选其它线型,
uppattern取0即可)。此进uppattern的16位二进制数的每一位代表一个象元, 如
果那位为1, 则该象元打开, 否则该象元关闭。

void far getlinesettings(struct linesettingstype far *lineinfo);
该函数将有关线的信息存放到由lineinfo 指向的结构中, 表中
linesettingstype的结构如下:
struct linesettingstype{
int linestyle;
unsigned upattern;
int thickness;
}
例如下面两句程序可以读出当前线的特性
struct linesettingstype *info;
getlinesettings(info);

void far setwritemode(int mode);
该函数规定画线的方式。如果mode=0, 则表示画线时将所画位置的原来信息
覆盖了(这是TURBO C的默认方式)。如果mode=1, 则表示画线时用现在特性的线
与所画之处原有的线进行异或(XOR)操作, 实际上画出的线是原有线与现在规定
的线进行异或后的结果。因此, 当线的特性不变, 进行两次画线操作相当于没有
画线。
有关线型设定和画线函数的例子如下所示。
例10.
#include
#include
int main()
{
int gdriver, gmode, i;
gdriver=DETECT;
registerbgidriver(EGAVGA_driver);
initgraph(&gdriver, &gmode, "");
setbkcolor(BLUE);
cleardevice();
setcolor(GREEN);
circle(320, 240, 98);
setlinestyle(0, 0, 3); /*设置三点宽实线*/
setcolor(2);
rectangle(220, 140, 420, 340);
setcolor(WHITE);
setlinestyle(4, 0xaaaa, 1); /*设置一点宽用户定义线*/
line(220, 240, 420, 240);
line(320, 140, 320, 340);
getch();
closegraph();
return 0;
}

5. 封闭图形的填充
填充就是用规定的颜色和图模填满一个封闭图形。

一、先画轮廓再填充
TURBO C提供了一些先画出基本图形轮廓, 再按规定图模和颜色填充整个封
闭图形的函数。在没有改变填充方式时, TURBO C以默认方式填充。 下面介绍这
些函数。

void far bar(int x1, int y1, int x2, int y2);
确定一个以(x1, y1)为左上角, (x2, y2)为右下角的矩形窗口, 再按规定图
模和颜色填充。
说明: 此函数不画出边框, 所以填充色为边框。

void far bar3d(int x1, int y1, int x2, int y2, int depth, int
topflag);
当topflag为非0时, 画出一个三维的长方体。当topflag为0时, 三维图形不
封顶, 实际上很少这样使用。
说明: bar3d()函数中, 长方体第三维的方向不随任何参数而变, 即始终为
45度的方向。

void far pieslice(int x, int y, int stangle, int endangle, int
radius);
画一个以(x, y)为圆心, radius为半径, stangle为起始角度, endangle 为
终止角度的扇形, 再按规定方式填充。当stangle=0, endangle=360 时变成一个
实心圆, 并在圆内从圆点沿X轴正向画一条半径。

void far sector(int x, int y, int stanle, intendangle, int
xradius, int yradius);
画一个以(x, y)为圆心分别以xradius, yradius为x轴和y轴半径, stangle
为起始角, endangle为终止角的椭圆扇形, 再按规定方式填充。

二、设定填充方式
TURBO C有四个与填充方式有关的函数。下面分别介绍:

void far setfillstyle(int pattern, int color);
color的值是当前屏幕图形模式时颜色的有效值。pattern的值及与其等价的
符号常数如表7所示。
表7. 关于填充式样pattern的规定
━━━━━━━━━━━━━━━━━━━━━━━━━━━
符号常数 数值 含义
───────────────────────────
EMPTY_FILL 0 以背景颜色填充
SOLID_FILL 1 以实填充
LINE_FILL 2 以直线填充
LTSLASH_FILL 3 以斜线填充(阴影线)
SLASH_FILL 4 以粗斜线填充(粗阴影线)
BKSLASH_FILL 5 以粗反斜线填充(粗阴影线)
LTBKSLASH_FILL 6 以反斜线填充(阴影线)
HATCH_FILL 7 以直方网格填充
XHATCH_FILL 8 以斜网格填充
INTTERLEAVE_FILL 9 以间隔点填充
WIDE_DOT_FILL 10 以稀疏点填充
CLOSE_DOS_FILL 11 以密集点填充
USER_FILL 12 以用户定义式样填充
━━━━━━━━━━━━━━━━━━━━━━━━━━━━

除USER_FILL(用户定义填充式样)以外, 其它填充式样均可由setfillstyle()
函数设置。当选用USER_FILL时, 该函数对填充图模和颜色不作任何改变。 之所
以定义USER_FILL主要因为在获得有关填充信息时用到此项。
void far setfillpattern(char * upattern,int color);
设置用户定义的填充图模的颜色以供对封闭图形填充。
其中upattern是一个指向8个字节的指针。这8个字节定义了8x8点阵的图形。
每个字节的8位二进制数表示水平8点, 8个字节表示8行, 然后以此为模型向个封
闭区域填充。
void far getfillpattern(char * upattern);
该函数将用户定义的填充图模存入upattern指针指向的内存区域。
void far getfillsetings(struct fillsettingstype far * fillinfo);
获得现行图模的颜色并将存入结构指针变量fillinfo中。其中fillsettingstype
结构定义如下:
struct fillsettingstype{
int pattern; /* 现行填充模式 * /
int color; /* 现行填充模式 * /
};
有关图形填充图模的颜色的选择, 请看下面例程。
例11:
#include
main(){
char str[8]={10,20,30,40,50,60,70,80}; /*用户定义图模*/
int gdriver,gmode,i;
struct fillsettingstype save; /*定义一个用来存储填充信息的结构变量*/
gdriver=DETECT;
initgraph(&gdriver,&gmode,"c:\\tc");
setbkcolor(BLUE);
cleardevice();
for(i=0;i<13;i++)
{
setcolor(i+3);
setfillstyle(i,2+i); /* 设置填充类型 *
bar(100,150,200,50); /*画矩形并填充*/
bar3d(300,100,500,200,70,1); /* 画长方体并填充*/
pieslice(200, 300, 90, 180, 90);/*画扇形并填充*/
sector(500,300,180,270,200,100);/*画椭圆扇形并填充*/
delay(1000); /*延时1秒*/
}
cleardevice();
setcolor(14);
setfillpattern(str, RED);
bar(100,150,200,50);
bar3d(300,100,500,200,70,0);
pieslice(200,300,0,360,90);
sector(500,300,0,360,100,50);
getch();
getfillsettings(&save); /*获得用户定义的填充模式信息*/
closegraph();
clrscr();
printf("The pattern is %d, The color of filling is %d",
save.pattern, save.color); /*输出目前填充图模和颜色值*/
getch();
}
以上程序运行结束后, 在屏幕上显示出现行填充图模和颜色的常数值。

三、任意封闭图形的填充
截止目前为止, 我们只能对一些特定形状的封闭图形进行填充, 但还不能对
任意封闭图形进行填充。为此, TURBO C 提供了一个可对任意封闭图形填充的函
数, 其调用格式如下:
void far floodfill(int x, int y, int border);
其中: x, y为封闭图形内的任意一点。border为边界的颜色, 也就是封闭图
形轮廓的颜色。调用了该函数后, 将用规定的颜色和图模填满整个封闭图形。
注意:
1. 如果x或y取在边界上, 则不进行填充。
2. 如果不是封闭图形则填充会从没有封闭的地方溢出去, 填满其它地方。
3. 如果x或y在图形外面, 则填充封闭图形外的屏幕区域。
4. 由border指定的颜色值必须与图形轮廓的颜色值相同, 但填充色可选任
意颜色。下例是有关floodfill()函数的用法, 该程序填充了bar3d()所画长方体
中其它两个未填充的面。
例12:
#include
#include
main()
{
int gdriver, gmode;
strct fillsettingstype save;
gdriver=DETECT;
initgraph(&gdriver, &gmode, "");
setbkcolor(BLUE);
cleardevice();
setcolor(LIGHTRED);
setlinestyle(0,0,3);
setfillstyle(1,14); /*设置填充方式*/
bar3d(100,200,400,350,200,1); /*画长方体并填充*/
floodfill(450,300,LIGHTRED); /*填充长方体另外两个面*/
floodfill(250,150, LIGHTRED);
rectanle(450,400,500,450); /*画一矩形*/
floodfill(470,420, LIGHTRED); /*填充矩形*/
getch();
closegraph();
}

6. 有关图形窗口和图形屏幕操作函数

一、图形窗口操作
象文本方式下可以设定屏幕窗口一样, 图形方式下也可以在屏幕上某一区域
设定窗口, 只是设定的为图形窗口而已, 其后的有关图形操作都将以这个窗口的
左上角(0,0)作为坐标原点, 而且可为通过设置使窗口之外的区域为不可接触。
这样, 所有的图形操作就被限定在窗口内进行。
void far setviewport(int xl,int yl,int x2, int y2,int clipflag);
设定一个以(xl,yl)象元点为左上角, (x2,y2)象元为右下角的图形窗口, 其
中x1,y1,x2,y2是相对于整个屏幕的坐标。若clipflag为非0, 则设定的图形以外
部分不可接触, 若clipflag为0, 则图形窗口以外可以接触。
void far clearviewport(void);
清除现行图形窗口的内容。
void far getviewsettings(struct viewporttype far * viewport);
获得关于现行窗口的信息,并将其存于viewporttype定义的结构变量viewport
中, 其中viewporttype的结构说明如下:
struct viewporttype{
int left, top, right, bottom;
int cliplag;
&nb

2008年10月29日星期三

VC小知识

网上看到的VC的相关的东西。
http://liubin.itpub.net/post/325/21104
VC小知识
作者 liubin 14:00 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | C++

(1) 如何通过代码获得应用程序主窗口的 指针?
主窗口的 指针保存在CWinThread::m_pMainWnd中,调用AfxGetMainWnd实现。
AfxGetMainWnd() ->ShowWindow(SW_SHOWMAXMIZED)
//使程序最大化.

(2) 确定应用程序的路径
Use GetModuleFileName 获得应用程序的路径,然后去掉可执行文件名。
Example:
TCHAR
exeFullPath[MAX_PATH] // MAX_PATH在API中定义了吧,好象是
128
GetModuleFileName(NULL,exeFullPath,MAX_PATH)


(3) 如何在程序中获得其他程序的 图标?
两种方法:
(1) SDK函数 SHGetFileInfo 或使用 ExtractIcon获得图标资源的 handle,
(2) SDK函数 SHGetFileInfo 获得有关文件的很多信息,如大小图标,属性, 类型等.
Example(1):
在程序窗口左上角显示 NotePad图标.
void CSampleView:
OnDraw(CDC * pDC)
{
if( :: SHGetFileInfo(_T("c:pwin95 otepad.exe"),0,
&stFileInfo,sizeof(stFileInfo),SHGFI_ICON))
{
pDC ->DrawIcon(10,10,stFileInfo.hIcon)
}
}
Example(2):同样功能,Use ExtractIcon Function
void CSampleView:: OnDraw(CDC *pDC)
{
HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T
("NotePad.exe"),0)
if (hIcon &&hIcon!=(HICON)-1)
pDC->DrawIcon(10,10,hIcon)
}
说明: 获得notepad.exe的路径正规上来说用GetWindowsDirectory函数得到, 如果是调用 win95下的画笔,应该用访问注册表的方法获得其路径,要作成一个比较考究的程序,考虑应该全面点.

(4) 获得各种目录信息
Windows目录: Use "GetWindowsDirectory"
Windows下的system目录: Use "GetSystemDirectory"
temp目录: Use "GetTempPath"
当前目录: Use "GetCurrentDirectory"

请注意前两个函数的第一个参数为目录变量名,后一个为缓冲区后两个相反.


(5) 如何自定义消息
1) 手工定义消息,可以这么写
#define WM_MY_MESSAGE(WM_USER+100),
MS 推荐的至少是 WM_USER+100

(2)写消息处理函数,用
WPARAM,LPARAM返回LRESULT.
LRESULT CMainFrame::OnMyMessage(WPARAM wparam,LPARAM lParam)

{
temp目录: Use "GetTempPath"
//加入你的处理函数 irectory"
}

(6) 如何改变窗口的图标?
向窗口发送 WM_SECTION消息。
Example:
HICON hIcon=AfxGetApp() ->LoadIcon(IDI_ICON)
ASSERT(hIcon)
AfxGetMainWnd() ->SendMessage(WM_SECTION,TRUE,(LPARAM)hIcon)


(7) 如何改变窗口的缺省风格?
重载 CWnd:: PreCreateWindow 并修改CREATESTRUCT结构来指定窗口风格和其他创建信息.
Example: Delete "Max" Button and Set Original
Window's Position and Size

BOOL CMainFrame:: PreCreateWindow
(CREATESTRUCT &cs)
{
cs.style &=~WS_MAXINIZEMOX

cs.x=cs.y=0
cs.cx=GetSystemMetrics(SM_CXSCREEN/2)
cs.cy=GetSystemMetrics(SM_CYSCREEN/2)

return CMDIFramewnd ::PreCreateWindow(cs)
}
(8) 如何将窗口居中显示?
Call Function CWnd::
Center Windows

Example(1):
Center Window( ) //Relative to it's parent
// Relative
to Screen
Example(2):
Center Window(CWnd:: GetDesktopWindow( ))
//Relative to
Application's MainWindow
AfxGetMainWnd( ) ->
Center Window( )


(9) 如何让窗口和 MDI窗口一启动就最大化和最小化?
先说窗口。
在 InitStance 函数中设定 m_nCmdShow的取值.
m_nCmdShow=SW_SHOWMAXMIZED //最大化
m_nCmdShow=SW_SHOWMINMIZED //最小化
m_nCmdShow=SW_SHOWNORMAL //正常方式

MDI窗口:
如果是创建新的应用程序,可以用MFC AppWizard 的Advanced 按钮并在MDI子窗口风格组中检测最大化或最小化还可以重载 MDI Window 的PreCreateWindow函数,设置WS_MAXMIZE or WS_MINMIZE

如果从 CMDIChildWnd派生,调用 OnInitialUpdate函数中的 CWnd::Show Window来指定 MDI Child Window的风格。
(10) 如何限制窗口的大小?
也就是 FixedDialog形式。 Windows发送 WM_GETMAXMININFO消息来跟踪, 响应它,在 OnGetMAXMININFO 中写代码:

(11) 如何使窗口不可见?
很简单,用SW_HIDE 隐藏窗口,可以结合 FindWindow,ShowWindow控制.

(12) 如何创建一个字回绕的CEditView
重载CWnd : : PreCreateWindow和修改CREATESTRUCT结构,关闭CEditView对象的ES_AUTOHSCROLL和WS_HSCROLL 风格位, 由于CEditView : : PreCreateWindow显示设置cs. style,调用基类函数后要修改cs . style。

BOOL CSampleEDitView : : PreCreateWindow (CREATESTRUCT&cs)
{
//First call basse class function .
BOOL bResutl =CEditView : : PreCreateWindow (cs)

// Now specify the new window style .
cs.style &= ~ (ES_AUTOHSCROLL |WS_HSCROLL)
return bResult
}

(13) 如何使程序保持极小状态?
这么办: 在恢复程序窗体大小时,Windows会发送WM_QUERY-OPEN消息,用 ClassWizard设置成员函数
OnQueryOpen() ,add following code:

Bool CMainFrame:: OnQueryOpen( )
{
Return false
}

(14) 移动窗口
调用CWnd : : SetWindowPos并指定SWP_NOSIZE标志。目的位置与父窗口有关(顶层窗口与屏幕有关)。调用CWnd : : MoveWindow时必须要指定窗口的大小。
//Move window to positoin 100 , 100 of its parent window .
SetWindowPos (NULL, 100 , 100 , 0 , 0 , SWP_NOSIZE |SWP_NOAORDER)

(15) 通用控件的显示窗口
MFC 提供了几个CView派生的视窗类,封装了通用控件的功能,但仍然使用工作框文档显示窗口体系结构:CEditView封装了编辑控件,CTreeView保持了树列表控件,CListView封装了列表显示窗口控件,CRichEditView可以处理多种编辑控件。

(16) 重置窗口的大小
调用CWnd: : SetWindowPos并指定SWP_NOMOVE标志, 也可调用CWnd : : MoveWindow 但必须指定窗口的位置。
// Get the size of the window .
Crect reWindow
GetWindowRect (reWindow )

//Make the window twice as wide and twice as tall .
SetWindowPos (NULL , 0 , 0 , reWindow . Width ( ) *2,

reWindow . Height () * 2,
SWP_NOMOVE |SWP_NOZORDER )

(17) 如何单击除了窗口标题栏以外的区域使窗口移动
当窗口需要确定鼠标位置时Windows向窗口发送WM_NCHITTEST信息,可以处理该信息使Windows认为鼠标在窗口标题上。对于对话框和基于对话的应用程序,可以使用ClassWizard处理该信息并调用基类函数, 如果函数返回HTCLIENT 则表明鼠标在客房区域,返回HTCAPTION表明鼠标在Windows的标题栏中。
UINT CSampleDialog : : OnNcHitTest (Cpoint point )
{
UINT nHitTest =Cdialog: : OnNcHitTest (point )
return (nHitTest = =HTCLIENT)? HTCAPTION : nHitTest
}

上述技术有两点不利之处,
其一是在窗口的客户区域双击时,窗口将极大;
其二, 它不适合包含几个视窗的主框窗口。
还有一种方法,当用户按下鼠标左键使主框窗口认为鼠标在其窗口标题上,使用ClassWizard在视窗中处理WM_LBUTTODOWN信息并向主框窗口发送一个WM_NCLBUTTONDOWN信息和一个单击测试HTCAPTION。
void CSampleView : : OnLButtonDown (UINT nFlags , Cpoint point
)
{
CView : : OnLButtonDow (nFlags , pont )

//Fool frame window into thinking somene clicked
on
its caption bar .
GetParentFrame ( ) —> PostMessage (
WM_NCLBUTTONDOWN ,
HTCAPTION , MAKELPARAM (poitn .x , point .y) )

}
该技术也适用于对话框和基于对的应用程序,只是不必调用
CWnd: :GetParentFrame 。
void CSampleDialog : : OnLbuttonDown (UINT nFlags, Cpoint point )
{
Cdialog : : OnLButtonDow (nFlags, goint )
//Fool dialog into thinking simeone clicked on its
caption bar .
PostMessage (WM_NCLBUTTONDOWN , HTCAPTION , MAKELPARM (point.x
, point. y
) )
}

(18) 如何改变视窗的背景颜色
Windows向窗口发送一个WM_ERASEBKGND消息通知该窗口擦除背景,可以使用ClassWizard重载该消息的缺省处理程序来擦除背景(实际是画),并返回TRUE以防止Windows擦除窗口。
//Paint area that needs to be erased.
BOOL CSampleView : : OnEraseBkgnd (CDC* pDC)
{
// Create a pruple brush.
CBrush Brush (RGB (128 , 0 , 128) )

// Select the brush into the device context .
CBrush* pOldBrush = pDC—>SelcetObject (&brush)

// Get the area that needs to be erased .
CRect reClip
pDC—>GetCilpBox (&rcClip)
//Paint the area.
pDC—> PatBlt (rcClip.left , rcClip.top , rcClip.Width ( ) , rcClip.Height( ) , PATCOPY )

//Unselect brush out of device context .
pDC—>SelectObject (pOldBrush )

// Return nonzero to half fruther processing .
return TRUE
}

(19) 如何改变窗口标题
调用CWnd : : SetWindowText可以改变任何窗口(包括控件)的标题。
//Set title for application's main frame window .
AfxGetMainWnd ( ) —> SetWindowText (_T("Application title") )

//Set title for View's MDI child frame window .
GetParentFrame ( ) —> SetWindowText ("_T ("MDI Child Frame new title")
)

//Set title for dialog's push button control.
GetDigitem (IDC_BUTTON) —> SetWindowText (_T ("Button new title ") )
如果需要经常修改窗口的标题(注:控件也是窗口),应该考虑使用半文档化的函数AfxSetWindowText。该函数在AFXPRIV.H中说明,在 WINUTIL.CPP中实现,在联机帮助中找不到它,它在AFXPRIV.H中半文档化, 在以后发行的MFC中将文档化。
AfxSetWindowText的实现如下:
voik AFXAPI AfxSetWindowText (HWND hWndCtrl , LPCTSTR IpszNew )
{
itn nNewLen= Istrlen (Ipaznew)
TCHAR szOld [256]
//fast check to see if text really changes (reduces
flash in the
controls )
if (nNewLen >_contof (szOld)
|| : : GetWindowText (hWndCrtl, szOld , _countof (szOld) !=nNewLen
|| Istrcmp (szOld , IpszNew)! = 0
{
//change it
: : SetWindowText(hWndCtrl , IpszNew )
}
}

(20) 如何防止主框窗口在其说明中显示活动的文档名
创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置
CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。
BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs)
{
//Turn off FWS_ADDTOTITLE in main frame .
cs.styel & = ~FWS_ADDTOTITLE  
return CMDIFrameWnd : : PreCreateWindow (cs )
}
关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。

(21) 如何获取有关窗口正在处理的当前消息的信息
调用CWnd: : GetCurrentMessage可以获取一个MSG指针。例如,可以使用ClassWizard将几个菜单项处理程序映射到一个函数中,然后调用GetCurrentMessage来确定所选中的菜单项。
viod CMainFrame : : OnCommmonMenuHandler ( )
{
//Display selected menu item in debug window .
TRACE ("Menu item %u was selected . n" ,

(22) 如何在代码中获取工具条和状态条的指针
缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个 AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针:
//Get pointer to status bar .
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR)

//Get pointer to toolbar .
CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )
—> GetDescendantWindow(AFX_IDW_TOOLBAR)

(23) 如何使能和禁止工具条的工具提示
如果设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用 CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数:
void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )
{
ASSERT_VALID (m_wndToolBar)

DWORD dwStyle = m _wndToolBar.GetBarStyle ( )

if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS

else
dwStyle & = ~CBRS_TOOLTIPS

m_wndToolBar.SetBarStyle (dwStyle )
}

(24) 如何创建一个不规则形状的窗口
可以使用新的SDK函数SetWindowRgn。该函数将绘画和鼠标消息限定在窗口的一个指定的区域,实际上使窗口成为指定的不规则形状。 使用AppWizard创建一个基于对的应用程序并使用资源编辑器从主对话资源中删除所在的缺省控件、标题以及边界。
给对话类增加一个CRgn数据成员,以后要使用该数据成员建立窗口区域。
Class CRoundDlg : public CDialog
{

private :
Crgn m_rgn : // window region

}
修改OnInitDialog函数建立一个椭圆区域并调用SetWindowRgn将该区域分配给窗口:
BOOL CRoundDlg : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )

//Get size of dialog .
CRect rcDialog
GetClientRect (rcDialog )

// Create region and assign to window .
m_rgn . CreateEllipticRgn (0 , 0 , rcDialog.Width( ) , rcDialog.Height ( ) )
SetWindowRgn (GetSafeHwnd ( ) , (HRGN) m_ rgn ,TRUE )

return TRUE
}

通过建立区域和调用SetWindowRgn,已经建立一个不规则形状的窗口,下面的例子程序是修改OnPaint函数使窗口形状看起来象一个球形体。
voik CRoundDlg : : OnPaint ( )
{
CPaintDC de (this) // device context for painting
.
//draw ellipse with out any border
dc. SelecStockObject (NULL_PEN)
//get the RGB colour components of the sphere color
COLORREF color= RGB( 0 , 0 , 255)
BYTE byRed =GetRValue (color)
BYTE byGreen = GetGValue (color)
BYTE byBlue = GetBValue (color)

// get the size of the view window
Crect rect
GetClientRect (rect)

// get minimun number of units
int nUnits =min (rect.right , rect.bottom )

//calculate he horiaontal and vertical step size
float fltStepHorz = (float) rect.right /nUnits
float fltStepVert = (float) rect.bottom /nUnits


int nEllipse = nUnits/3 // calculate how many to
draw
int nIndex
// current ellipse that is being draw

CBrush brush
// bursh used for ellipse fill color
CBrush *pBrushOld // previous
brush that was selected into dc
//draw ellipse , gradually moving towards upper-right
corner
for (nIndex = 0 nIndes < + nEllipse nIndes++)
{
//creat solid brush
brush . CreatSolidBrush (RGB ( ( (nIndex*byRed ) /nEllipse ).
( ( nIndex * byGreen ) /nEllipse ), ( (nIndex * byBlue)
/nEllipse ) ) )

//select brush into dc
pBrushOld= dc .SelectObject (&brhsh)

//draw ellipse
dc .Ellipse ( (int) fltStepHorz * 2, (int) fltStepVert * nIndex ,
rect. right -( (int) fltStepHorz * nIndex )+ 1,
rect . bottom -( (int) fltStepVert * (nIndex *2) ) +1)

//delete the brush
brush.DelecteObject ( )
}
}

最后,处理WM_NCHITTEST消息,使当击打窗口的任何位置时能移动窗口。
UINT CRoundDlg : : OnNchitTest (Cpoint point )
{
//Let user move window by clickign anywhere on thewindow .
UINT nHitTest = CDialog : : OnNcHitTest (point)
rerurn (nHitTest = = HTCLIENT)? HTCAPTION: nHitTest

}

(25) 如何获取应用程序的 实例句柄?
应用程序的实例句柄保存在CWinApp m_hInstance 中,可以这么调用AfxGetInstancdHandle获得句柄.
Example: HANDLE hInstance=AfxGetInstanceHandle()

(26) 如何编程结束应用程序?
这是个很简单又是编程中经常要遇到的问题.
向窗口发送 WM_CLOSE消息,调用 CWnd::OnClose成员函数.允许对用户提示是否保存修改过的数据.
Example: AfxGetMainWindow()->SendMessage(WM_CLOSE)

还可以创建一个自定义的函数 Terminate Window
void Terminate Window(LPCSTR pCaption)
{
CWnd *pWnd=Cwnd::FindWindow(NULL,pCaption)

if (pWnd)

pWnd ->SendMessage(WM_CLOSE)
}

说明: FindWindow函数不是提倡的做法,因为它无法处理标题栏自动改变,比如我们要检测 Notepad是不是已运行而事先不知道Notepad的标题栏,这时FindWindow就无能为力了,可以通过枚举 windows任务列表的办法来实现。在机械出版社"Windows 95 API开发人员指南"一书有比较详细的介绍,这里就不再多说乐。

(27) 如何创建和使用无模式对话框
MFC 将模式和无模式对话封装在同一个类中,但是使用无模式对话需要几个对话需要几个额处的步骤。首先,使用资源编辑器建立对话资源并使用 ClassWizard创建一个CDialog的派生类。模式和无模式对话的中止是不一样的:模式对话通过调用CDialog : : EndDialog 来中止,无模式对话则是调用CWnd: : DestroyWindow来中止的,函数CDialog : : OnOK和CDialog : : OnCancel调用EndDialog ,所以需要调用DestroyWindow并重置无模式对话的函数。
void CSampleDialog : : OnOK ( )
{
// Retrieve and validate dialog data .
if (! UpdateData (TRUE) )
{
// the UpdateData rountine
will set focus to correct item TRACEO (" UpdateData failed during dialog termination .n")
return
}

//Call DestroyWindow instead of EndDialog .
DestroyWindow ( )
}

void CSampleDialog : : OnCancel ( )
{
//Call DestroyWindow instead of EndDialog .
DestroyWindow ( )
}

其次,需要正确删除表示对话的C++对象。对于模式对来说,这很容易,需要创建函数返回后即可删除C++对象;无模式对话不是同步的,创建函数调用后立即返回,因而用户不知道何时删除C++对象。撤销窗口时工作框调用CWnd : : PostNcDestroy,可以重置该函数并执行清除操作,诸如删除this指针。
void CSampleDialog : : PostNcDestroy ( )
{
// Declete the C++ object that represents this dialog.
delete this

最后,要创建无模式对话。可以调用CDialog : : DoModal创建一个模式对放,要创建一个无模式对话则要调用CDialog: : Create。下面的例子说明 了应用程序是如何创建无模式对话的: 象;无模式对话不是同步的,创建函数调用后立即返回,
void CMainFrame : : OnSampleDialog ( )
{
//Allocate a modeless dialog object .
CSampleDilog * pDialog =new CSampleDialog
ASSERT_VALID (pDialog) Destroy ( )

//Create the modeless dialog . represents this dialog.
BOOL bResult = pDialog —> Creste (IDD_IDALOG)
ASSERT (bResult )
}

(28) 如何防止主框窗口在其说明中显示活动的文档名
创建主框窗口和MDI子窗口进通常具有FWS_ADDTOTITLE风格位,如果不希望在说明中自动添加文档名, 必须禁止该风格位, 可以使用ClassWizard重置
CWnd: : PreCreateWindow并关闭FWS_ADDTOTITLE风格。
BOOL CMainFrame : : PreCreateWindow (CREATESTRUCT&cs)
{
//Turn off FWS_ADDTOTITLE in main frame .
cs.styel & = ~FWS_ADDTOTITLE  
return CMDIFrameWnd : : PreCreateWindow (cs )
}
关闭MDI子窗口的FWS _ADDTOTITLE风格将创建一个具有空标题的窗口,可以调用CWnd: : SetWindowText来设置标题。记住自己设置标题时要遵循接口风格指南。

(29) 如何在代码中获取工具条和状态条的指针
缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个 AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针:
//Get pointer to status bar .
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR)

//Get pointer to toolbar .
CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )
—> GetDescendantWindow(AFX_IDW_TOOLBAR)


(30) 怎样加载其他的应用程序?
三个SDK函数 winexec, shellexecute,createprocess可以使用。
WinExec最简单,两个参数,前一个指定路径,后一个指定显示方式.后一个参数值得说一下,比如泥用 SW_SHOWMAXMIZED方式去加载一个无最大化按钮的程序,就是Neterm,calc等等,就不会出现正常的窗体,但是已经被加到任务列表里了。

ShellExecute 较 WinExex灵活一点,可以指定工作目录,下面的Example就是直接打开 c:temp1.txt,而不用加载与 txt文件关联的应用程序,很多安装程序完成后都会打开一个窗口,来显示Readme or Faq,我猜就是这么作的啦.

ShellExecute(NULL,NULL,_T("1.txt"),NULL,_T("c: emp"),SW_SHOWMAXMIZED)

CreateProcess最复杂,一共有十个参数,不过大部分都可以用NULL代替,它可以指定进程的安全属性,继承信息,类的优先级等等.来看个很简单的Example:
STARTUPINFO stinfo
//启动窗口的信息
PROCESSINFO procinfo //进程的信息

CreateProcess(NULL,_T("notepad.exe"),NULL,NULL.FALSE,
NORMAL_PRIORITY_

CLASS,NULL,NULL, &stinfo,&procinfo)

(31) 如何在代码中获取工具条和状态条的指针
缺省时,工作框创建状态条和工具条时将它们作为主框窗口的子窗口,状态条有一个AFX_IDW_STATUS_BAR标识符,工具条有一个 AFX_IDW_TOOLBAR标识符,下例说明了如何通过一起调用CWnd: : GetDescendantWindow和AfxGetMainWnd来获取这些子窗口的指针:
//Get pointer to status bar .
CStatusBar * pStatusBar = (CStatusBar *) AfxGetMainWnd ( )
—> GetDescendantWindow(AFX_IDW_STUTUS_BAR)

(32) 如何使能和禁止工具条的工具提示
如果设置了CBRS_TOOLTIPS风格位,工具条将显示工具提示,要使能或者禁止工具提示,需要设置或者清除该风格位。下例通过调用 CControlBar : : GetBarStyle和CControlBar : : SetBarStyle建立一个完成此功能的成员函数:
void CMainFrame : : EnableToolTips ( BOOL bDisplayTips )
{
ASSERT_VALID (m_wndToolBar)

DWORD dwStyle = m _wndToolBar.GetBarStyle ( )

if (bDisplayTips) dwStyle |=CBRS_TOOLTIPS

else
dwStyle & = ~CBRS_TOOLTIPS

m_wndToolBar.SetBarStyle (dwStyle )
}

//Get pointer to toolbar .
CToolBar * pToolBar = (CToolBar * ) AfxGetMainWnd ( )
—> GetDescendantWindow(AFX_IDW_TOOLBAR)

(33) 如何设置工具条标题
工具条是一个窗口,所以可以在调用CWnd : : SetWindowText来设置标题,例子如下:
int CMainFrame : : OnCreate (LPCREATESTRUCT lpCreateStruct )
{

// Set the caption of the toolbar .
m_wndToolBar.SetWindowText (_T "Standdard")

(34) 如何使窗口始终在最前方?
BringWindowToTop(Handle)
SetWindowPos函数,指定窗口的 最顶风格,用WS_EX_TOPMOST扩展窗口的风格

Example:
void ToggleTopMost(
CWnd *pWnd)
{
ASSERT_VALID(pWnd)

pWnd ->SetWindowPos(pWnd-> GetStyle( ) &WS_EX_TOPMOST)?

&wndNoTopMOST: &wndTopMost,0,0,0,0,SSP_NOSIZE|WSP_NOMOVE)
}

(35) 如何在对话框中显示一个位图
这要归功于Win 32先进的静态控件和Microsoft的资源编辑器,在对话框中显示位图是很容易的, 只需将图形控件拖到对话中并选择适当属性即可,用户也可以显示图标、位图以及增强型元文件。

(36) 如何改变对话或窗体视窗的背景颜色
调用CWinApp : : SetDialogBkColor可以改变所有应用程序的背景颜色。第一个参数指定了背景颜色,第二个参数指定了文本颜色。下例将应用程序对话设置为蓝色背景和黄色文本。
BOOL CSampleApp : : InitInstance ( )
{


//use blue dialog with yellow text .
SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 ,255 , 0 ) )


}

需要重画对话(或对话的子控件)时,Windows向对话发送消息WM_CTLCOLOR,通常用户可以让Windows选择绘画背景的刷子,也可重置该消息指定刷子。下例说明了创建一个红色背景对话的步骤。

首先,给对话基类增加一人成员变量
CBursh :class CMyFormView : public CFormView
{


private :
CBrush m_ brush // background brush


}

其次, 在类的构造函数中将刷子初始化为所需要的背景颜色。
CMyFormView : : CMyFormView ( )
{
// Initialize background brush .
m_brush .CreateSolidBrush (RGB ( 0, 0, 255) )
}

最后,使用ClassWizard处理WM_CTLCOLOR消息并返回一个用来绘画对话背景的刷子句柄。注意:由于当重画对话控件时也要调用该函数,所以要检测nCtlColor参量。
HBRUSH CMyFormView : : OnCtlColor (CDC* pDC , CWnd*pWnd , UINT nCtlColor
)

{
// Determine if drawing a dialog box . If we are, return +handle to
//our own background brush . Otherwise let windows handle it .
if (nCtlColor = = CTLCOLOR _ DLG )
return (HBRUSH) m_brush.GetSafeHandle ( )
return CFormView : : OnCtlColor (pDC, pWnd , nCtlColor
)
}

(37) 如何获取一个对话控件的指针
有两种方法。其一,调用CWnd: : GetDlgItem,获取一个CWnd*指针调用成员函数。下例调用GetDlgItem,将返回值传给一个CSpinButtonCtrl*以便调用CSpinButtonCtrl : : SetPos 函数:
BOOL CSampleDialog : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )

//Get pointer to spin button .
CSpinButtonCtrl * pSpin - ( CSpinButtonCtrl *) GetDlgItem(IDC_SPIN)
ASSERT _ VALID (pSpin)
//Set spin button's default position .
pSpin —> SetPos (10)

return TRUE
}

其二, 可以使用ClassWizard将控件和成员变量联系起来。在ClassWizard中简单地选择Member Variables标签,然后选择Add Variable …按钮。如果在对话资源编辑器中,按下Ctrl键并双击控件即可转到Add Member Variable对话。

(38) 如何禁止和使能控件
控件也是窗口,所以可以调用CWnd : : EnableWindow使能和禁止控件。
//Disable button controls .
m_wndOK.EnableWindow (FALSE )
m_wndApply.EnableWindow (FALSE )

(39) 如何改变控件的字体
由于控件是也是窗口,用户可以调用CWnd: : SetFont指定新字体。该函数用一个Cfont指针,要保证在控件撤消之前不能撤消字体对象。下例将下压按钮的字体改为8点Arial字体:
//Declare font object in class declaration (.H file ).
private : Cfont m_font
// Set font in class implementation (.Cpp file ). Note m_wndButton is a
//member variable added by ClassWizard.DDX routines hook the member
//variable to a dialog button contrlo.
BOOL CSampleDialog : : OnInitDialog ( )
{

//Create an 8-point Arial font
m_font . CreateFont (MulDiv (8 , -pDC
—> GetDeviceCaps(LOGPIXELSY) ,72). 0 , 0 , 0 , FW_NORMAL , 0 , 0,0, ANSI_CHARSER, OUT_STROKE_PRECIS ,

CLIP_STROKE _PRECIS , DRAFT _QUALITY
VARIABLE_PITCH |FF_SWISS, _T("Arial") )

//Set font for push button .
m_wndButton . SetFont (&m _font )


}

(40) 如何在OLE控件中使用OLE_COLOR数据类型
诸如COleControl : : GetFortColor和COleControl : : GetBackColor等函数返回OLE _COLOR数据类型的颜色,而GDI对象诸如笔和刷子使用的是COLORREF数据类型,调用COleControl : : TranslateColor可以很容易地将OLE_COLOR类型改为COLORREF类型。下例创建了一个当前背景颜色的刷子:

void CSampleControl : : OnDraw (CDC* pdc
const Crect& rcBounds , const Crect& rcInvalid
)
{
//Create a brush of the cuttent background color.
CBrush brushBack (TranslateColor (GetBackColor () ) )

//Paint the background using the current backgroundcolor .
pdc—> FilllRect (rcBounds , &brushBack)

//other drawign commands


}

(41) 在不使用通用文件打开对话的情况下如何显示一个文件列表
调用CWnd: : DlgDirList或者CWnd: : DlgDirListComboBox,Windows 将自动地向列表框或组合框填充可用的驱动器名或者指定目录中的文件,下例将Windows目录中的文件填充在组合框中:
BOOL CSampleDig : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )
TCHAR szPath [MAX_PATH] = {"c:windows"}
int nReslt = DlgDirListComboBox (szPath, IDC_COMBO , IDC_CURIDIR, DDL_READWRITE |DDL_READONLY|DDL_HIDDEN| DDL_SYSTEM|DDL_ARCHIVE)
return TRUE
}

(42) 为什么旋转按钮控件看起来倒转
需要调用CSpinCtrl : : SetRange 设置旋转按钮控件的范围,旋转按钮控件的缺省上限为0,缺省下限为100,这意味着增加时旋转按控件的值由100变为0。下例将旋转按钮控件的范围设置为0到100:
BOOL CAboutDlg : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )

//set the lower and upper limit of the spin button
m_wndSpin . SetRange ( 0 ,100 )

return TRUE
}

Visual C++ 4.0 Print对话中的Copise旋转按钮控件也有同样的问题:按下Up按钮时拷贝的数目减少,而按下Down 按钮时拷贝的数目增加。

(43) 为什么旋转按钮控件不能自动地更新它下面的编辑控件
如果使用旋转按钮的autu buddy特性, 则必须保证在对话的标记顺序中buddy窗口优先于旋转按钮控件。从Layout菜单中选择Tab Order菜单项(或者按下Crtl+D)可以设置对话的标签顺序。

(44) 如何用位图显示下压按钮
Windows 95按钮有几处新的创建风格,尤其是BS_BITMAP和BS_ICON,要想具有位图按钮,创建按钮和调用CButton : : SetBitmap或CButton : : SetIcon时要指定BS_BITMAP或BS_ICON风格。

首先,设置按钮的图标属性。然后,当对话初始化时调用CButton: : SetIcon。注意:下例用图标代替位图,使用位图时要小心,因为不知道背景所有的颜色——并非每个人都使用浅灰色。

BOOL CSampleDlg : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )

//set the images for the push buttons .
BOOL CSampleDlg : : OnInitDialog ( )
{
CDialog : : OnInitDialog ( )

//set the images for the push buttons .
m_wndButton1.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION1))
m_wndButton2.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION2))
m_wndButton3.SetIcon (AfxGetApp ( ) —> LoadIcon (IDI _ IPTION3))

return TRUE
}

(45) 如何一个创建三态下压按钮
可以使用新的BS_PUSHBUTTON 风格位和检测框以及按钮来创建一个三态下压按钮。这很容易,只需将检测框和按钮拖拉到对话中并指定属性Push—like即可。不用任何附加程序就可以成为三态下压按钮。

(46) 如何动态创建控件
分配一个控件对象的实例并调用其Create成员函数。开发者最容易忽略两件事:忘记指定WS_VISBLE标签和在栈中分配控件对象。下例动态地创建一个下压按钮控件:
//In class declaration (.H file ).
private : CButton* m _pButton

//In class implementation (.cpp file ) .
m_pButton =new CButton
ASSERT_VALID (m_pButton)
m_pButton —>Create (_T ("Button Title ") , WS_CHILD |WS_VISIBLE |BS_PUSHBUTTON. Crect ( 0, 0, 100 , 24) , this , IDC _MYBUTTON )

(47) 如何限制编辑框中的准许字符
如果用户在编辑控件中只允许接收数字,可以使用一个标准的编辑控件并指定新的创建标志ES_NUMBERS,它是Windows 95新增加的标志,该标志限制 编辑控件只按收数字字符。如果用户需要复杂的编辑控件,可以使用Microsoft 的屏蔽编辑控件,它是一个很有用的OLE定制控件。
如果希望不使用OLE 定制控件自己处理字符,可以派生一个CEdit类并处理WM_CHAR消息,然后从编辑控件中过滤出特定的字符。首先,使用ClassWizard建立一个 CEdit的派生类,其次,在对话类中指定一个成员变量将编辑控件分类在OnInitdialog 中调用CWnd: : SubclassDlgItem .

//In your dialog class declaration (.H file )
private : CMyEdit m_wndEdit // Instance of your new edit control .

//In you dialog class implementation (.CPP file )
BOOL CSampleDialog : : OnInitDialog ( )
{


//Subclass the edit lontrod .
m_wndEdit .SubclassDlgItem (IDC_EDIT,this)


}

使用ClassWizard处理WM_CHAR消息,计算nChar参量并决定所执行的操作,用户可以确定是否修改、传送字符。下例说明了如何显示字母字符,如果字符是字母字符,则调用CWnd OnChar,否则不调用OnChar.
//Only display alphabetic dharacters .
void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UITN nFlags )
{
//Determine if nChar is an alphabetic character.
if (: : IsCharAlpha ( ( TCHAR) nChar ) )
CEdit : : OnChar (nChar, nRepCnt , nFlags )
}

如果要修改字符,则不能仅仅简单地用修改过的nChar调用CEdit: : OnChar,然后CEdit: : OnChar调用CWnd: : Default获取原来的wParam 和lParam 的值,这样是不行的。要修改一个字符,需要首先修改nChar,然后用修改过的nChar调用CWnd: : DefWindowProc。下例说明了如何将字符转变为大写:
//Make all characters uppercase
void CMyEdit : : OnChar (UINT nChar , UINT nRepCnt , UINT nFlags )
{
//Make sure character is uppercase .
if (: : IsCharAlpha ( .( TCHAR) nChar)
nChar=: : CharUpper(nChar )

//Bypass default OnChar processing and directly call
//default window proc.
DefWindProc (WM_CHAR, nChar , MAKELPARAM (nRepCnt, nFlags ))
}

(48) 如何改变控件的颜色
有两种方法。其一,可以在父类中指定控件的颜色,或者利用MFC4.0新的消息反射在控件类中指定颜色。当控件需要重新着色时,工作框调用父窗口(通常是对话框)的CWnd: : OnCrtlColor,可以在父窗口类中重置该函数并指定控件的新的绘画属性。例如,下述代码将对话中的所有编辑控件文本颜色改为红色:
HBRUSH CAboutDig : : OnCtlColor (CDC * pDCM , CWnd * pWnd , UINT nCtlColor)

{
HBRUSH hbr = CDialog : : OnCtlColor (pDC, pWnd , nCtlColor )

//Draw red text for all edit controls .
if (nCtlColor= = CTLCOLOR_EDIT )
pDC —> SetTextColor (RGB (255, 0 , 0 , ) )

return hbr
}

然而,由于每个父窗口必须处理通知消息并指定每个控件的绘画属性,所以,这种方法不是完全的面向对象的方法。控件处理该消息并指定绘画属性更合情合理。消息反射允许用户这样做。通知消息首先发送给父窗口,如果父窗口没有处理则发送给控件。创建一个定制彩色列表框控件必须遵循下述步骤。

首先,使用ClassWizard 创建一个CListBox 的派生类并为该类添加下述数据成员。
class CMyListBox publilc CListBox
{

private
COLORREF m_clrFor // foreground color
COLORREF m_clrBack //background color
Cbrush m_brush //background brush

}
其次,在类的构造函数中,初始化数据中。
CMyListBox : : CMyListBox ()
{
//Initialize data members .
m_clrFore =RGB (255 , 255 , 0) //yellow text
m_clrBack=RGB (0 , 0 , 255) // blue background
m_brush . CreateSolidBrush (m _clrBack )
}

最后,使用ClassWizard处理反射的WM_CTLCOLOR(=WM_CTLCOLOR)消息并指定新的绘画属性。
HBRUSH CMyListBox : : CtlColor (CDC* pDC, UINT nCtlColor )
{
pDC—>SetTextColor (m_clrFore)
pDC—>SetBkColor (m_clrBack)

return (HBRUSH) m_brush.GetSafeHandle ()
}
现在,控件可以自己决定如何绘画,与父窗口无关。

(49) 当向列表框中添加多个项时如何防止闪烁
调用CWnd::SetRedraw 清除重画标志可以禁止CListBox(或者窗口)重画。当向列表框添加几个项时,用户可以清除重画标志,然后添加项,最后恢复重画标志。为确保重画列表框的新项,调用SetRedraw (TRUE) 之后调用CWnd::Invalidate。

//Disable redrawing.
pListBox->SetRedraw (FALSE)

//Fill in the list box gere
//Enable drwing and make sure list box is redrawn.
pListBox->SetRedraw (TRUE)
pListBox->Invalidate ()

(50) 如何向编辑控件中添加文本
由于没有CEdit:: AppendText函数,用户只好自己做此项工作。调用CEdit:: SetSel移动到编辑控件末尾,然后调用CEdit:: ReplaceSel添加文本。下例是AppendText 的一种实现方法:

void CMyEdit:: AppendText (LPCSTR pText)
{
int nLen=GetWindowTextLength ()
SetFocus ()
SetSel (nLen, nLen)

ReplaceSel (pText)
}

(51) 如何访问预定义的GDI对象
可以通过调用CDC:: SlectStockObject使用Windows的几个预定义的对象,诸如刷子、笔以及字体。下例使用了Windows预定义的笔和刷子GDI对象在视窗中画一个椭圆。
//Draw ellipse using stock black pen and gray brush.
void CSampleView:: OnDraw (CDC* pDC)
{
//Determine size of view.
CRect rcView
GetClientRect (rcView)

//Use stock black pen and stock gray brush to draw ellipse.
pDC->SelectStockObject (BLACK_PEN)
pDC->SelectStockObject (GRAY_BRUSH)
//Draw the ellipse.
pDC->Ellipse (reView)
}

也可以调用新的SDK函数GetSysColorBrush获取一个系统颜色刷子,下例用背景色在视窗中画一个椭圆:
void CsampleView:: OnDraw (CDC* pDC)
{
//Determine size of view.
CRect rcView
GetClientRect (rcView)

//Use background color for tooltips brush.
CBrush * pOrgBrush=pDC->SelectObject ( CBrush ::FromHandle( ::GetSysColorBrush (COLOR_INFOBK)))

//Draw the ellipse.
pDC->Ellipse (rcView)

//Restore original brush.
pDC->SelectObject (pOrgBrush)
}

(52) 如何获取GDI对象的属性信息
可以调用GDIObject:: GetObject。这个函数将指定图表设备的消息写入到缓冲区。下例创建了几个有用的辅助函数。
//Determine if font is bold.
BOOL IsFontBold (const CFont&font)
{
LOGFONT stFont
font.GetObject (sizeof (LOGFONT), &stFont)
return (stFont.lfBold)? TRUE: FALSE
}

//Return the size of a bitmap.
CSize GetBitmapSize (const CBitmap&bitmap)
{
BITMAP stBitmap
bitmap.GetObject (sizeof (BITMAP), &stBitmap)
return CSize (stBitmap.bmWidth, stBitmap.bmHeight)
}

//Create a pen with the same color as a brush.
BOOL CreatePenFromBrush (Cpen&pen, cost Cbrush&brush)
{
LOGBRUSH stBrush
brush.Getobject (sizeof (LOGBRUSH), &stBrush)
return pen. Createpen (PS_SOLID, 0, stBrush.ibColor)
}

(53) 如何实现一个橡皮区矩形
CRectTracker是一个很有用的类,可以通过调用CRectTracker::TrackRubberBand 响应WM_LBUTTONDOWN消息来创建一个橡皮区矩形。
下例表明使用CRectTracker移动和重置视窗中的蓝色椭圆的大小是很容易的事情。

首先,在文件档中声明一个CRectTracker数据成员:
class CSampleView : Public CView
{

public :
CrectTracker m_tracker

}

其次,在文档类的构造函数中初始化CRectTracker 对象:
CSampleDoc:: CSampleDOC ()
{
//Initialize tracker position, size and style.
m_tracker.m_rect.SetRect (0, 0, 10, 10)
m_tracker.m_nStyle=CRectTracker:: resizeInside | CRectTracker ::dottedLine
}

然后,在OnDraw函数中画椭圆和踪迹矩形:
void CSampleView:: OnDraw (CDC* pDC)
{
CSampleDoc* pDoc=GetDocument ()
ASSERT_VALID (pDoc)

//Select blue brush into device context.
CBrush brush (RGB (0, 0, 255))
CBrush* pOldBrush=pDC->SelectObject (&brush)

//draw ellipse in tracking rectangle.
Crect rcEllipse
pDoc->m_tracker.GetTrueRect (rcEllipse)
pDC->Ellipse (rcEllipse)

//Draw tracking rectangle.
pDoc->m_tracker.Draw (pDC)
//Select blue brush out of device context.
pDC->Selectobject (pOldBrush)
}

最后,使用ClassWizard处理WM_LBUTTONDOWN消息,并增加下述代码。该段代码根据鼠标击键情况可以拖放、移动或者重置椭圆的大小。
void CSampleView::OnLButtonDown (UINT nFlags, CPoint point)
{
//Get pointer to document.
CSampleDoc* pDoc=GetDocument ()
ASSERT_VALID (pDoc)

//If clicked on ellipse, drag or resize it.Otherwise create a
//rubber-band rectangle nd create a new ellipse.
BOOL bResult=pDoc->m_tracker.HitTest (point)!= CRectTracker::hitNothing

//Tracker rectangle changed so update views.
if (bResult)
{
pDoc->m_tracker.Track (this,point,TRue)
pDoc->SetModifiedFlag ()
pDoc->UpdateAllViews (NULL)
}

else
pDoc->m-tracker.TrackRubberBand(this,point,TRUE)
CView:: onLButtonDown (nFlags,point)
}

(54) 如何更新翻转背景颜色的文本
调用CDC:: SetBkmode并传送OPAQUE用当前的背景颜色填充背景,或者调用CDC::SetBkMode并传送TRANSPAARENT使背景保持不变,这两种方法都可以设置背景模式。下例设置背景模式为TRANSPARENT,可以两次更新串,用花色带黑阴影更新文本。黑色串在红色串之后,但由于设置了背景模式仍然可见。

void CSampleView:: OnDraw (CDC* pDC)
{
//Determint size of view.
CRect rcView
GetClientRect (rcVieew)

//Create sample string to display.
CString str (_T ("Awesome Shadow Text..."))
//Set the background mode to transparent.
pDC->SetBKMode (TRANSPARENT)

//Draw black shadow text.
rcView.OffsetRect (1, 1)
pDc->SetTextColor (RGB (0, 0, 0))
pDC->DrawText (str, str.GetLength (), rcView, DT_SINGLELINE | DT_CENTER | DT_VCENTER)

//Draw red text.
rcView.OffsetRect (-1,-1)
pDc->SetTextColor (RGB (255, 0, 0))
pDC->DrawText (str, str.GetLength (), rcView, DT_SINGLELINE | DT_CENTER | DT_VCENTER)

}

(55) 如何创建一个具有特定点大小的字体
可以指定字体逻辑单位的大小,但有时指定字体的点的大小可能会更方便一些。可以如下将字体的点转换为字体的高度:

int nHeigth=mulDiv (nPointSize, -dc.GetDeviceCaps (LOGPIXELSY), 72)
下例创建了一个8点的Apial字体:

CClientDC dc (AqfxGetMainWnd ())

m_font. CreateFont (MulDiv (8, -dc.GetDeviceCaps (LOGPIXELSY), 72), 0, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET, OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS, DRAFT_QUALITY, VARIABLE_PITCH | FF-SWISS,_T("Arial"))

(56) 如何计算一个串的大小
函数CDC:: Det text Extent 根据当前选择的字体计算一个串的高度和宽度。如果使用的不是系统字体而是其他字体,则在调用GetTextExtent之前将字体选进设备上下文中是很重要的,否则计算高度和宽度时将依据系统字体,由此得出的结果当然是不正确的。下述样板程序当改变下压按钮的标题时动态调整按钮的大小,按钮的大小由按钮的字体和标题的大小而定。响应消息WM_SETTEXT时调用OnSetText,该消息使用ON_MESSAE宏指令定义的用户自定义消息。

LRESULT CMyButton:: OnSettext (WPARAM wParam, LPARAM lParam)
{
//Pass message to window procedure.
LRESULT bResult=CallWindowProc (*GetSuperWndProcAddr(), m_hWnd, GetCurrentMessage() ->message,wParam,lParam)
//Get title of push button.
CString strTitle
GetWindowText (strTitle)

//Select current font into device context.
CDC* pDC=GetDc ()
CFont*pFont=GetFont ()
CFont*pOldFont=pDC->SelectObject (pFont)

//Calculate size of title.
CSize size=pDC->GetTextExent (strTitle,strTitle.GetLength())

//Adjust the button's size based on its title.
//Add a 5-pixel border around the button.
SetWindowPos (NULL, 0, 0, size.cx+10, size.cy+10, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE)
//Clean up.
pDC->SelectFont (pOldFont)
ReleaseDC (pDC)

return bResult
}

(57) 如何显示旋转文本
只要用户使用TrueType或者GDI笔或字体就可以显示旋转文本(有些硬件设备也支持旋转光栅字体)。LOGFONT结构中的ifEscapement 成员指定了文本行和x轴的角度,角度的单位是十分之一度而不是度,例如,ifEscapement为450表示字体旋转45度。为确保所有的字体沿坐标系统的同一方向旋转,一定要设置ifEscapement成员的CLIP_LH_ANGLES位,否则,有些字体可能反向旋转。下例使用了14点Arial 字体每间隔15度画一个串。
void CSampleView:: OnDraw (CDC* pDC)
{
//Determine the size of the window.
CRect rcClient
GetClientRect (rcClient)

//Create sample string.
CString str (_T ("Wheeee...I am rotating!"))
//Draw transparent, red text.
pDC->SetBkMode (TRANSPARENT)
pDC->SetTextColor (RGB (255,0,0))
CFont font
//font object
LOGFONT stFont //font definition
//Set font attributes that will not change.
memset (&stFont, 0, sizeof (LOGFONT))
stFont.ifheight=MulDiv (14, -pDC->GetDeviceCaps(LOGPIXELSY), 72)
stFont.ifWeight=FW_NORMAL
stFont.ifClipPrecision=LCIP_LH_ANGLES
strcpy (stFont.lfFaceName, "Arial")

//Draw text at 15degree intervals.
for (int nAngle=0 nAngle<3600 nAngle+=150)
{
//Specify new angle.
stFont.lfEscapement=nAngle

//Create and select font into dc.
font.CreateFontIndirect(&stfont)
CFont* pOldFont=pDC ->SelectObject(&font)

//Draw the text.
pDC->SelectObject(pOldFont)
font.DelectObjext()
}
}

(58) 如何正确显示包含标签字符的串
调用GDI文本绘画函数时需要展开标签字符,这可以通过调用CDC:: TabbedTextOut或者CDC:: DrawText并指定DT_EXPANDTABS标志来完成。TabbedTextOut函数允许指定标签位的数组,下例指定每20设备单位展开一个标签:

void CSampleView:: OnDraw (CDC* pDC)
{
CTestDoc* pDoc=GetDocument ()
ASSERT_VALID (pDoC)

CString str
str.Format (_T ("CathytNormantOliver"))
int nTabStop=20 //tabs are every 20 pixels
pDC->TabbedtextOut (10, 10, str, 1, &nTabStop, 10)
}

(59) 如何快速地格式化一个CString对象
调用CString:: Format,该函数和printf函数具有相同的参数,下例说明了如何使用Format函数:

//Get size of window.
CRect rcWindow
GetWindowRect (rcWindow)
//Format message string.
CString strMessage
strMessage.Format (_T ("Window Size (%d, %d)"),

rcWindow.Width (), rcWindow.Height ())

//Display the message.
MessageBox (strmessage)

(60) 串太长时如何在其末尾显示一个省略号
调用CDC:: DrawText并指定DT_END_ELLIPSIS标志,这样就可以用小略号取代串末尾的字符使其适合于指定的边界矩形。如果要显示路径信息,指定DT_END_ELLIPSIS标志并省略号取代串中间的字符。

void CSampleView:: OnDraw (CDC* pDC)
{
CTestDoc* pDoc=GetDocument ()
ASSERT_VALID (pDoc)

//Add ellpsis to end of string if it does not fit
pDC->Drawtext (CString ("This is a long string"), CRect (10, 10, 80, 30), DT_LEFT | DT_END_ELLIPSIS)

//Add ellpsis to middle of string if it does not fit
pDC->DrawText (AfxgetApp () ->m_pszhelpfilePath, CRect (10, 40, 200, 60), DT_LEFT | DT_PATH_ELLIPSIS)
}

(61) 为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态
需要将CFrameWnd:: m_bAutomenuEnable设置为FALSE,如果该数据成员为TRUE(缺省值),工作框将自动地禁止没有ON_UPDATE_COMMAND_UI或者ON_COMMAND的菜单项。

//Disable MFC from automatically disabling menu items.
m_bAuoMenuEnable=FALSE
//Now enable the menu item.
CMenu* pMenu=GetMenu ()
ASSERT_VALID (pMenu)

pMenu->EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND | MF_ENABLED)

(62) 如何给系统菜单添加一个菜单项
给系统菜单添加一个菜单项需要进行下述三个步骤:
首先,使用Resource Symbols对话(在View菜单中选择Resource Symbols...可以显示该对话)定义菜单项ID,该ID应大于0x0F而小于0xF000;
其次,调用CWnd::GetSystemMenu获取系统菜单的指针并调用CWnd:: Appendmenu将菜单项添加到菜单中。下例给系统菜单添加两个新的
int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct)
{

//Make sure system menu item is in the right range.
ASSERT (IDM_MYSYSITEM &0xFFF0)==IDM_MYSYSITEM)
ASSERT (IDM-MYSYSITEM<0xF000)

//Get pointer to system menu.
CMenu* pSysmenu=GetSystemmenu (FALSE)
ASSERT_VALID (pSysMenu)
//Add a separator and our menu item to system menu.
CString StrMenuItem (_T ("New menu item"))
pSysMenu->Appendmenu (MF_SEPARATOR)
pSysMenu->AppendMenu (MF_STRING, IDM_MYSYSITEM, strMenuitem)


}

现在,选择系统菜单项时用户应进行检测。使用ClassWizard处理WM_SYSCOMMAND消息并检测用户菜单的nID参数:
void CMainFrame:: OnSysCommand (UINT nID,LPARAM lParam)
{
//Determine if our system menu item was selected.
if ( (nID & 0xFFF0)==IDM_MYSYSITEM)
{
//TODO-process system menu item
}

else
CMDIFrameWnd ::OnSysCommand (nID, lParam)
}
最后,一个设计良好的UI应用程序应当在系统菜单项加亮时在状态条显示一个帮助信息,这可以通过增加一个包含系统菜单基ID的串表的入口来实现。

(63) 如何确定顶层菜单所占据的菜单行数
这可以通过简单的减法和除法来实现。首先,用户需要计算主框窗口的高度和客户区;其次,从主框窗口的高度中减去客户区、框边界以及标题的高度;最后,除以菜单栏的高度。下例成员函数是一个计算主框菜单所占据的行数的代码实现。

int CMainFrame:: GetMenuRows ()
{
CRect rcFrame,rcClient
GetWindowRect (rcFrame)
GetClientRect (rcClient)
return (rcFrame.Height () -rcClient.Height () - :: GetSystemMetrics(SM_CYCAPTION) - (:: getSystemMetrics(SM_CYFRAME) *2)) / :: GetSystemMetrics(SM_CYMENU)
}

(64) 在用户环境中如何确定系统显示元素的颜色
调用SDK函数GetSysColor可以获取一个特定显示元素的颜色。下例说明了如何在MFC函数CMainFrameWnd:: OnNcPaint中调用该函数设置窗口标题颜色。

void CMiniFrameWnd:: OnNcPaint ()
{

dc.SetTextColor (:: GetSysColor (m_bActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT))


(65) 如何查询和设置系统参数
在Windows 3.1 SDK中介绍过SDK函数SystemParametersInfo,调用该函数可以查询和设置系统参数,诸如按键的重复速率设置、鼠标双击延迟时间、图标字体以及桌面覆盖位图等等。

//Create a font that is used for icon titles.
LOGFONT stFont
∶: SystemParametersInfo (SPIF_GETICONTITLELOGFONT, sizeof (LOGFONT), &stFont, SPIF_SENDWININICHANGE)
m_font.CreateFontIndirect (&stFont)

//Change the wallpaper to leaves.bmp.
∶ : SystemParametersInfo (SPI_SETDESKWALLPAPER, 0, _T (" forest.bmp"), SPIF_UPDATEINIFILE)

(66) 如何确定当前屏幕分辨率
调用SDK函数GetSystemMetrics,该函数可以检索有关windows显示信息,诸如标题大小、边界大小以及滚动条大小等等。

//Initialize CSize object with screen size.
CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN),
GetSystemMetrics (SM_CYSCREEN))

(67) 如何使用一个预定义的Windows光标
调用CWinApp:: LoadStandardCursor并传送光标标识符。
BOOL CSampleDialog:: OnSetCursor (CWnd* pWnd,
UINT nHitTest, UINT
message)
{
//Display wait cursor if busy.
if (m_bBusy)
{
SetCursor (AfxGetApp () ->LoadStandardCursor (IDC_WAIT))
return TRUE
}

return CDialog:: OnSetCursor (pWnd. nHitTest,message)
}

(68) 如何检索原先的Task Manager应用程序使用的任务列表
原先的Task Manager应用程序显示顶层窗口的列表。为了显示该列表,窗口必须可见、包含一个标题以及不能被其他窗口拥有。调用CWnd:: GetWindow可以检索顶层窗口的列表,调用IsWindowVisible、GetWindowTextLength以及GetOwner可以确定窗口是否应该在列表中。下例将把TaskManager窗口的标题填充到列表中。

void GetTadkList (CListBox&list)
{
CString strCaption
//Caption of window.

list.ResetContent ()
//Clear list box.

//Get first Window in window list.
ASSERT_VALID (AfxGetMainWnd ())
CWnd* pWnd=AfxGetMainWnd () ->GetWindow (GW_HWNDFIRST)

//Walk window list.
while (pWnd)
{
// I window visible, has a caption, and does not have an owner?
if (pWnd ->IsWindowVisible()
&& pWnd ->GetWindowTextLength ()
&&! pWnd ->GetOwner ())
{

//Add caption o window to list box.

pWnd ->GetWindowText (strCaption)

list.AddString (strCaption)
}
//Get next window in window list.
pWnd=pWnd ->GetWindow(GW_HWNDNEXT)
}
}

(69) 如何确定Windows和Windows系统目录
有两个SDK函数可以完成该功能。GetWindowsDirectory和GetSystemDirectory,下例说明了如何使用这两个函数:

TCHAR szDir [MAX_PATH]
//Get the full path of the windows directory.
∶ : GetWindowsDirectory (szDir, MAX_PATH)
TRACE ("Windows directory %sn", szDir)
//Get the full path of the windows system directory.
∶ : GetSystemDirectory (szDir, MAX_PATH)
TRACE ("Windows system directory %sn", szDir)

(70) 在哪儿创建临文件
调用SDK函数GetTemPath可以确定临时文件的目录,该函数首先为临时路径检测TMP环境变量:如果没有指定TMP,检测TMP环境变量,然后返回到当前目录。下例说明了如何创建一个临时文件。


//get unique temporary file.
CString strFile
GetUniqueTempName (strFile)
TRY
{
//Create file and write data.Note that file is closed
//in the destructor of the CFile object.
CFile file (strFile,CFile ::modeCreate | Cfile:: modeWrite)

//write data
}

CATCH (CFileException, e)
{
//error opening file
}
END_CATCH


Void GetuniqueTempName (CString& strTempName)
{
//Get the temporary files directory.
TCHAR szTempPath [MAX_PATH]
DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath)
ASSERT (dwResult)

//Create a unique temporary file.
TCHAR szTempFile [MAX_PATH]
UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempfile)
ASSERT (nResult)

strTempName=szTempFile
}

(71) 我怎样才能建立一个等待光标?
调 用 BeginWaitCursor 函 数 来 启 动 等 待 光 标,调 用 EndWaitCursor 函 数 来 结 束 等 待 光 标。要 注 意,二 者 都 要 调 用 app 的 成 员 函 数,如 下 所 示:

AfxGetApp()->BeginWaitCursor();
// 要做的事
AfxGetApp()->EndWaitCursor();

(72) 我在MDI框架中有个 form 视窗。它有个取消按钮,我需要当用户按取消按钮时可关闭form视窗。我应该如何关闭该文档?
调 用 OnCloseDocument 函 数。

(73) 如何访问桌面窗口
静态函数CWnd:: GetDesktopWindow 返回桌面窗口的指针。下例说明了MFC函数CFrameWnd::BeginModalStae是如何使用该函数进入内部窗口列表的。

void CFrameWnd::BeginModalState ()
{

//first count all windows that need to be disabled
UINT nCount=0
HWND hWnd= :: GetWindow (:: GetDesktopWindow(), GW_CHILD)
while (hWnd!=NULL)
{
if (:: IsWindowEnabled (hwnd)
&& CWnd::FromHandlePermanent (hWnd)!=NULL
&& AfxIsDescendant (pParent->m_hWnd, hWnd)
&& :: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0)==0)
{
++nCount
}
hWnd=:: GetWindow (hWnd, GW_HWNDNEXT)
}


(74) 什么是COLORREF? 我该怎样用它?
COLORREF 是 一 个 32-bit 整 型 数 值,它 代 表 了 一 种 颜 色。你 可 以 使 用 RGB 函 数 来 初 始 化 COLORREF。例 如:

COLORREF color = RGB(0, 255, 0);
RGB 函 数 接 收 三 个 0-255 数 值,一 个 代 表 红 色, 一 个 代 表 绿 色, 一 个 代 表 蓝 色。在 上 面的 例 子中, 红 色 和 蓝 色 值 都 为 0,所 以 在 该 颜 色 中 没 有 红 色 和 蓝 色。绿 色 为 最 大 值 255。所 以 该颜 色 为 绿 色。0,0,0 为 黑 色,255,255,255 为 白 色。

另 一 种 初 始 化 COLORREF 的 方 法 如 下 所 示:

CColorDialog colorDialog;
COLORREF color;

if( colorDialog.DoModal() == IDOK )
{
color = colorDialog.GetColor();
}
这 段 代 码 使 用 了 MFC 中 的 颜 色 对 话 框,它 需 要 文 件。

(75) AppWizard所产生的STDAFX文件是干什么用的?
它 主 要 是 协 助 产 生 预 编 译 头 文 件 的。通 常 你 是 不 需 要 修 改 它 的。

(76) 我在我的程序中是了CDWordArray。我向它添加了约10,000个整数,这使得它变得非常非常慢。为什么会这么糟?
CDWordArray 是 很 好 用 的,只 是 因 为 你 没 有 指 定 数 组 的最大尺寸。因 此,当 你 添 加 新 元 素 时,该 类 会 从 堆 中 重新 分 配 空 间。不 幸 的 是,该 类 会 在 每 次 插 入 新 元 素 时 都 为 数 组 重 新 分 配 空 间。如 果 你 向 它添 加 了 很 多 新 元 素,所 有 这 些 分 配 和 复 制 数 组 的 操 作 会 就 会 使 它 变 慢。解 决 该 问 题 的 方法 是,你 可 以 使 用 SetSize 函 数 的 第 二 个 参 数 来 改 变 这 种 重 新 分 配 的 频 率。例 如,如 果 你把 该 参 数 设 置 为 500,则 每 次 数 组 空 间 超 出 时 它 才 重 新 分 配 并 添 加 500 个 新 空 间,而 不是 1 个。这 样 一 来,你 就 可 以 不 用 重 新 分 配 而 添 加 了 另 外 499 个 元 素 空 间,这 也 会 大 大 提高 程 序 的 运 行 速 度。

(77) 我该如何改变MDI框架窗口的子窗口的大小以使在窗口以一定的大小打开?
在视 中 的 OnInitialUpdate 函 数 中 调 用 GetParentFrame 函 数。GetParentFrame 会 返 回一 指 向 一 保 存 有 该 视 的 框 架 窗 口 的 指 针。然 后 调 用 在 框 架 窗 口 上 调 用 MoveWindow。

(78) 在我的程序的某些部分,我可以调用 MessageBox 函数来建立一个信息对话框,例如在视类中。但是,在其它部分我却不能,如文档类中。为什么?我怎样才能在我的应用程序类中建立一个信息对话框?
MessageBox 函 数 来 自 CWnd 类,所 以 你 只 能 在 从 CWnd 继 承 的 类 ( 如 CView ) 中 调 用 它。但 是,MFC 也提 供 了 AfxMessageBox 函 数,你 可 以 在 任 何 地 方 调 用 它。

(79) 我需要在我的程序中设置全局变量,以使文档中的所有类都能访问。我应该吧它放到哪儿?
把 该 变 量 放 到 该 应 用 程 序 类 的 头 文 件 中 的 attribute 处。然 后,在 程 序 的 任 何 地 方,你 都 可 以 用 下 面 的 方 法 来 访 问 该 变 量:

CMyApp *app = (CMyApp *)AfxGetApp();
app->MyGlobalVariable = ...

(80) 我听说MFC可以发现内存漏洞,我怎样使用该特性?
如果 你 在 Debug 菜 单 中 的 Go 选 项 ( 不 是 Project 菜 单 中 的 Execute 选 项 ) 来 运 行 你的 应 用 程 序,MFC 应 该 在 程 序 终 止 时 报 告 内 存 漏 洞。如 果 没 有,那 么 试 试 运 行 MFC Tracer 工 具 程 序 ( 在 VC++ 程 序 组 中 ),并 启 动 跟 踪。然 后 返 回 应 用 程 序。

(81) 我怎样才能在我的应用程序中循环浏览已经打开的文档?
使用CDocTemplate中未公开的GetFirstDocPosition()和GetNextDoc()函数。

(82)才能在我的应用程序中循环浏览已经打开的视?
使 用 CDocument 中 未 公 开 的 GetFirstViewPosition() 和 GetNextView() 函 数。

(83)数PreCreateWindow是干什么用的?
PreCreateWindow 允 许 你 在 调 用 CreateWindow 之 前 来 改 变 窗 口 属 性。

(84)该怎样防止MFC在窗口标题栏上把文档名预置成应用程序名?
在 PreCreateWindow 函 数 中 删 除 FWS_PREFIXTITLE 标 志 的 窗 口 样 式:

cs.style &= ~FWS_PREFIXTITLE;

(85) 我应该怎样防止MFC在窗口标题栏上添加文档名?
在 PreCreateWindow 函 数 中 删 除 FWS_ADDTOTITLE 标 志 的 窗 口 样 式:

cs.style &= ~FWS_ADDTOTITLE ;

(86) 我应该如何改变视窗口的大小?
因为 视 窗 口 实 际 上 是 框 架 窗 口 的 子 窗 口,所 以 你 必 须 改 变 框 架 窗 口 的 大 小,而 不 是 改 变 视窗 口。使 用 CView 类 中 的 GetParentFrame() 函 数 获 得 指 向 框 架 窗 口 的 指 针,然 后 调 用 MoveWindow() 函 数 来 改 变 框 架 的 大 小。这 会 使 变 尺 寸 的 视 充 满 框 架 窗 口。

(87) 我有一无模式对话框。我怎样才能在窗口退出时删除CDialog对象?
把“delete this”加 到 PostNcDestroy 中。这 主 要 用 在 需 要 自 动 删 除 对 象 的 场 合。

(88) 为什么把“delete this”放在PostNcDestroy中而不是OnNcDestroy?
OnNcDestroy 只 被 已 建 立 的 窗 口 调 用。如 果 建 立 窗 口 失 败 ( 如 PreCreateWindow ),则 没 有 窗 口 处 来发 送 WM_NCDESTROY 消 息。PostNcDestroy 是 在 对 象 窗 口 被 完 全 删 除,在 OnNcDestroy 后,甚 至 在 窗 口 建 立 失 败 之 后 调 用 的。

(89) File菜单中的MRU列表是从哪儿来的?列表中的名字放在哪儿了?我怎样才能改变列表中项目的最大值?
在应 用 程 序 类 的 InitInstance 函 数 中 对 LoadStdProfileSettings 的 调 用 中。该 调 用 接受 一 个 参 数 ( 在 缺 省 情 况 下 如 果 没 有 传 递 值 则 为 4 )。MRU 文 件 名 是 从 INI 文 件 中 调用 的。如 果 你 有 带 有 ID_FILE_MRU_FILE1 的 ID 的 菜 单 选 项,它 会 为 调 入 的 MRU 列 表 所替 换。如 果 你 改 变 传 递 给 LoadStdProfileSettings 的 数 值 ( 最 大 为 16 ),则 你 就 改 变了 所 装 如 文 件 名 的 最 大 值。

(90) 我在菜单中添加了新的项。但是,当我选该项时,在状态栏上没有出现任何提示信息。为什么?
打开 资 源 文 件 中 的 菜 单 模 板。打 开 新 菜 单 选 项 的 属 性 对 话 框。在 对 话 框 的 底 部 的 Prompt 编 辑 框 中 ,你 可 以 如 下 指 定 状 态 栏 上 的 提 示 信 息 和 工 具 栏 上 的 提 示 信 息 ( 如 果 你 已经 建 立 的 工 具 栏 按 钮 ):

Status bar stringnFlying tag

(91) 我怎样才能在应用程序的缺省系统菜单中加上一些东西?
系 统 菜 单 与 其 它 菜 单 类 似,你 可 以 添 加 或 删 除 项 目,这 需 要 使 用 CMenu 类 的 成 员 函 数。下 面 的 代 码 在 你 的 系 统 菜 单 后 面 添 加 一 个 新 菜 单 项:

CMenu *sysmenu;
sysmenu = m_pMainWnd->GetSystemMenu(FALSE);
sysmenu->AppendMenu(MF_STRING, 1000, "xxx");
参 见 MFC 帮 助 文 件 中 的 CMenu 类。

(92) 我建立了一个对话框。但是当我显示该对话框时,第一个编辑框总是不能获得焦点,我必须单击它来使它获得焦点。我怎样才能使第一个编辑框在对话框打开时就获得焦点?
打 开 资 源 编 辑 器 中 的 对 话 框 模 板。在 Layout 菜单 中 选 择 Tab Order 选 项。按 你 的 需 求 单 击 对 话 框 中 的 控 制 来 重 新 排 列 这 些 控 制 的 tab 顺 序。

(93) 我怎样才能使一个窗口具有“always on top”特性?
在 调 用 OnFileNew 后,在 你 的 InitInstance 函 数 中 加 上 下 面 的 代 码:

m_pMainWnd->SetWindowPos(&CWnd::wndTopMost,0,0,0,0, SWP_NOMOVE | SWP_NOSIZE);

(94) 我要为我的form view添加文档模板。我先建立了对话框模板,然后使用ClassWizard建立了基于CFormView的新类,它也是从CDocument继承来的。我还建立了相应的资源并在InitInstance中添加了新的文档模板。但是,当我试图运行该程序时,出现了Assertion信息。为什么?

form 的 对 话 框 模 板 需 要 些 特 殊 设 置 以 便 可 用 于 CFromView。确 保 这 些 设 置 的 最 简 单 方 法 是使 用 AppWizard 来 建 立 CFormView 应 用 程 序,并 查 看 AppWizard 所 建 立 的 对 话 框 模 板所 选 择 的Styles Properties。你 会 发 现 该 对 话 框 模 板 具 有 下 列 样 式:没 有 标 题 栏、不 可见 和“Child”。把 你 的 form view 的 对 话 框 属 性 变 成 这 样 就 可 以 了。

(95) 我在一对话框中有一列表框,我需要tabbed列表框中的项目。但是,当我处理含有tab字符(用AddString添加的)的列表项时,tab被显示成小黑块而没有展开。哪儿出错了?

在 对 话 框 模 版 中,打 开 列 表 框 的 属 性。确 保 选 择 了“Use Tabstops” 样 式。然 后,确 保 在 对 话 框 类 中 OnInitDialog 函 数 中 调 用 SetTabStops。

(96) 我建立了一个应用程序,并使用了CRecordset类。但是,当我运行该程序时,它试图要访问数据库,并给出“Internal Application Error”对话框。我应该怎样做?

通 常 情 况 下,当 你 的 程 序 中 向 数 据 库 发 送 信 息 的 SQL 语 句 出 现 问 题 时 才 出 现 该 对 话 框。例 如,参 见 下 面 的 例 子:

set.m_strFilter = "(ZipCode = '27111')";
如果 ZipCode 列 被 定 义 为 字 符 串 时 不 会 出 现 问 题,如 果 定 义 为 long,则 会 出 现“Internal Application Error”对 话 框,这 是 由 于 类 型 不 匹 配 的 缘 故。如 果 你 删 除 27111 的 单 引号,则 不 会 出 现 问 题。当 你 看 到“Internal Application Error”时,最 好 检 查 一 下 试 图 要发 送 给 数 据 库 的 SQL 语 句。

(97) 我用ClassWizard建立了一个类。但是,我把名字取错了,我想把它从项目中删除,应该如何做?

在 ClassWizard 对 话 框 关 闭 后,用 文 件 管 理 器 删 除 新 类 的 H 和 CPP 文 件。然 后 打 开 ClassWizard,它 会 提 示 丢 失 了 两 个 文 件,并 询 问 你 该 如 何 做。你 可 以 选 择 从 项 目 中 删 除这 两 个 问 的 按 钮。

(98) 当我打开应用程序中的窗口时,我要传递该窗口的矩形尺寸。该矩形指定了窗口的外围大小,但是当我调用GetClientRect时,所得到的尺寸要比所希望的值要小(因为工具栏和窗口边框的缘故)。有其它方法来计算窗口的尺寸吗?

参 见 CWnd::CalcWindowRect。

(99) 我在文档类中设置了一个整型变量。但是,当我试图把该变量写入Serialize函数中的archive文件中时,出现了类型错误。而文档中的其它变量没有问题。为什么?

archive 类 只 重 载 某 些 类 型 的 >> 和 << 操 作 符。“int”类 型 没 有 在 其 中,也 许 是 因为 int 变 量 在 Windows 3.1 与 Windows NT/95 有 所 不 同 的 缘 故 吧。“long”类 型 得 到 了支 持,所 以 你 可 以 把 int 类 型 改 成 long 型。参 见 MFC 帮 助 文 件 中 CArchive 类。


(100) 如何控制菜单的大小?
我用MFC的CMenu生成了一个动态菜单(例如File,Edit,View...Help), 我想控制这个菜单的大小(长+高).

方法一:查找 WM_MEASUREITEM 和 MEASUREITEMSTRUCT.
方法二:查询系统::GetSystemMetric(SM_CXMENUSIZE).

/* 你可以通过如下代码来获得文本的大小:
(A)获得被使用的字体 */

NONCLIENTMETRICS ncm;
HFONT hFontMenu;
SIZE size;
size.cy = size.cy = 0;

memset(&ncm, 0, sizeof(NONCLIENTMETRICS));
ncm.cbSize = sizeof(NONCLIENTMETRICS);
if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
{
hFontMenu = CreateFontIndirect(&ncm.lfMenuFont);
/*
(B) 获得菜单项的文本: */
char szText[_MAX_PATH];

pMenu->GetMenuString(0, szText, _MAX_PATH, MF_BYPOSITION);
/*
然后,获得菜单项文本的高度: */
HFONT hFontOld;
HDC hDC;

hDC = ::GetDC(NULL);
hFontOld = (HFONT) ::SelectObject(hDC, hFontMenu);
GetTextExtentPoint32(hDC, szText, lstrlen(szText), &size);
SelectObject(hDC, hFontOld);
::ReleaseDC(NULL, hDC);
}
/*此时,size.cy即为高度,size.cx为宽度,你可以给菜单加上自定义的高度和宽度,通过比较,我发现宽度为4

比较合适。*/


(101) 改变LVIS_SELECTED的状态颜色?
我想将CListCtrl项和CTreeCtrl项在LVIS_SELECTED状态时的颜色变灰.

方法一:查找函数CustomDraw,它是IE4提供的公共控制,允许有你自己的代码.
方法二:生成一个draw控件,然后在DrawItem中处理文本颜色.

(102) 如何只存储文档的某一部分?
我只想存储文档的某一部分,

2008年10月26日星期日

LWUIT – One Interface to Rule Them All


LWUIT – One Interface to Rule Them All
http://thefutureofthings.com/news/5579/lwuit-one-interface-to-rule-them-all.html
A team of scientists at the Israeli branch of Sun Microsystems have developed a unifying user interface (UI) library for mobile devices built upon Sun’s well known Java platform. The interface, which according to the development team, was inspired by Swing programming paradigm and its design, provides a solution to a longtime problem faced by J2ME developers, which is the inconsistent and often hazardous behavior of the J2ME UI classes under various product vendors. The new interface will be able, according to its developers, to run on any Java-enabled mobile device and under any operating system.

一个统一的移动设备上的用户界面库(UI)
你可以在这里下载:https://lwuit.dev.java.net/,这里还有两个YouTube的视频演示。

2008年8月16日星期六

Ext JS Overview

一个跨平台的JavaScript库
Ext JS is a cross-browser JavaScript library for building rich internet applications. It includes:
High performance, customizable UI widgets
Well designed and extensible Component model
An intuitive, easy to use API
Commercial and Open Source licenses available

支持的浏览器包括
Browser Compatibility
Ext JS supports all major web browsers including:

Internet Explorer 6+
FireFox 1.5+ (PC, Mac)
Safari 3+
Opera 9+ (PC,
Mac)

Kentico CMS for ASP.NET Free Edition 免费的内容管理系统

Kentico CMS for ASP.NET Free Edition
You can use Kentico CMS Free Edition for commercial and personal projects. There’s no hidden fee!

Whether you build a personal blog, corporate site or a small on-line store, you can use the Free Edition for unlimited time on your live server!
免费版本有如下的限制:
The free edition has the following limits:
1 global administrator user
account per installation
1 editor per web site
1000 documents/pages per
web site
100 site members per web site
you are required to put the Powered
by Kentico CMS logo
in the footer of all pages managed by Kentico CMS
the support is available only through forums without any
guarantee (e-mail and phone support is only available for the users of the paid
editions and for evaluators)
点击查看所有的功能:Feature Matrix
You can see all features available in the Free Edition in the Feature Matrix.

Please note: if you wish to evaluate all Kentico CMS features, please use the trial version that is limited by 30-day trial period, but supports all functionality.