VC常见入门问题总结1

1:fatal error C1010: unexpected end of file while looking for precompiled header directive该如何解决
    如果发生错误的文件是由其他的C代码文件添加进入当前工程而引起的,则Alt+F7进入当前工程的Settings,选择C/C++选项卡,从Category组合框中选中Precompiled Headers,选择Not Using Precompiled headers。确定
    如果发生错误的文件原本是该工程中的,则检查该文件头部有没有#include "stdafx.h"语句,没有的话添加。
    如果还不行,也有可能是定义的类或结构体等最后忘了加分号,注意一下。
2:fatal error RC1015: cannot open include file 'afxres.h'.该如何解决
    #include "afxres.h"语句是在.rc文件中的,而afxres.h文件在VC的安装目录中的./VC98/MFC/INCLUDE目录中,所以着重查一下Tools菜单中Options对话框中的Directories中的包括文件的路径是否正确,是否在VC的安装路径中,不是的话,改过来,如果这方面没问题,则到其他机器中拷贝afxres.h到相应的目录中
3:Dll分配的内存块,应用程序释放,结果报异常。
    用GlobalAlloc()代替new, 用GlobalFree() 代替delete就不会出错了
    其实还有一个办法,就是把dll的Settings的C/C++选项卡的Code Generation的Use Run-time liberary改成Debug Multithreaded DLL,在Release版本中改成Multithreaded DLL,就可以直接使用new和delete了,没问题
    比较规范点的做法一般是DLL分配的内存由DLL释放。在DLL中加一个函数释放内存不是更好吗。
4:发现打印预览的图形明显比屏幕显示图形小,怎么办?
    这多半是CDC映射模式的选择引起的,缺省状态下,选择的是MM_TEXT模式,MM_TEXT以设备的像素点为单位,而不同设备的像素点的大小不同,打印机的分辨率比显示器要高很多,所以导致同样图形在打印时候变小。解决之道是统一使用其他定长的映射模式,比如MM_HIMETRIC等等(CDC::SetMapMode()改变映射模式)
5:CString、char*、string、int、_bstr_t、CTime、COleDateTime等等的相互转换,如何判断一个字符串是一个浮点数?

#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]; //字符串申请空间
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

//判断字符串是否是某种类型
CString sValue("123.1");
COleVariant vValue(sValue);

BOOL bStrIsFloat = (SUCCEEDED(VariantChangeType(&vValue, &vValue, 0, VT_R8)) && sValue.Find('.') != -1);
if(bStrIsFloat)
{
AfxMessageBox("浮点");
}
}

6:如何建立一个UNICODE应用程序?

建立一个应用程序,打开Alt+F7 settings选项,选择C/C++选项卡,在Preprocessor definenation中加上_UNICODE,在Link选项卡中,在Category选择框中选择Output,在Entry-point symbol编辑框中,添加wWinMainCRTStartup确定。

注意调试UNICODE程序时,需要在安装时VC选择所有选项,否则会缺少动态库和相应的.lib文件


7:ADO操作数据库表,更新出现问题
在打开数据库前,添加如下语句试一下pRecordSet->CursorLocation = adUseClient;

IntefOptics.lib(IntefOptics.dll) : error LNK2005: "public: bool __thiscall CIntvnOptics::NewtonRingsCreate(int,double,int,int,int,int)" (?NewtonRingsCreate@CIntvnOptics@@QAE_NHNHHHH@Z) already defined in IntvnOptics.obj

这类错误是什么导致? 不要说rebuild all, 因为我已经做了不下百次了
LIB里面有和IntvnOptics.cpp里面一样的函数实现。估计你在编译库的时候将NewtonRingsCreate的实现写在头文件里面,然后你使用库的那个CPP文件include了那个头文件。
ll.h
//
void func()
{
//...
}
ll.cpp
#include "ll.h"
以上两个文件编译成lib,使用库的时候
ul.cpp
#include "ll.h"
这时候ul里面也连接了func,lib里面也有func。
解决方法:
1、实现放到CPP里面
或者
2、使用inline修饰
inline void func()
{
//...
}
大家分享一下如何用MFC做实际项目的经验
希望大家一起分享一下如何用MFC做实际项目的经验,中秋凑个热闹。呵呵。
1、界面风格和控件
2、消息循环、多线程、数据库相关
3、数据结构和算法相关
4、其他

