??xml version="1.0" encoding="utf-8" standalone="yes"?> 在处理内存分配的时候,C++E序员会?/span>new操作W(operator newQ来分配内存Qƈ?/span>delete操作W(operator deleteQ来释放内存。这是一?/span>new操作W的例子?/span> class CTest 虽然q种写法在大多数时候都工作得很好,但还是有些情况下使用new是很烦h的,比如当你想重新分配一个数l或者当你想在预分配的内存上构造一个对象的时候?/span> 比如W一U情况,重新分配一个数l效率是很低的: // 分配一个有10个对象的数组 如果你想在预分配的内存上创徏对象Q用~省?/span>new操作W是行不通的。要解决q个问题Q你可以?/span>placement new构造。它允许你构造一个新对象到预分配的内存上Q?/span> // buffer 是一?/span>void指针 (void *) 下面是一些例子: #include <new> 当你有自q内存~冲区或者在你实现自q内存分配{略的时候,placement new会很有用。事实上?/span>STL中广泛用了placement new来给容器分配内存Q每个容器类都有一个模版参数说明了构?/span>/析构对象时所用的分配器(allocatorQ?/span> 在?/span>placement new的时候,你要C以下几点Q?/span> pFirst->~CTest(); 字符串拆分的中文处理问题 容健行@2007q?/span>7?/span> 转蝲h明出?/span> 原文出处Q?a target="_blank">http://www.devdiv.net/home/space.php?uid=125&do=blog&id=365 拆分一个字W串在程序中使用非常q泛Q特别是我们l常跟表格打交道的程序员们。所谓拆分字W串Q就是将一个字W串中间以某个(或某些)字符为分隔,拆分成多个字W串。如 std::string s = "abc | ddd | 中国"; 如果以竖U?#8220;|”拆分Q可以将q个字符串拆分成三个字符丌Ӏ?/span> 当然字符串拆分还包括通过正则表达式来拆分Qؓ了简化问题,我们以单个字W做分隔的拆分,因ؓq种拆分用得最多。代码?/span>C++来讲解?/span> 问题来源于实际,是之前我们组和其他组都有遇上的。先看一个例子,使用"|"拆分以下字符Ԍ看v来怎么数都是分?/span>48列,但我看到好几个版本的字符串拆分函数却报有49列: "AGZGY1000004|200|刘瓅||20100101||OPRT10|1|0||AAGZ0Y100|0|0|24|0|0|0|0||-1|20030101|0|20991231||AGZGK6172888|200|曾晓?/span>||20100101||OPRT10|1|0||AAGZ0K617|0|0|24|0|0|0|0||-1|20061215|1|20061215||" 让我们先把以上字W串攑ֈUltraEdit中,q切换到16q制的编辑模式,看看它的~码?/span> 原因是原来的字符串拆分函数只是简单的查找“?#8221;Q编码ؓ0x7cQ?/span>,而没有考虑C文的处理Q源代码太多Q且有好几个版本Q这里略去)?/span> ?/span>boss中,c++E序使用的编码方式几乎全?/span>ansiQ而在ansi中,表示中文是用两个字符Q且W一个字W是一个大?/span>0x80的字W(字符的第一位ؓ1Q,W二个字WؓL字符。这里引起一个问题: 当我们要分割字符串时Q假如用"|"(0x7c)作ؓ分割W,当分析上面这个字W遇?/span>"?/span>"(~码?/span>0xad,0x7c)q个字符Ӟ会把它第二个字符作ؓ了分割符Q结果就多出了一列?/span> 问题原因扑ֈ了,重新写了一下字W串拆分函数Q?/span>SplitQ这里用的Ҏ是:扑ֈ分隔W后Q再向前查找字符看一下它前一个字W是否ؓ东亚文字的第一个字W编码(~码大于0x80Q?/span> 考虑C后支?/span>unicodeQ这里用了模板。以下可能不是最高效单的实现Q但如果以后遇上q种问题Q可以参考一下?/span> #include "stdafx.h" #include <stdio.h> #include <tchar.h> #include <iostream> #include <string> #include <vector> #include <algorithm> #include <fstream> // unicode 分割{略 inline bool __SplitPolicy( const std::wstring& s, const std::wstring& splitchar, std::wstring::size_type& pos) { pos = s.find_first_of(splitchar, pos); return pos != std::string::npos; } // ansi 分割{略 inline bool __SplitPolicy( const std::string& s, const std::string& splitchar, std::string::size_type& pos) { pos = s.find_first_of(splitchar, pos); if (pos != std::string::npos) { // 如果前一个字W的W一位ؓ1Q且当前字符是在东亚文字的第二个字符Q?/span> // 则认字符是东亚字的其中一个字W,要蟩q,不作为分割符?/span> std::string::size_type i = 1; for (; i < pos; ++i) { if (!((char)(s[pos - i]) & 0x80)) // 判断W一位是否ؓ1。(0x80的二q制?10000000Q?/span> break; } if (!(i % 2)) // 看一下当前字W是否ؓ东亚文字的第二个字符 { ++pos; __SplitPolicy(s, splitchar, pos); } } return pos != std::string::npos; } template<typename char_type> inline int Split( const std::basic_string<char_type>& s, const std::basic_string<char_type>& splitchar, std::vector<std::basic_string<char_type> >& vec) { typedef std::basic_string<char_type> string_t; typedef typename string_t::size_type size_t; string_t tmpstr; size_t pos = 0, prev_pos = 0; vec.clear(); while (__SplitPolicy(s, splitchar, pos)) { tmpstr = s.substr(prev_pos, pos - prev_pos); vec.push_back(tmpstr); prev_pos = ++pos; } size_t len = s.length() - prev_pos; if (len > 0) vec.push_back(s.substr(prev_pos, len)); return static_cast<int>(vec.size()); } // ansi版本试 void testSplit() { std::vector<std::string> vec; const std::string str = "AGZGY1000004|200|刘瓅瓅||20100101||OPRT10|1|0||AAGZ0Y100|0|0|24|0|0|0|0||-1|20030101|0|20991231||AGZGK6172888|200|曾晓||20100101||OPRT10|1|0||AAGZ0K617|0|0|24|0|0|0|0||-1|20061215|1|20061215||a"; const std::string sp = "|"; int count = Split(str, sp, vec); for (std::vector<std::string>::const_iterator it = vec.begin(); it != vec.end(); ++it) std::cout << *it << " "; } // unicode版本试 void testSplitW() { std::vector<std::wstring> vec; const std::wstring str = L"AGZGY1000004|200|刘瓅||20100101||OPRT10|1|0||AAGZ0Y100|0|0|24|0|0|0|0||-1|20030101|0|20991231||AGZGK6172888|200|曾晓||20100101||OPRT10|1|0||AAGZ0K617|0|0|24|0|0|0|0||-1|20061215|1|20061215||"; const std::wstring sp = L"|"; Split(str, sp, vec); const char head[3] = {0xff, 0xfe, 0}; const wchar_t line[3] = L" "; // 控制台输Z了unicode字符Q用输出到文g的方?/span> std::ofstream fileOut("C:/out.txt"); fileOut.write(head, 2); for (std::vector<std::wstring>::iterator it = vec.begin(); it != vec.end(); ++it) { fileOut.write((const char*)it->c_str(), it->length() * 2); fileOut.write((const char*)line, 2); } } int main() { testSplit(); testSplitW(); } 1Q?a target="_blank">http://unicode.org/ 2Q?/span>《谈谈Unicode~码Q简要解释UCS、UTF、BMP、BOM{名词?/span>
{
/* 成员函数和成员数?/span> */
};
// . . . 代码
// 分配一个对?/span>
CTest * pTest = new Test;
// 分配一个有十个对象的数l?/span> (CTest 要有~省构造函敎ͼdefault constuctorQ?/span>)
CTest * p10Tests = new Test[ 10];
CTest * pTests = new Test[ 10];
// . . .
// 假设现在我们需?/span>11个对?/span>
CTest * pNewTests = new Test[ 11];
// . . . 我们必须把原来的对象拯到新分配的内存中
for ( int i = 0; i < 10; i++)
pNewTests[ i] = pTests[ i];
delete pTests;
pTests = pNewTests;
// 用方括号[] 括v来的部分是可选的
[CYourClass * pValue = ] new( buffer) CYourClass[( parameters)];
class CTest
{
public:
CTest()
{}
CTest( int)
{}
/* 代码*/
};
int main(int argc, char* argv[])
{
// ׃q个例子的目的,我们不考虑内存寚w问题
char strBuff[ sizeof( CTest) * 10 + 100];
CTest * pBuffer = ( CTest *)strBuff;
// ~省构?/span>
CTest * pFirst = new(pBuffer) CTest;
// ~省构?/span>
CTest * pSecond = new(pBuffer + 1) CTest;
// 带参数的构造;
// 不理会返回的指针
new(pBuffer + 2) CTest( 5);
// 带参数的构?/span>
CTest * pFourth = new( pBuffer + 3) CTest( 10);
// ~省构?/span>
CTest * pFifth = new(pBuffer + 4) CTest();
// 构造多个元素(~省构造)
CTest * pMultipleElements = new(pBuffer + 5) CTest[ 5];
return 0;
}
pSecond->~CTest();
Q:栈上的对?注意,是类对象,charcd无需?后面q会提到)保证攑֜寚w地址?
但是Q个人实验了一下,发现q不是这?br />
例如Q?br />
int main()
{
char c1 = 'A' ;
char c2 = 'B' ;
char c3 = 'C' ;
char c4 = 'D' ;
char c5 = 'E' ;
//-------- 验证q四个地址是否?nbsp;4 的倍数 --------------//
if ( ((int)(&c1)) % 4 == 0 )
cout << "c1:Yes" << endl ;
if ( ((int)(&c2)) % 4 == 0 )
cout << "c2:Yes" << endl ;
if ( ((int)(&c3)) % 4 == 0 )
cout << "c3:Yes" << endl ;
if ( ((int)(&c4)) % 4 == 0 )
cout << "c4:Yes" << endl ;
if ( ((int)(&c5)) % 4 == 0 )
cout << "c5:Yes" << endl ;
cout << (int)(&c1) << endl // 输出四个字符所在的地址Q输出结果都?nbsp;4 的倍数Q?br />
<< (int)(&c2) << endl
<< (int)(&c3) << endl
<< (int)(&c4) << endl
<< (int)(&c5) << endl ;
}
-----------------------------
上面的执行结果在VC下运行都?nbsp;4 的倍数
Q-Q-Q-Q-Q-Q-Q-
--> 问题1Q连栈上分配的空间地址都是 4 的倍数Q那p明系l分配的I间都是 4 的倍数吧?Q?
--> 问题2Q如果万一Q如果放一个对象的地址不是4的倍数Q那么会出现什么情况?Q可以给单说一下吗Q?br />
--> 问题3Q地址寚w的通用性?Q?
Q-Q-Q-Q-Q-Q-Q?br />
E序1Q?br />
Class C1
{
int i ;
char c ;
} ;
cout << sizeof(C1) << endl ;// 输出l果Q?nbsp;8 Q是 4 的倍数Q?br />
E序2Q?br />
class C2
{
char c1 ;
char c2 ;
} ;
cout << sizeof(C2) << endl ;// 输出l果Q? Q?nbsp;上一个中charcd也给?个字节,怎么q个地方都给了一个字节?Q)
--> 问题4Q由上面的程? 引出下面的程?br />
class C2// sizeof(C2) =2 ,在VC实验下的l果Q不?nbsp;4
{
char c1 ;
char c2 ;
} ;
//----------用placement newҎ建立对象----------------
void *ptr = operator new(100) ;// 分配内存
C2 *POINTER = (C2*)ptr ;// cd转换
String *str1 = new (POINTER) C2() ;// 建立一C2对象
String *str2 = new (POINTER+1) C2() ;// 再徏立一个对?br />
String *str3 = new (POINTER+2) C2() ;// 再徏立一个对?br />
cout << (int)(str1) << endl// l果Q?608720Q?nbsp; ?的倍数Q?br />
<< (int)(str2) << endl // l果Q?608722Q不?的倍数Q!Q?br />
<< (int)(str3) << endl ;// l果Q?608724Q不?的倍数Q!Q?br />
]]>概述Q?/font>
问题Q?/font>
原因分析Q?/font>
解决ҎQ?/font>
参考:
]]>
]]>
1、RGBD{灰度值对32位整数取RQGQB对应?位ƈ加权合成?br />
2、求一个字W串中出现频率最高的字符。字W范围ƈ涡有说明Q通常?br />
指ASCII字符集,可是当时考虑复杂了,于是惛_了stl的map来做?br />
l果没有写完。就交了?
*/
#include<iostream>
using namespace std;
#define CHARNUM 256
//计算一个串最出现频率最高的字符
char mostFreq(const char* str)
{
int freq[CHARNUM]= {0};
int firstPos[CHARNUM] = {0};
int pos = 0;
const char* p = str;
while( *p != '\0')
{
if(freq[*p] == 0)
{
firstPos[*p] = pos;
}
freq[*p++]++;
pos++;
}
int maxF = -1;
int ch = '\0';
for(int i = 1;i < 256;i++)
{
if( freq[i] > maxF)
{
ch = i;
maxF = freq[i];
}
if( freq[i] == maxF)
{
if( firstPos[i] < firstPos[ch])
{
ch = i;
}
}
}
cout<<" maxF ="<<maxF<<endl;
return (char)ch;
}
int main()
{
int* a[9][4][5];
int b = a[5] - a[3];
cout<<"b = "<<b<<endl;
int* c[3];
char * str = "aabyebbdfdf 1`5454545$$$#$#$2788kldef";
char ch;
ch = mostFreq( str);
cout<<"ch = " <<ch<<endl;
}
4.l出一个CThing cȝ源代码让分析Q其中有三个语句要求解释语句作用?br />
一个填I,分析时有点忙了,应该一个函C个函数的分析Q或怼有清晰思\?br />
各个类的名U和功能整理下会理出些思\?br />
5、给出strcpy的源代码让说明其功能Qƈ指出参数讄上只一人错?br />
6、给Z个将整数i转换?q制的方法,要求对其q行改进?br />
src:
void count(int i, char* str)
{
map[
sorry, 记忆不清楚了
7、给几个名词让解释placement new,ARM, GCC, android, q有一人?Q?br />
8、英文解释题目。第一个还好。第二个说游戏加速的
increment ...update frame , ??q词词认识,放一赯不出来表CZ?br />
意?
int **p=0;
func(p);
cout<<(**p)<<endl;
int *pV;
pV = new int(2); //q里注意与在cpp中与java中语法的差异
cout<<"PV = "<<(*pV)<<endl;
预编译头文g
今天在改一个很大的E序Q慢慢看Q慢慢改。突然发C?c文gQ里面什么也没有Q?
几个头文gQ我一看,我靠Q这不是把简单的问题搞复杂了吗,随手删掉那个c文g?
l果不能~译了,我靠Q?
fatal error C1083: Cannot open precompiled header file: \'Debug/v13_3.pch\':
No such file or directory
怎么rebuild all都不行?
上网查了一下,才搞懂了Q?
Q-Q-Q-Q-Q-Q-Q-Q-ȝQ-Q-Q-
如果工程很大Q头文g很多Q而有几个头文件又是经常要用的Q那?
1。把q些头文件全部写C个头文g里面去,比如写到preh.h
2。写一个preh.cQ里面只一句话Q?include "preh.h"
3。对于preh.cQ在project setting里面讄creat precompiled headersQ对于其?
.c文gQ设|use precompiled header file
//
哈哈
我试了一下,效果很明显,不用precompiled headerQ编译一ơ我可以M个厕所Q用
precompiled headerQ编译的时候,我可以站h怸懒腰Q活动活动就差不多啦
Q-Q-Q-Q-Q{载的文章Q-Q-Q-Q-Q-
预编译头的概念:
所谓的预编译头是把一个工E中的那一部分代码,预先~译好放在一个文仉(通常?
?pch为扩展名?Q这个文件就UCؓ预编译头文gq些预先~译好的代码可以是Q何的
C/C++代码--------甚至是inline的函敎ͼ但是必须是稳定的Q在工程开发的q程中不?
被经常改变。如果这些代码被修改Q则需要重新编译生成预~译头文件。注意生成预~?
译头文g是很耗时间的。同时你得注意预~译头文仉常很大Q通常?-7M大。注意及
时清理那些没有用的预~译头文件?
也许你会问:现在的编译器都有Time stamp的功能,~译器在~译整个工程的时候,?
只会~译那些l过修改的文Ӟ而不会去~译那些从上ơ编译过Q到现在没有被修改过
的文件。那么ؓ什么还要预~译头文件呢Q答案在q里Q我们知道编译器是以文g为单
位编译的Q一个文件经q修改后Q会重新~译整个文gQ当然在q个文g里包含的所?
头文件中的东西(.eg Macro, Preprocesser Q都要重新处理一遍。VC的预~译头文?
保存的正是这部分信息。以避免每次都要重新处理q些头文件?
预编译头的作用:
Ҏ上文介绍Q预~译头文件的作用当然是提高便宜速度了,有了它你没有必要每次
都编译那些不需要经常改变的代码。编译性能当然提高了?
预编译头的用:
要用预~译_我们必须指定一个头文gQ这个头文g包含我们不会l常改变?
代码和其他的头文Ӟ然后我们用这个头文g来生成一个预~译头文Ӟ.pch文gQ?
惛_大家都知?StdAfx.hq个文g。很多h都认是VC提供的一?#8220;pȝU别”?
Q编译器带的一个头文g。其实不是的Q这个文件可以是M名字的。我们来考察一?
典型的由AppWizard生成的MFC Dialog Based E序的预~译头文件。(因ؓAppWizard
会ؓ我们指定好如何用预~译头文Ӟ默认的是StdAfx.hQ这是VCL名字Q。我?
会发现这个头文g里包含了以下的头文gQ?
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#include <afxdisp.h> // MFC Automation classes
#include <afxdtctl.h> // MFC support for Internet Explorer 4
Common Controls
#include <afxcmn.h>
q些正是使用MFC的必d含的头文Ӟ当然我们不太可能在我们的工程中修改这些头?
件的Q所以说他们是稳定的?
那么我们如何指定它来生成预编译头文g。我们知道一个头文g是不能编译的。所以我
们还需要一个cpp文g来生?pch 文g。这个文仉认的是StdAfx.cpp。在q个文g
里只有一句代码就是:#include “Stdafx.h”。原因是理所当然的,我们仅仅是要它能
够编译而已?D?D?D也就是说Q要的只是它?cpp的扩展名。我们可以用/Yc~译开x?
定StdAfx.cpp来生成一?pch文gQ通过/Fp~译开x指定生成的pch文g的名字。打
开project ->Setting->C/C++ 对话框。把Category指向Precompiled Header。在左边?
树Ş视图里选择整个工程
Project Options(右下角的那个白的地方)可以看到 /Fp “debug/PCH.pch”Q这是?
定生成的.pch文g的名字,默认的通常是 <工程?gt;.pchQ我的示例工E名是PCHQ?
然后Q在左边的树形视N选择StdAfx.cpp.//q时只能选一个cpp文gQ?
q时原来的Project Option变成?Source File OptionQ原来是工程Q现在是一个文?
Q当然变了)。在q里我们可以看到 /Yc开养I/Yc的作用就是指定这个文件来创徏一?
Pch文g?Yc后面的文件名是那个包含了E_代码的头文gQ一个工E里只能有一个文
件的可以有YC开兟뀂VC根据这个选项?StdAfx.cpp~译成一个Obj文g和一个PCH文g
?
然后我们再选择一个其它的文g来看看,//其他cpp文g
在这里,Precomplier 选择?Use ⋯⋯⋯一,头文件是我们指定创徏PCH 文g的stda
fx.h
文g。事实上Q这里是使用工程里的讄Q(如图1Q?Yu”stdafx.h”?
q样Q我们就讄好了预编译头文g。也是_我们可以使用预编译头功能了。以
下是注意事项Q?
1):如果使用?YuQ就是说使用了预~译Q我们在每个.cpp文g的最开_我强调一?
是最开_包含 你指定生pch文g?h文gQ默认是stdafx.hQ不然就会有问题。如
果你没有包含q个文gQ就告诉你Unexpected file end. 如果你不是在最开头包含的Q?
你自p以下q道了Q绝Ҏ很惊人的效果?.
fatal error C1010: unexpected end of file while looking for precompiled
header directive
Generating Code...
2Q如果你把pch文g不小心丢了,~译的时候就会生很多的不正常的行ؓ。根据以?
的分析,你只要让~译器生成一个pch文g。也是说把 stdafx.cppQ即指定/Yc的那?
cpp文gQ从新编译一遍。当然你可以d?Rebuild All。简单一点就是选择那个cpp
文gQ按一下Ctrl + F7可以了。不然可是很费旉的哦?
//
呵呵Q如果你居然耐着性子看到了这里,那么再回到帖子最开始看看我的ȝ吧!
W一?Windows的编E模?/a> | W二?MFC应用E序框架 |
W三?消息映射和视囄 | W四?资源和编?/a> |
W五?基本事g处理 | W六?映射模式 |
W七?滚动视窗 | W八?C֤环境c?/a> |
W九?GDI对象 | W十?windows颜色映射 |
![]() |
W二?MFC应用E序框架
?MFC是C++的Microsoft Windows API
?MFC产生的应用程序用了标准化的l构?br />
?MFC产生的应用程序短而运行速度快?br />
?VCQ+工具降低了编码的复杂性,q当然了Q很多代码都由它代劳了,呵呵?br />
?MFC库应用程序框架的功能非常丰富?br />
以上说的都是MFC库的优点Q虽然说MFC有着q样多的优点Q但我个Z能盲目的学习它,要想学好Q那么您必须先掌握C++Q这是毋庸置疑的。可能刚开始的时候,您觉得收获很大,也很有趣Q但要进一步提高,没有C++基础是很隄。所以站长徏议大家学习的时候要有先有后Q这h能学好!
应用E序框架是一U类库的集?br />
我们现在先来看一个例子,看看MFC有多么强大!您只需加一行代码,甚至一行都不用加只需要点几下鼠标可以创Z个windows E序Q不信,试一下:
1、打开VC++6从菜单选择NEWQ给目命名?MyApp "?br />
2、选择MFC AppWizard[exe] 选项Q除STEP 1选择单文档外其他STEP~省?br />
3、在Class View选择CMyAppViewcȝOnDraw()成员函数双击会在C++~译器看C下内?/font>
void CMyAppView::OnDraw(CDC* pDC)
{
CMyAppDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
?// TODO: add draw code for native data here的位|增加一行代?br />
void CMyAppView::OnDraw(CDC* pDC)
{
CMyAppDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
pDC->TextOut(10,10,"愿vc在线能成为您学习vc最好的朋友Q?); //增加的一?br />
// TODO: add draw code for native data here
}
完了Q就q么单。编译运行。看C吗?q个E序具备WINDOWSE序的所有特性,例如有菜单、工h、状态栏、最大化、关闭、甚臌有关于对话框、打印预?....全了Q这是AppWizard通过MFC动态创建的一个应用程序。从q个例子可以看出用VC/MFC设计WINDOWSE序多么方便?/font>
下面我们看看书上的例子,以便更进一步了解应用程序框架?br />
1、先建立一个Win32 Application的应用程序?br />
2、选择Project->Add to project->Files,分别创徏一个名为MyApp.h和一个名为MyApp.cpp的文件?br />
3、添加代码:Q最好照敲一下代码到~译器,别用Ctrl+C/Ctrl+VQ?br />
//***********************************************
// MyApp.h
//
class CMyApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
class CMyFrame:public CFrameWnd
{
public:
CMyFrame();
protected:
afx_msg void OnLButtonDown(UINT nFlags,CPoint point);
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
};
//*****************************************************
// MyApp.cpp
//
#include "afxwin.h"
#include "myapp.h"
CMyApp theApp;//建立一个CMyAPP对象
BOOL CMyApp::InitInstance ()
{
m_pMainWnd=new CMyFrame();
m_pMainWnd->ShowWindow (m_nCmdShow);
m_pMainWnd->UpdateWindow ();
return TRUE;
}
BEGIN_MESSAGE_MAP(CMyFrame,CFrameWnd)
ON_WM_LBUTTONDOWN()
ON_WM_PAINT()
END_MESSAGE_MAP()
CMyFrame::CMyFrame(){
Create(NULL,"MYAPP Application");
}
void CMyFrame::OnLButtonDown (UINT nFlags,CPoint point)
{
TRACE("Entering CMyFrame::OnLButtonDown - %lx,%d,%d\n",
(long)nFlags,point.x ,point.y);
}
void CMyFrame::OnPaint ()
{
CPaintDC dc(this);
dc.TextOut (0,0,"Hello World!");
}
4、编译运行,报错。ؓ什么呢Q原来还没有dMFC的支持,在Project Setting选项General属性页选择"Use MFC in a Static Library"
5、再按Ctrl+F5Q怎么P单吧Q?br />
让我们看看这个程序中的一些元素?br />
①WinMain函数QWindowsL要求每个应用E序都要有WinMain函数的,您之所以看不见Q是因ؓ它已l隐藏在应用E序框架内部了?br />
②CMyAppc:CMyAppcȝ对象代表一个应用程序,CWinApp基类军_它的大部分行为?br />
③应用程序的启动Q当开始运行应用程序时WINDOWS会调用WinMain函数QWinMain会查找该应用E序的全局对象theApp?br />
④CMyApp::InitInstance成员函数Q发现theApp后自动调用重载的虚函数InitInstance来完成主H口的构造和昄工作?br />
⑤CWinApp::Run成员函数QWinMain在调用InitInstance之后紧接着调用Run函数Q它被隐藏在基类中负责传递应用程序的消息l相映的H口?br />
⑥CMyFramec:此类的对象代表着应用E序的主H口。它的构造函数调用基cCFrameWnd的Create函数创徏具体的窗口结构?br />
⑦CMyFrame::OnLButtonDown函数Q演C消息处理机Ӟ当鼠标坐键被按下q一事g被映到CMyFrame的OnLButtonDown函数上,如果你选择F5q行~译q行的话可以在调试窗口看到TRACE宏显C的cM下面的信?br />
Entering CMyFrame::OnLButtonDown - 1,309,119
Entering CMyFrame::OnLButtonDown - 1,408,221
⑧CMyFrame::OnPaint函数Q应用程序每ơ重新绘制窗口都需要调用此函数Q将昄"Hello World!"攑֜q里是因为每ơ窗口发生变化时保证"Hello World!"被显C,你可以试着语句:
CPaintDC dc(this);
dc.TextOut (0,0,"Hello World!");
写在别出Q例如写?br />
void CMyFrame::OnLButtonDown (UINT nFlags,CPoint point)
{
TRACE("Entering CMyFrame::OnLButtonDown - %lx,%d,%d\n",
(long)nFlags,point.x ,point.y);
CPaintDC dc(this);
dc.TextOut (0,0,"Hello World!");
}
q行后当点击左键时显C?Hello World!"Q但当窗口最化再最大化?Hello World!"不见了?br />
⑧关闭应用程序:用户关闭应用E序时会有一pd事g发生。首先CMyFrame对象被删除,然后退出RunQ进而退出WinMainQ最后删除CMyApp对象?br />
通过上面的示例我们看见程序的大部分功能包含在基类CWinApp和CFrameWnd中,我们只写了很的函数Q便可以完成很复杂的功能。所以应用程序框架不仅仅是一U类库,它还定义了应用程序的l构Q除了基cdq包括WinMain函数Q以及用来支持消息处理、诊断、DLL、等都包含在应用E序框架中?
![]() |
W三?消息映射和视囄
MFC库应用程序框架没有采用虚函数来处理windows消息Q而是通过宏将消息映射到派生类相应的成员函C。文档-视图l构是应用程序框架的核心Q它把数据从用户Ҏ据的观察中分d来,q样做最大的好处是同一个数据可以对应多个视图。比如同一个股报h据,既可以有报表观察H口Q也可以有图形观察窗口,明白了否Q?br />
视图单来说就是一个普通的H口Q对于程序员来说是一个从MFC库中CviewcL生出来的cȝ一个对象。视囄分ؓ两个源文件模块:头文ӞHQ和源代码文ӞCPPQ?br />
用Appwizard创徏一个SDI应用E序Q生了如下文gQ假讑ַE名为Exc01Q:
Exc01.dsp 目文gQVisual Studio用它来创建应用程?br />
Exc01.dsw 工作I间文gQ包含一个项目Exc01.dsp
Exc01.rc ASCII码资源描q文?br />
Exc01View.cpp 包含CExc01ViewcL员函数和视图cL?br />
Exc01View.h 包含CExc01Viewcd义的视图cd文g
Exc01.opt 二进制文Ӟ告诉Developer Studio本项目的哪些文g是打开的,又是如何排序?br />
Readme.txt 用来解释所产生的所有文件的文本文g
Resource.h 包含#define帔R定义的头文g
从Exc01View.cpp和Exc01View.h的代码中可以看出Q这两个文g已经完全定义了CExc01Viewc,而该cL是此应用E序的核心。CExc01Viewcȝ对象与应用程序的视窗相关联,应用E序的所?动作"都会在这个视H中昄出来?br />
CExc01Viewcȝ两个最重要的基cLCWnd和CViewcRCWndcL供了CExc01View的窗口属性,而CViewcd提供了它和应用程序框架的其它部分之间的联p,特别是和文档以及框架H口之间的联pR这一点一定要C?br />
下面我们来看一下如何在视窗内绘图。最重要的一个函数是OnDraw()函数Q它是一个虚函数Q每ơ窗口被重画Ӟ应用E序都要先调用这个函数。注意:管可以随时对窗口绘Ӟ但最好还是等变化内容U篏C定程度后再教lOnDraw()函数处理Q这h率会高一些?br />
在MFC中,讑֤环境是由C++的CDCcd象来表示的,该对象被作ؓ参数传给Ondraw()函数Q这P我们可以调用CDC的许多成员函数来完成各种l制了?br />
扑ֈOnDraw()函数Q用以下语句替换函数原来的内容:
pDC->TextOut( 0, 0, "Hello World!" );
pDC->Ellipse(CRect(0,20,100,120));
再编译运行,看到了什么?
TextOut和Ellipse都是讑֤环境cCDC的成员函敎ͼMFC库提供了一个用来表Cwindows矩Ş的类CRectQ在q里CRect的一个时对象被作ؓ参数传递给 了Ellipse函数Q当外接矩Ş的宽和高相等ӞEllipse函数qZ圆?
![]() |
W四?资源和编?/strong>
资源文gQ就是以应用E序名和扩展名是.rc的文Ӟ很大E度上决定了应用E序的用L面。在VC++中资源文件包括以下内容:
Accelerator //模拟菜单和工h选择的键盘定?
Dialog //对话框的布局及内?
Icon //图标有两U一U是16X16一U是32X32?
Menu //应用E序的主菜单及所属的弹出式菜?
String table //一些字W串Q不属于C++源代码部?
Toolbar //工具条?
Version //E序的描q、版本号、支持语a信息?
除了以上信息Q?rc文gq包含了以下语句Q?#include "afxres.h" #include "afxres.rc" 它们的作用是把适合于所有应用程序的一些通用MFC库资源包含进来,其中包括字符丌Ӏ图形按钮以及打印所需的一些元素?
关于资源~辑器的使用׃多说了,因ؓ它的操作很简单,需要注意的是虽然resource.h是一个ASCII码文件可以用文本~辑器进行编辑,但如果用文本编辑器q行~辑的话Q下ơ再使用资源~辑器时所做的修改有可能丢失,所以我们应该在量在资源编辑器中编辑应用程序的资源Q新增的资源内容回自动的d在我们的E序相应位置Q例如resource.h而不用我们操心?
~译在VC++中有两种模式Q一U是Release Build另一U是Debug Build。它们之间的区别在于QRelease Build不对源代码进行调试,不考虑MFC的诊断宏Q用的是MFC Release库,~译十对应用E序的速度q行优化Q而Debug Build则正好相反,它允许对源代码进行调试,可以定义和用MFC的诊断宏Q采用MFC Debug库,寚w度没有优化。所以我们应该在Debug模式下开发应用程序,然后在Release模式下发布应用程序。在我们的工E文件夹下会有一个Debug文g夹和一个Release文g夹分别存放输出文件和中间文g?
诊断宏是我们~译E序时检程序状态的有利工具Q例如上两篇用到的TRACE宏,可以在DebugH口获得你需要的诊断信息Q而不用设|对话框之类的方法,在发布时Release会自动o掉此信息?
Z更好的管理项目,最好理解系l是如何处理预编译头文g的。VCQ+有两个预~译pȝQ自动的和手工的。这一部分W者就不多说了Q徏议读者好好看看?
![]() |
MFC库对140Uwindows消息直接提供了消息控制函敎ͼq且我们q可以自己定义自q消息Q下面列出的五种消息是我们应该特别注意的QMSDN上有更详l的内容Q?br />
WM_CREATE
该消息是Windows发给视图的第一个消息。当应用E序框架调用create函数时该消息便会被发送,此时H口q未创徏完成Q不可见Q因此在消息控制函数OnCreate内不能调用那些依赖窗口处于完全激zȝ态的Windows函数。如果需要可以在重蝲的OnInitialUpdate函数内调用。不q注意在SDI应用E序OnInitialUpdate函数可能被多ơ调用?br />
WM_CLOSE
当用户关闭窗口时Q系l会发送WM_CLOSE消息。如果派生类重新定义了OnClose函数Q就可以完全控制关闭q程Q可以将提醒用户存盘之类的工作放在这里完成。我们可以通过重蝲CDocument::SaveModified虚函数达到相同的目的?br />
WM_QUERYENDSESSION
从字面的意思看可以看出,当用户退出WindowsӞ或者调用了ExitWindows 函数时。Windows会发送WM_QUERYENDSESSION消息l所有的正在q行的应用程序,由OnQueryEndSession消息映射函数Ҏ息进行处理。在它之后应该是WM_ENDSESSION 消息?br />
WM_DESTROY
在Windows发送WM_CLOSE消息后,紧接着会发送WM_DESTROY消息Q虽然窗口已lClose但实际上q没有完全清除,在Q务管理器中还可以看见应用E序的进E(我想很多木马或病毒都是无H口的程序,它们的做法是生成了已l活动状态的H口但不昄出来Q,利用q个消息控制函数便可以对依赖于当前窗口存在的东西做清除工作,不过一定要注意Q应该调用基cȝOnDestroy函数Q而不能在用户自己的视囄OnDestroy函数中终止窗口的析构q程Q终止析构过E应该在OnClose函数中?br />
WM_NCDESTROY
当窗口被取消所发送的最后一个消息就是这个消息。我们可以在OnNcDestroy函数中做一些不依赖该窗口是否处于活动状态的最后的处理工作Q(我实在想不出q需要做什么?那位朋友能给个例子)Q注意一定要调用基类中的OnNcDestroy函数?/p>
MFC库中非静态数据成员的名字以m_为前~?br /> 一个窗口具有一个矩形的"客户区域"QCWnd中的GetClient成员函数可以l出客户区域的大,只允许在客户区域内绘图?br /> 标准的windows应用E序会首先登C个窗口类Q这不同于C++c,同时在处理过E中Q还需要对每个cL定窗口过E。每ơ应用程序调用CreateWindow建立一个窗口时Q都要指定一个窗口类作ؓ参数Q这样就把新建立的窗口和H口q程函数q接h了,每次windowsl窗口发送消息的时候,q个函数׃被调用,以检查用参数传进来的消息码?br />
![]() |
映射模式 | 逻辑单位 |
MM_LOENGLISH | 0.01英寸 |
MM_HIENGLISH | 0.001英寸 |
MM_LOMETRIC | 0.1mm |
MM_HIMETRIC | 0.01mm |
MM_TWIPS | 1/1440英寸 |
![]() |
CSize sizeTotal( 20000, 30000 ); //逻辑H口大小20×30cm
CSize sizePage( sizeTotal.cx/2, sizeTotal.cy/2 );
CSize sizeLine( sizeTotal.cx/50, sizeTotal.cy/50 );
SetScrollSizes( MM_HIMETRIC, sizeTotal, sizePage, sizeLine );
}
4?用ClassWizard产生Ҏ息WM_KEYDOW控制的OnKeyDown函数Qƈ~辑代码如下Q?br />
void CAView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
switch( cChar ){
case VK_HOME:
OnVScroll( SB_TOP, 0, NULL );
OnHScroll( SB_LEFT, 0, NULL );
break;
case VK_END:
OnVScroll( SB_BOTTOM, 0, NULL );
OnHScroll( SB_RIGHT, 0, NULL );
break;
case VK_UP:
OnVScroll( SB_LINEUP, 0, NULL );
break;
case VK_DOWN:
OnVScroll( SB_LINEDOWN, 0, NULL );
break;
case VK_PRIOR:
OnVScroll( SB_PAGEUP, 0, NULL );
break;
case VK_NEXT:
OnVScroll( SB_PAGEDOWN, 0, NULL );
break;
case VK_LEFT:
OnHScroll( SB_LINELEFT, 0, NULL );
break;
case VK_RIGHT( SB_LINERIGHT, 0, NULL );
break;
default:
break;
}
?br />
5?~辑构造函数和OnDraw函数如下Q?br />
CAView::CAView():m_rectEllipse( 0, 0, 4000, -4000 )
{
// TODO: add construction code here
m_nColor = GRAY_BRUSH;
}
…
void CAView::OnDraw(CDC* pDC)
{
pDC->SelectStockObject( m_nColor );
pDC->Ellipse( m_rectEllipse );
}
6?映射WM_LBUTTONDOWN消息q编辑消息处理函数OnLButtonDown如下Q?br />
void CAView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc( this );
OnPrepareDC( &dc );
CRect rectDevice = m_rectEllipse;
dc.LPtoDP( rectDevice );
if( rectDevice.PtInRect( point ) ){
if( m_nColor = GRAY_BRUSH )
m_nColor = WHITE_BRUSH;
else
m_nColor = GRAY_BRUSH;
}
InvalidateRect( rectDevice );
}
~译q运行看看结果吧?br />
另外Q我们要特别注意下面五种比较Ҏ的windows消息Q?br />
1?WM_CREATE消息
该消息是windows发给视图的第一个消息,׃应用E序框架调用Create函数时该消息׃被发送,而此时窗口创未完成,因此在Create函数内不能调用那些依赖于H口处于完全Ȁzȝ态的windows函数。不q对于SDI应用E序Q在视图生存期间QOnInitialUpdate函数可以被调用多ơ?br />
2?WM_CLOSE消息
当用户从pȝ菜单中关闭窗口或者父H口被关闭时Qwindows会发送WM_CLOSE消息?br />
3?WM_QUERYENDSESSION消息
当用户退出windowsӞwindows׃发送WM_QUERYENDSESSION消息l正在运行的E序Q处理这个消息的映射函数为OnQueryEndSession?br />
4?WM_DESTROY消息
Windows在发送完WM_CLOSE消息后,紧接着发送WM_DESTROY消息Q消息映函CؓOnDestroy。当E序接收到该消息Ӟ它将假定此时视窗已经消失Q但仍处于活动状态。利用这个消息控制函敎ͼ可以对依赖于当前窗口的所有东西作清除工作Q不q一定要CQ应该用基类的OnDestroy而不能在自己视图中的OnDestroy?l止"H口的析构过E,l止析构的处理应该在OnClose函数中?br />
5?WM_NCDESTROY消息
当窗口被取消时发送的最后一个消息就是这个消息,׃此时所有的H口都被关闭Q所以我们可以在OnNcDestroy函数中做一些不依赖于窗口是否处于激zȝ态的最后处理工作,不过一定要调用基类的OnNcDestroy函数。不要在OnNcDestroy中取消动态申LH口对象Q这一工作是由CWnd的一个特D虚函数PostNcDestroy来完成的Q它是由基类的OnNcDestroy来调用的。何时取消窗口对象最为合适呢Q去看MFC的联机文档吧Q?br />
![]() |
ME序在画图时都需要调用图形设备接口( GDI Q函敎ͼ GDI 包含了一些绘制点、线、矩形、椭圆、位图以及文本的函数?Windows 的设备环境是 GDI 的关键元素,它代表了物理讑֤Q每一?C++ 讑֤环境对象都有与之对应?Windows 讑֤环境Qƈ通过一?32 位的 HDC 句柄来标识?
MFC 中的基类 CDC 包含了绘图所需要的所有成员函敎ͼq且除了 CMetaFileDC cdQ所有的zc都只有构造函数和析构函数不同。对于显C器来说Q常用的zcL CClientDC ?CWindowDC ?
昄讑֤环境的类 CClientDC ?CWindowDC Q?CClientDC cȝ囑֏局限于客户区域内,即不包含Ҏ、菜单栏和标题栏Q?CWindowDC cd以。简单来_如果创徏 CclientDC 对象Q点Q?0,0 Q指客户区域的左上角Q如果创建的?CWindowDC 对象Q则点( 0,0 Q指整个屏幕的左上角?
在创?CDC 对象的时候,不要忘记在合适的时候将它删除,不然E序在退Z前有部分内存就会丢失。要保证讑֤环境对象能够被适时的删除,可以有两U方法:
一U是在堆栈中构造对象,比如?OnLButtonDown 函数中,它的析构函数在函数返回时自动被调用?
void CMyView::OnLButtonDown(UINT nFlags,CPoint point){
CRect rect;
CClientDC dc(this); //constructs dc on the stack
…
} //dc automatically destroyed
另一U是通过调用 CWnd 的成员函?GetDC 来获得设备环境指针,但此时必要调用 RleaseDC 来释放设备环境?
void CMyView::OnLButtonDown(UINT nFlags,CPoint point){
CRect rect;
CDC *pDC=GetDC();
pDC->GetClipBox(rect);
ReleaseDC(pDC); // 不要忘了q句
}
注意Q千万不要删除作为参C指针形式传递给 OnDraw 函数?CDC 对象Q应用程序框架会自动控制它的删除?
在绘图时我们M开讑֤环境Q那么在l图时我们就要依赖于讑֤环境的当前状态,q种状态包括:
• 被选中?GDI l图对象Q如W、刷子和字体{?
• l图时的~放寸的映模?
• 其他各种l节Q如文本的对齐方式,多边形的填充状?
创徏讑֤环境对象Ӟ通常会有些默认的Ҏ,而其他特性都是通过 CDC cȝ成员函数来设定的Q可以通过重蝲 SelectObject 函数来将 GDI 对象选进讑֤环境中?
如果我们要重新编?OnPaint 函数Q就需要?CPaintDC c,q个cL比较Ҏ的,它的构造函数和析构函数所完成的工作都是针ҎC用的,当我们一旦获得一?CDC 指针Q就可以把它当成M讑֤环境指针来用?/font>![]() |
所?GDI 对象c都是由抽象基类 CGdiObject z出来的。下面是 GDI zcd表:
CBitmap Q?位图是一U位矩阵Q每一个显C像素都对应一个或多个位,我们可以用位图来表示囑փQ也可以用它来创建刷子?
CBrush Q?刷子定义了一U位囑Ş式的像素Q用它可以对区域内部填充颜色?
CFont Q?字体是一U具有某U风格和寸的所有字W的集合?
CPalette Q?调色板是一U颜色映接口?
CPen Q?W是一U画U和有ŞҎ的工P可以指定ȝ的宽度,以及画虚U,实线{?
CRgn Q?区域是一U范_可以用它来填充、裁剪以及鼠标点中测试?
我们只需要构?CGdiObject cȝzcd象,而无需构造它的对象,有些 GDI zcd许构造函C步完成创建对象的dQ如 CPen ?CBrush 。而有些派生类的对象要两步Q如 CFont ?CRgn Q首先要调用默认的构造函敎ͼ然后q要调用相应的创建函敎ͼ?CreateFont ?CreatePolygonRgn {?
CGdiObject cL一个虚析构函数Q如果构造了一个它的派生类的对象,则在E序退Z前要其删除Qؓ了删除它Q要先将其从讑֤环境中分d来。那么如何分dQ其实, CDC cȝ SelectObject 成员函数在将 GDI 对象选进讑֤环境的同Ӟ它已l从讑֤环境中分d来了Q但在未选中新的对象前,q不能将旧的对象分离。所以在选进自己?GDI 对象Ӟ原来的 GDI 对象也保存v来,d完成后,再将其恢复,q样可以将自己?GDI 对象分离q删除了。下面看一个例子:
void CMyView::OnDraw( CDC *pDC ){
CPen newPen( PS_DASHDOTDOT, 2, (COLORREF)0); //black 2 pixels wide
CPen * pOldPen = pDC->SelectObject( &newPen );
pDC->MoveTo( 10, 10 );
pDC->LineTo( 110, 10 );
pDC->SelectObject( pOldPen ); //newPen 被分?
} //newPen 在函数退出时自动删除
对于一些库存的 GDI 对象Q由于它们是 windows pȝ的一部分Q因此我没有必要删除它们?MFC 库函?SelectStockObject 可以一个库存对象选进讑֤环境中,q返回原先被选中对象的指针,同时使该对象被分R在上例中,我们可以用库存对象代替“?#8221;对象Q?
void CMyView::OnDraw( CDC *pDC ){
CPen newPen( PS_DASHDOTDOT, 2, (COLORREF)0); //black 2 pixels wide
pDC->MoveTo( 10, 10 );
pDC->LineTo( 110, 10 );
pDC->SelectStockObject( BLACK_PEN ); //newPen 被分?
} //newPen 在函数退出时自动删除
对于昄讑֤环境来说Q在每个消息控制函数的入口处Q设备环境都是未被初始化的,因此每次都必M头开始设|设备环境,׃ SelectObject q回?GDI 对象指针的时性,而应用程序框架在函数q回时会删除 C++ 临时对象指针Q所以不能简单地设备环境指针保存在cȝ数据成员中,而要借助?GetSafeHandle 成员函数来将它{换ؓ windows 句柄Q唯一能够持久存在?GDI 标识Q?
注意Q当删除?SelectObject q回的指针所指向的对象时Q一定要当心Q如果该对象是我们自qLQ可以删除,如果是时的Q则不能随便删除?
1Qfatal error C1010: unexpected end of file while looking for precompiled header directive该如何解?
如果发生错误的文件是由其他的C代码文gdq入当前工程而引LQ则Alt+F7q入当前工程的SettingsQ选择C/C++选项卡,从Categoryl合框中选中Precompiled HeadersQ选择Not Using Precompiled headers。确? 如果发生错误的文件原本是该工E中的,则检查该文g头部有没?include "stdafx.h"语句Q没有的话添加? 如果q不行,也有可能是定义的cLl构体等最后忘了加分号Q注意一下? 2Qfatal error RC1015: cannot open include file ’afxres.h’.该如何解? #include "afxres.h"语句是在.rc文g中的Q而afxres.h文g在VC的安装目录中?\VC98\MFC\INCLUDE目录中,所以着重查一下Tools菜单中Options对话框中的Directories中的包括文g的\径是否正,是否在VC的安装\径中Q不是的话,改过来,如果q方面没问题Q则到其他机器中拯afxres.h到相应的目录? 3QDll分配的内存块,应用E序释放Q结果报异常? 用GlobalAlloc()代替new, 用GlobalFree() 代替delete׃会出错了 其实q有一个办法,是把dll的Settings的C/C++选项卡的Code Generation的Use Run-time liberaryҎDebug Multithreaded DLLQ在Release版本中改成Multithreaded DLLQ就可以直接使用new和delete了,没问? 比较规范点的做法一般是DLL分配的内存由DLL释放。在DLL中加一个函数释攑ֆ存不是更好吗? 4Q发现打印预览的囑Ş明显比屏q显C图形小Q怎么办? q多半是CDC映射模式的选择引v的,~省状态下Q选择的是MM_TEXT模式QMM_TEXT以设备的像素点ؓ单位Q而不同设备的像素点的大小不同Q打印机的分辨率比显C器要高很多Q所以导致同样图形在打印时候变。解决之道是l一使用其他定长的映模式,比如MM_HIMETRIC{等QCDC::SetMapMode()改变映射模式Q? 5QCString、char*、string、int、_bstr_t、CTime、COleDateTime{等的相互{换,如何判断一个字W串是一个QҎQ? #include<string> using namespace std; #include <COMDEF.H> { CString strCString="ABC"; char strchar[256],*pstr; pstr=(LPSTR)(LPCTSTR)strCString; //CString---->char* strcpy(strchar,(LPSTR)(LPCTSTR)strCString); //CString---->char[] _bstr_t strbstr=pstr; //char*---->_bstr_t WCHAR *strWCHAR=strbstr; //b_str_t--->UNICODE strbstr=strWCHAR; pstr=strbstr; //UNICODE---->char* strCString="10"; int istr=atoi((LPSTR)(LPCTSTR)strCString); //CString、char[]、char*------>int strCString.Format("%d",istr); //int----->CString sprintf(strchar,"%d",istr); //int----->char[] pstr=new char[256]; //字符串申L? strcpy(pstr,"ABC"); //字符串赋? delete []pstr; //字符串释? string strstring="ABC"; pstr=(char*)strstring.c_str(); //string---->char* strCString="2003-10-27 6:24:37"; //CString--->COleDateTime COleVariant vtime(strCString); vtime.ChangeType(VT_DATE); COleDateTime time4=vtime; COleDateTime time1(1977,4,16,2,2,2); //COleDataTime--->CTime SYSTEMTIME systime; VariantTimeToSystemTime(time1, &systime); CTime tm(systime); time_t time2=tm.GetTime(); //CTime--->time_t COleDateTime time3(time2); //time_t--->COleDateTime //判断字符串是否是某种cd CString sValue("123.1"); COleVariant vValue(sValue); BOOL bStrIsFloat = (SUCCEEDED(VariantChangeType(&vValue, &vValue, 0, VT_R8)) && sValue.Find(’.’) != -1); if(bStrIsFloat) { AfxMessageBox("点"); } } 6Q如何徏立一个UNICODE应用E序Q? 建立一个应用程序,打开Alt+F7 settings选项Q选择C/C++选项卡,在Preprocessor definenation中加上_UNICODEQ在Link选项卡中Q在Category选择框中选择OutputQ在Entry-point symbol~辑框中Q添加wWinMainCRTStartup定? 注意调试UNICODEE序Ӟ需要在安装时VC选择所有选项Q否则会~少动态库和相应的.lib文g 7QADO操作数据库表Q更新出现问? 在打开数据库前Q添加如下语句试一下pRecordSet->CursorLocation = adUseClient |