初学MFC的时候,大家最先接触的就是界面吧。
虽然说界面不是特别重要,但确实让人头痛。
弄来弄去,大多是控件搞不定。(在这个版这样的问题好多:))
至于消息循环机制,我觉得我们用到不多。
MFC都帮我们做好了。不过有一些注意事项。
上一次我做多线程的时候死锁了,阿行大哥就是用消息机制帮我解决的。
另外,rtdb大哥还赠了我1000分,使我能够继续提问。(太感谢了)
这个版好心人不少。感谢之余,我在这里也和大家分享一下。

1、
刚开始的时候,为了把界面做得好看,
我在www.codeproject.com和www.codeguru.com上面找到了一些好用的控件。
如ButtonST、TruecolorToolbar、GradientProgressCtrl、CoolToolbar等
控件。可能大家也用过。它们都很好用,而且有演示程序下载,边学边用,
用对比法和增减法,这两个方法学MFC挺管用的。
后来在www.vkbase.com看到了一个换肤的ActiveX控件,很好用。
做出来的界面特好看。大家去下载看看。
可惜对组合框等控件支持不够。(可能是小弟不会:))

后来做数据库的时候,我公司的高手说选择越简单的控件越好。
我刚开始用DataGrid,直接绑定数据库。
他们建议用原始的Grid控件,独立于具体的数据库。
Grid控件没有(也不需要!)编辑和组合框支持。编辑的时候跳出对话框来解决。

现在我做的一个项目的界面是单文档多个formview切换。(这个界面挺古老的吧)
曾经用过属性页控件,现在用了Tab控件和对话框嵌入,感觉这个挺好的。

遇到控件问题的时候,我常看msdn,上面的实例真好。
现在有问题来msdn,我都是先搜索一下,其实大多数问题都已经有帖子解答。
这样可以节省自己和别人的时间。
记住每个控件都是一个窗口是有帮助的。

2、
多线程的时候尤其要注意一个问题:MFC帮我们开的线程是界面线程。
如果我们以后再开的线程是工作者线程,那么界面主线程不能阻塞。
如果界面主线程阻塞了,相当于消息泵阻塞了。
我上次犯的错误就是让其他工作者线程发一个消息来让主线程解除阻塞。结果死锁。
解决方法是将其他线程改为界面线程。
还有一个问题,创建新线程的时候要小心,它有一个CRuntimeClass*的参数。
它要CreateObject()创建一个新的线程,然后把线程指针返回。
CSerialPortEx* g_pPort = new CSerialPortEx;
CRuntimeClass* IOClass  = g_pPort->GetRuntimeClass();
g_pPort = (CSerialPortEx*)AfxBeginThread(IOClass);
上面的代码将使g_pPort无法访问CSerialPortEx内部的变量。
通过增加一个临时变量来解决。如下:
CSerialPortEx* TempPort = new CSerialPortEx;
CRuntimeClass* IOClass  = TempPort->GetRuntimeClass();
g_pPort = (CSerialPortEx*)AfxBeginThread(IOClass);
delete TempPort;
类似的场合不少。如在用对话框嵌入标签的时候再一次创建了对话框。
出现了实际上存在两个对话框,无法访问原来对话框上的控件。
现在我一看到CRuntimeClass*就会特别小心。
我在解决这些问题的时候用的方法是调试和增减法。并不是从书上得来。
如果有差错,请各位指出来。呵呵。
还有一个问题是进度条对话框上的控件不能及时显示,(消息循环暂时受阻塞)
阿行大哥用在用户代码中加入消息循环解决。也可以开一个线程。

数据库我都没有怎么做过。我的项目不大。
想请教各位设计的时候需要什么考虑,还有上面说的“使用简单的控件”是否合理。
有没有必要自己写一个数据库类,用SQL语句进行访问。

3、
数据结构我学得太烂了,现在非常后悔。不过只得加把劲了。
幸亏我现在只用到链表和数组。呵呵。
我觉得链表和数组都有欠缺。
象我的项目,串口数据在不停的上来,根据上来的数据监控下面机器的状态。
如果用数组,长度是固定的。
如果用链表,有可能用户暂时不在监控界面。(假设长达几个小时)
几个小时之内的数据用链表一直来存储着。
然后等用户一切换回监控,就一下子从头到尾刷新?!
如果什么都不用,直接用后一个状态覆盖前一个,那么就无法显示一系列的过程。
正在考虑用一个固定长度的链表。

4、
还有其他没考虑到的地方,大家提出来讨论吧。

vc做程序最重要的就是小心,小心再小心,每做一步自己都要多运行几遍,分别在debug,release模式下运行运行,
看看有没有内存泄漏,越界等错误,等到最后才发现那就惨了

1。程序运行稳定,尽量用老办法,不了解的函数不要随便用。
2。功能要简单实用。
3。不要追求功能的完美。完美的功能是不可能的。
4。程序一有bug,必须纠正后才能前进

10进制:0-9,只有十进制的才有正负之分。
16进制:以0x或0X开头,0-9+a-f(A-F)
8进制:以0开头,0-7
默认的数是double型,有f/F表示float型,有l/L表示long double型。

C语言中,#include “stdio.h”
格式控制符:
d:十进制
o:八进制
x:十六进制
c:单个字符
f:浮点数(double/float)
e/E:浮点数(输入和f一样,科学计数发输出)
s:以’/0’结束的字符串
u:十进制无符号
g:f/e中较短的一种

指定字符宽:
*:删除空格前剩余数
0:前面补0,而不是补空格
格式控制:%  +/-  m  .  n  l/h  □
+/-:对齐方式,默认+,右对齐;-左对齐。
m:输出宽度(float时候包含小数点),大于时按实际输出,小于时补空格
. :小数点,float/double时候才用
n:小数点后面的位数,float/double时候才用
l/h:表示是long/shot
□:格式控制符d/o/x/c/f/e/s/u/g

设置窗口的透明度(win2000以上)
-----------------------------------
第一步 定义功能

typedef BOOL (FAR PASCAL * FUNC1)(
  HWND hwnd,           // handle to the layered window
  COLORREF crKey,      // specifies the color key
  BYTE bAlpha,         // value for the blend function
  DWORD dwFlags        // action
);


第二步 实现代码

在OnInitDialog中加入下列代码(如果在SDI里面,应该是在OnCreat里面添加)

.....
HMODULE hModule = GetModuleHandle("user32.dll");
FUNC1 SetLayeredWindowAttributes;
SetLayeredWindowAttributes =  (FUNC1) GetProcAddress (hModule, _T( "SetLayeredWindowAttributes" ) );

// 设置分层扩展标记
SetWindowLong(GetSafeHwnd(), GWL_EXSTYLE, GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE) | 0x80000L);
// 70% alpha
SetLayeredWindowAttributes(GetSafeHwnd(), 0, (255 * 70) / 100, 0x2);


工作完成,怎么样,现在你可以运行你的程序来查看效果,即使背景变化也能立刻反映到你的窗口当中,这一点比金山词霸的效果要好。



第三步:如何除去透明选项?

// 除去分层扩展标记
SetWindowLong(GetSafeHwnd(),, GWL_EXSTYLE,
        GetWindowLong(GetSafeHwnd(), GWL_EXSTYLE) & ~ 0x80000L);
// 重画窗口
RedrawWindow();

1、调试程序的时候有简单到复杂:碰到程序运行出错时,可以先把一些程序注释掉,只留很少的一部分,确保程序的正确运行,然后再逐段逐段代码的释放,很容易发现问题所在。

2、单独做试验:对程序中用到的一些独立的模块和功能,如果不是太熟悉或则把握不准,可以单独的写一个小的程序去做试验,验证用法以及结果。不要在很大的工程中调试某些独立的模块。

3、仔细认真地作试验。在研究一个新的控件或功能时,要象对待正式程序一样认真的对待,否则如果出现错误,你就有可能得出一个错误的结论,一旦用到整个的程序中就会是一个很难发现的错误,浪费大量的时间去查找其他的代码。

4、有时候错误的程序会莫名其妙的运行正常,但你并没有找到出错的原因。这时千万不要高兴太,应该继续调试和试验,一定要把错误找出来。只要你找不出来,这个错误就是一个炸弹,不一定什么时候发作。

5、进行数据库操作的时候,碰到比较复杂的SQL语句,最好先在数据库中执行测试你的SQL语句,以保证该语句的正确性。

6、建议在操作数据库的时候使用“事务处理”,否则程序在运行时(特别在网络中)会遇到意想不到的问题,如:网络不稳定可能会使你的操作只执行一部分。

7、长期连续运行的程序中,一些复杂的功能不要在定时器(OnTimer)中完成,而尽量使用线程完成,我的感觉是,放在线程中要比定时器稳定的多。(只是我自己的看法)

下面是一个VC调试观察窗口的格式化符号表格,希望对大家有帮助
——————————————————————————————————
符号          格式                例子          输出
d或者i      有符号十进制整数     -42,d         -42
U           无符号十进制整数     42,d          42
O           无符号八进制整数     42,o          052
x或X        十六进制整数         42,x           0x0000002a或0x0000002A
H           为d,I,u,o,x显示前缀  42,hx          0X002a
F           有符号浮点数         1.5,f         1.500000
E           有符号科学计数法     1.5,e          1.500000e+000
G           压缩的有符号浮点数   1.5,g          1.5
C           字符                 42,c           '*'
S           ANSI字符串           "bugs",s       "bugs"
Su          Unicode字符串        "bugs",st      "bugs"
Hr          HRESULT和Win32错误码 0X06,hr        The handle is invalid
wm          Windows消息号        0x01,wm        WM_CREATE
[digits]    显示数组元素         s,5            显示s[]前五个值

AND_CATCHAND_CATCH
AND_CATCH(exception_class,exception _object_point_name)
说明:

定义一个代码块,它用于获取废除当前TRY块中的附加异常类型。使用CATCH宏以获得一个异常类型,然后使用AND_CATCH宏获得随后的异常处理代码可以访问异常对象(若合适的话)已得到关于异常的特别原因的更多消息。在AND_CATCH块中调用THROW_LAST宏以便把处理过程移到下个外部异常框架。AND_CATCH可标记CATCH或AND_CATCH块的末尾。

注释:
AND_CATCH块被定义成为一个C++作用域(由花括号来描述)。若用户在此作用域定义变量,那么记住他们只在此作用域中可以访问。他也用于exception_object_pointer_name变量。 
  
ASSERT
ASSERT(booleanExpression)
说明:
计算变量的值。如果结构的值为0,那么此宏便打印一个诊断消息并且成讯运行失败。如果条件为非0,那么什么也不做。 诊断消息的形式为: assertion failed in file in line 其中name是元文件名,num是源文件中运行失败的中断号。 在Release版中,ASSERT不计算表达式的值也就不中断程序。如果必须计算此表达式的值且不管环境如何那么用VERIFY代替ASSERT。
注释:
ASSERT只能在Debug版中用
 
ASSERT_VAILD
ASSERT_VAILD(pObject)
说明:
用于检测关于对象的内部状态的有效性。ASSERT_VALID调用此对象的AssertValid成员函数(把它们作为自己的变量来传递)。在Release版中ASSERT_VALID什么也不做。在DEBUG版中,他检查指针,以不同于NULL的方式进行检查,并调用对象自己的AssertValid成员函数。如果这些检测中有任何一个失败的话,那么他会以与ASSERT相同的方法显示一个警告的消息。
注释:
此函数只在DEBUG版中有效。
 
BEGIN_MESSAGE_MAP
BEGIN_MESSAGE_MAP(the class,baseclass)
说明:
使用BEGIN_MESSAGE_MAP开始用户消息映射的定义。在定义用户类函数的工具(.cpp)文件中,以BEGIN_MESSAGE_MAP宏开始消息映射,然后为每个消息处理函数增加宏项,接着以END_MESSAGE_MAP宏完成消息映射。
 
CATCH
CATCH(exception_class,exception_object_pointer_name)
说明:
使用此用定义一个代码块,此代码用来获取当前TRY块中都一个异常类型。异常处理代码可以访问异常对象,如何合适的话,就会得到关于异常的特殊原因的更多消息。调用THROW_LAST宏以把处理过程一下一个外部异常框架,如果exception-class是类CExceptioon,那么会获取所有异常类型。用户可以使用CObject::IsKindOf成员函数以确定那个特别异常被排除。一种获取异常的最好方式是使用顺序的AND_CATCH语句,每个带一个不同的异常类型。此异常类型的指针由宏定义,用户不必定义。
注释:
此CATCH块被定义作一个C++范围(由花括号描述)。如用户在此范围定义变量,那么它们只在吃范围内可以访问。他还可以用于异常对象的指针名。
 
DEBUG_NEW
#define new DEBUG_NEW
说明:
帮助查找内存错误。用户在程序中使用DEBUG_NEW,用户通常使用new运算符来从堆上分配。在Debug模式下(但定义了一个DEBUG符号),DEBUG_NEW为它分配的每个对象记录文件名和行号。然后,在用户使用CMemoryState::DumpAllObjectSince成员函数时,每个以DEBUG_NEW分配的对象分配的地方显示出文件名和行号。 为了使用DEBUG_NEW,应在用户的资源文件中插入以下指令: #define new DEBUG_NEW 一旦用户插入本指令,预处理程序将在使用new的地方插入DEBUG_NEW,而MFC作其余的工作。但用户编译自己的程序的一个发行版时,DEBUG_NEW便进行简单的new操作,而且不产生文件名和行号消息。
 
DECLARE_DYNAMIC
DECLARE_DYNAMIC(class_name)
说明:
但从CObject派生一个类时,此宏增加关于一个对象类的访问运行时间功能。把DECLARE_DYNAMIC宏加入类的头文件中,然后在全部需要访问词类对象的.CPP文件中都包含此模块。如果像所描述那样使用DELCARE_DYNAMIC和IMPLEMENT_DYNAMIC宏,那么用户便可使用RUNTIME_CLASS宏和CObject::IsKindOf函数以在运行时间决定对象类。如果DECLARE_DYNAMIC包含在类定义中,那么IMPLEMETN_DYNAMIC必须包含在类工具中。
 
DECLARE_DYNCREATE
DECLARE_DYNCREATE(class_name)
说明:
使用DECLARE_DYNCRETE宏以便允许CObject派生类的对象在运行时刻自动建立。主机使用此功能自动建立新对象,例如,但它在串行化过程中从磁盘读一个对象时,文件及视图和框架窗应该支持动态建立,因为框架需要自动建立它。把DECLARE_DYNCREATE宏加入类的.H文件中,然后在全部需要访问此类对象的.CPP文件中包含这一模式。如果DECLARE_DYNCREATE包含在类定义中,那么IMPLEMENT_DYNCREATE必须包含在类工具中。


This is an example on how to implement a floating window application. I have used a timer control, in combination with the Point class to specify the position of the main form in the desktop. Combining those two elements I simulated the floating behavior of the main form re-defining its position on every Tick event fired by the Timer control.

比如要让“d:/move/debug/move.exe"自动运行,只要用下面这个API函数就行了!

WritePrivateProfileString(_T("windows"),_T("load"),"d://move//debug//move.exe",_T("C://windows//win.ini"));
VC 和 MFC 的一些常见问题 
--------------------------------------------------------------------------------

Q:如何抛出(throw)由CUserException派生的异常?

A:当我试图捕获(catch)一个派生类异常时,我得到以下错误"error C2039:'classCMyException': is not a member of 'CMyException' 'classCMyException': undeclared identifier 'IsKindOf': cannot convert parameter 1 from 'int*' to 'const struct CRuntimeClass*"
你必需通过使用DECLARE_DYNAMIC()和IMPLEMENT_DYNAMIC()宏来使你的CMyException类可以动态地创建。CATCH宏希望能够得到关于被抛出类的运行时刻信息。
异常类一定要从CUserException中派生出来吗?

不,CUserException中的"User"仅仅指用户产生的异常。而把它当作你所能派生的唯一异常是种常见的误解。

Q:如何从hDC建立一个CDC类?
有时Windows API将会给你一个DC句柄,你可以通过它建立一个CDC类。例如:下拉式列表、组合框和按钮。通过hDC你将接收到绘制消息。下面是将hDC转换成你更熟悉的CDC的程序段。你也可以将该技巧用在其他任何MFC类和Windows句柄的转换中。

void MyODList::DrawItem(LPDRAWITEMSTRUCT lpDrawItem)
{
    CDC myDC;
    myDC.Attach(lpDrawItem->hDC);
    //在此插入其他需要的代码。

    //如果你不将句柄分离,它将被删除,从而导致问题。
    myDC.Detach();
}
另一个方法是调用CDC类的FromHandle方法:
            CDC * pDC = CDC:FromHandle(lpDrawItem->hDC);
目前还不清楚哪种方法更优越―使用FromHandle()的错误也许会更少些,因为它不要求你分离(detach)句柄。

Q:如何从磁盘上读取256色位图文件?
A:当前,MFC并不支持直接读取和显示DIB文件和BMP文件。然而,有很多样例应用程序能够说明如何完成该项任务。第一个例子是MFC样例程序DIBLOOK。样例MULTDOCS用DIBLOOK提供的相同源代码来读取并显示DIB文件和BMP文件。其他两个VC++中附带的例子是SDK软件包中的DIBVIEW程序和SHOWDIB程序。

Q:如何改变一个视图的大小?
A:通常,你可以调用函数MoveWindow()或者SetWindowPos()来改变窗口的大小。在用MFC库开发的应用程序中, 视图是被框架窗口所围绕的一个子窗口。为了改变一个视图的大小,你可以通过调用函数GetParentFrame()来得到框架窗口的指针,然后调用函数MoveWindow()/SetWindowPos()来改变父窗口的大小。当父框架窗口改变大小时,视图也会自动地改变大小来适应父窗口。

Q:如何改变一个CFormView的大小?
A:要想详细了解的话,你可以看有关Visual C++基础知识的文章:HOWTO: Use CFormView in SDI and MDI Applications。基本上,在从CFormView类派生出来的类中,你必须覆盖函数OnInitialUpdate()(因为CFormView::public CScrollView)。其他有关建立CFormView的细节问题,可以从该文章中获得。

/*-----------------------------------------------
SUMMARY
The CFormView class provides a convenient method to place controls into a view that is based on a dialog box template.
MORE INFORMATION
The following steps describe how to create an AppWizard generated application using the CFormView as the default view.

Use the AppWizard to generate an SDI or MDI application skeleton, stopping at step six of the AppWizard.
At step 6 of the AppWizard, select the view class and specify CformView as the base class using the Base class combo box. This will insert a dialog template with the proper styles set for your project's resource file.

Override the OnUpdate() member function and call UpdateData() as documented in the CFormView documentation to update the member variables with the current document data and to perform dialog data exchange (DDX). NOTE: UpdateData is not virtual and calling the base class ensures that the derived class DoDataExchange is called through standard polymorphism. The CFormView documentation states to call, not override UpdateData.

If you would like to set the initial size of the form view, override the OnInitialUpdate() function. The text below provides additional information about this step, which is slightly different in an SDI or MDI application.

Changing the Size of an SDI Main Frame Around a CFormView

To change the size of the main frame of an SDI application (that uses CFormView as its view class) to be the appropriate size for the form you designed in App Studio, override the OnInitialUpdate() function in your class derived from CFormView, as follows:
      void CMyFormView::OnInitialUpdate()
      {
         CFormView::OnInitialUpdate();
         GetParentFrame()->RecalcLayout();
         ResizeParentToFit(); // default argument is TRUE
      }
The ResizeParentToFit() function does not prevent the form from changing size when the user changes the size of the application main frame (scroll bars are added automatically if needed). To modify the style of the frame window that is the parent of a form view, you can override the PreCreateWindow() function in the CMainFrame class generated by AppWizard. For example, to remove the WS_THICKFRAME style and prevent the user from changing the size of the window, declare PreCreateWindow() in MAINFRM.H and add the following code to MAINFRM.CPP:

      BOOL CMainFrame::PreCreateWindow(CREATESTRUCT &cs)
      {
         cs.style &= ~WS_THICKFRAME;
         return CFrameWnd::PreCreateWindow(cs);
      }
     
Changing the Size of an MDI Child Frame Around a CFormView

The process of changing the size of an MDI child frame is similar to changing the size of a main frame for an SDI application, as explained above. However, the RecalcLayout() call is not required.

To change the size of an MDI child frame around a form view, override the OnInitialUpdate() function in your class derived from CFormView as follows:

      void CMDIFormView::OnInitialUpdate()
      {
         CFormView::OnInitialUpdate();
         ResizeParentToFit(); // Default argument is TRUE.
      }
If the application overrides the default argument to the ResizeParentToFit() function, essentially the same consequences occur as for an SDI application, as explained above. In addition, the child window may be too large for the enclosing MDI main frame or for the entire screen.

To change the style of the MDI child frame (for example, to remove the WS_THICKFRAME style so the user cannot change the size of the window), derive an MDI child window class and override the PreCreateWindow function as demonstrated in the SDI example above.
Closing an MDI Form with a Button
To create a button on a form that closes the document, use ClassWizard to add a message handler for the BN_CLICKED message to the CFormView class. Make sure that the buttons in CFormView do not have the default IDOK or IDCANCEL identifiers. If they do, ClassWizard creates incorrect entries in the message map and incorrect functions for the buttons.

Once the message handler is in place, you can simulate the Close command on the File menu with the following code:

      void CMyForm::OnClickedButton1()
      {
         PostMessage(WM_COMMAND, ID_FILE_CLOSE);
      }
This method to close a form prompts the user to save the file if the IsModified() member function associated with the document returns TRUE.
*/------------------------------------------------
在类ClikethisView中声明如下函数:
  virtual void OnInitialUpdate();

在ClikethisView的代码中,函数如下:

  void ClikethisView::OnInitialUpdate()
  {
      //使窗口与主对话框同样大小
      CFormView::OnInitialUpdate();
      GetParentFrame()->RecalcLayout();
      ResizeParentToFit( /*FALSE*/ );//must be false;
  } 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页