VC 心得:
1: 什么时候该进行物理坐标和逻辑坐标之间的转换(LPtoDP and DPtoLP)
见VC内幕 p55
只要不该变映射模式(MM_TEXT MM_LOENGLISH等)就用不着这种转换。
2: 按惯例,我们在直接调用win32函数时应该使用C++作用域分辨符(::)
3: OnPrepareDC 。OnDraw会自动调用它,但是其他消息控制函数,如果使用
了视图的设备环境,就必须要人工调用它。
4: 在运行时加入对话框控件:先调用构造函数,然后再调用Create
在调用了控件的Create函数后,还要调用其ShowWindow函数此控件
才能在窗口上显示!!!
5: 滑杆条控件和微调按钮控件的编程 vc内幕117~119
114面,注意在微调控件的style对话框选项卡里选择auto buddy和
set buddy integer
6: 关于设置映射模式的问题:可以在onPrepareDC函数里面通过
pDC->SetMapMode(****);
通过对CEx05c例子的分析,可知,如果视图的基类是CScrollView
那么成员函数SetScrollSizes(mapmode,***,***,***);也有同样的作用。
通过对ex10b的分析,如果自己加了一个CDC的成员变量,那么如果view
自身的设备环境设定了映射模式,用户自加的CDC成员变量也要设定映射
模式,见void CEx10bView::OnInitialUpdate()
前面有SetScrollSize 后来,用户自己的m_pdcMemory->SetMapMode();
如果用户的mapmode和view的mapmode不同的话,用户的会否覆盖view的?
7: 如何加入自定义的消息,以及如何使用PostMessage. ex07a给出了答案。
p129(下面,定义自己的消息) 130 131 133
8: 进行图像拖动时如何防止图像不闪烁?ex10b给出了答案。
简单点说就是要使用内存设备环境代替view本来的设备环境作为从OnPaint
传到OnDraw的参数
9: 用BeginWaitCursor和EndWaitCursor标识鼠标状态忙。p201
10: 进度条是如何实现的?且看多线程编程的一个例子,实际上只用到timer
ex11a p210
11: 辅助线程如何和主线程通话? ex11b, 生成全局的线程处理函数和自定义的消息处理函数用于退出。
12: 使用CEvent类来同步进程。ex11c。注意在stdAfx.h中加入#include <afxmt.h>以使用CEvent.
13: 阻塞区
14: 如何做选项卡式的属性页。p240 改进的ex12a程序。
15: 属性页的apply按钮的消息传递模式,根据ex12a。CPage1只要重载CPropertyPage::OnApply,而无需用
classwizard去生成什么响应WM_OnApply消息的函数(其实也没有这个消息)。而对于OK按钮,即“确定”
按钮,则根本无需自己编程,MFC已做好一切。按确定和按Apply都会导致调用OnApply(),不同的是确定
钮同时导致关闭对话框! Apply按钮是否可用,取决于是否SetModified(true),
在本例中,在OnCommand中调用了SetModified(true)
16: 一个比较重要的心得:关于控件和变量之间的值交换,对于那些用classwizard联系起来的变量和
控件,DDX会做一切,不要操心,只需调用updatedata(BOOL),注意参数的含义。true是控件向变量
传,false是变量向控件传。对于15中提到的属性页,则根本不用调用updatedata,只要按了apply
或者“确定”,DDX就自动调用了。
17: CWnd指针和控件ID的相互转换。GetDlgItem GetDlgCtrlID。p109
18: 如果要用SetDlgItemText()设定静态文本控件的caption,那么此静态文本控件的ID不能是
19: 多个命令映射同一个命令处理函数时的解决办法 p256 ON_COMMAND_EX
默认值IDC_STATIC.
20: 如何处理状态栏,看EX13B,注意267面的indicators数组,除了ID_SEPARATOR以外,其他三项,
名称末尾的字符串就是在状态栏上相应位置显示的字符。
21: 保存窗口的大小和位置,用到CPersistentFrame类,EX14A
22: 如何将工具栏上的按钮和菜单项相关联?(即菜单和菜单项具有相同的功能)。只要将此按钮的ID值
设为和菜单项的ID值设为相同。
23: 关于已关联的工具栏按钮和菜单项的提示写法:例如Draw a circle Circle ," "之前的是菜单项的
提示,之后的是工具栏按钮的提示。
24: 如何改变主窗口的caption,在CXXApp中的InitInstance()中加入m_pMainWnd->SetWindowText("自己的标题");
25: DECLARE_DYNAMIC(类名) IMPLEMENT_DYNAMIC()
保证在诊断信息转储过程中能得到类名。
26: 可序列化的类必须直接或间接地从CObject派生而来,并且在类声明中必须包含DECLARE_SERIAL IMPLEMENT_SERIAL
27: AppWizard所生成的任何一个文档类都包含DECLARE_DYNCREATE IMPLEMENT....
28: 第十四章,在InitInstance函数中调用SetRegistryKey,使用注册表存数据。
29: 使用注册表将文件和程序关联。P355上面
30: 多文档程序启动时默认打开一个新文档的问题。
AppWizard会自动在InitInstance中加入
if (!ProcessShellCommand(cmdInfo))//会调用OnFileNew
return FALSE;
如果不想在启动时就打开一个新文档,则在此代码前面加上
if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileNew) {
cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;
}
31: CListCtrl的用法 http://www.codeproject.com/listctrl/listctrldemo.asp?target=clistctrl
注意,LVITEM 的iItem和iSubitem。前一个代表行,后一个代表行中的列。
如何得到当前被选中的行,使用成员函数GetFirstSelectedItemPosition。
32: 如何让窗口变灰,在当前对话框调用此函数
GetDlgItem(IDC_BUTTON_START_PROC)->EnableWindow(false);
参数是控件ID。
在有CView的mfc中,做法不同参见深入浅出 ex17a。
void CStudentView::OnUpdateCommandDel(CCmdUI* pCmdUI)
{
// called during idle processing and when Student menu drops down
pCmdUI->Enable(m_position != NULL);
}
33: 如何不用AfxMessageBox("you info")而弹出对话框。用windows api的MessageBox
lpText=TEXT("错误:无法查询有关的注册表信息");
lpCaption=TEXT("port info");
MessageBox(NULL,lpText,lpCaption,MB_OK);
34: 如何把整型转换成字符型
char buffer[2];
itoa(urint,buffer,10);
35: CListCtrl,如何在选中时使整行都变蓝(既选中状态)
pmyListCtrl->SetExtendedStyle
(pmyListCtrl->GetExtendedStyle()|LVS_EX_FULLROWSELECT);
36: 关于属性页,AddPage一定要放在第二个构造函数里面。
CProSht_DcmConfig::CProSht_DcmConfig(UINT nIDCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(nIDCaption, pParentWnd, iSelectPage)
{
//AddPage(&m_CProPgDimSev);//如果放在这个构造函数里面,DoModal的时候
//AddPage(&m_CProPgDrctrs);//将没任何反应。
}
CProSht_DcmConfig::CProSht_DcmConfig(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage)
:CPropertySheet(pszCaption, pParentWnd, iSelectPage)
{
AddPage(&m_CProPgDimSev);
AddPage(&m_CProPgDrctrs);
}
而且要在包含此CProperSheet的类的构造函数后面初始化一下这个成员,(用冒号的)
like this:CProShtDcmCfg("");(假设CProShtDcmCfg是个CProperSheet数据成员)
37: 关于属性页的“Apply”问题。如果对于每个页当Apply时要有不同的操作,那么就重载每个页的OnApply
函数,即使没有设定SetModified(true)(即不将Apply按钮设为可用),当按下OK按钮时,每个页面的
OnApply()函数还是会被一一调用。(注意重载的OnApply还是要调用基类OnApply,VC会自动生成这个代码,别删)
38: 如何关掉警告信息
下面这样加在stdafx.h中
#pragma warning(disable : 4507 4244),后面的数字为警告码,要关哪种警告,就把警告码加进去。
39: 有关目录操作的函数 makepath,access,CreateDirectory(Ex), MakeSureDirectoryPathExists
40: 关于CRecordset类,如果我的类(继承自CRecordset)只映射一个表,那么查询,修改,插入,删除都可以
但是如果映射了多个表,那么只能查询。
41: AfxBeginThread无法和类成员函数使用,http://www.china-askpro.com/msg42/qa64.shtml
解决方法:使用静态成员函数作为 AfxBeginThread 的第一个参数,可以将this指针作为第二个参数,也就是该静态成员函数的参数,然后在该静态成员函数内部使用this指针间接的来使用成员变量和函数。
MyClass{ static UINT threadProc(LPVOID pParam);} //在头文件中
MyClass::threadProc(LPVOID pParam)//在cpp文件中
{
((MyClass*)pParam)->.....
}
AfxBeginThread(threadProc,(LPVOID)this); //在使用AfxBeginThread时
42: 关于如何做控件的文章 http://www.csdn.net/develop/Read_Article.asp?Id=18059
值得注意的是,如何在控件中对调用对象发出消息,一个 fire****, 有趣。
43: 用ATL实现VC插件
http://www.yesky.com/SoftChannel/72342371928702976/20030813/1721237.shtml
44: 如何得到一个对象的runtime class, 任何一个从CObject继承来的类的对象A,都可以通过A.GetRuntimeClass()->m_lpszClassName来得到这个对象的类名
C++心得:
1:构造函数的一种用法,如果只需要返回一个对象,而不需要为这个对象命名
则可以直接用构造函数 MyClass(....); 相当于*(new MyClass(....))
见p306
void CEx15aView::OnUpdateEditClearAll(CCmdUI* pCmdUI)
{
pCmdUI->Enable(GetDocument()->m_student !=CStudent()); //直接用构造函数返回了一个对象
}
2: 集合类,如果我们想用一个集合保存混合指针则使用CObList类,如果我们想要一个类型安全的集合,
它只包含一种类型对象的集合,那么我们就应该看看mfc库的模板指针集合类。CTypedPrtList就是
一个很好的例子。 p331
3: 使用rand函数获得随机数。rand函数返回的随机数在0-RAND_MAX(32767)之间。如果要实现类似0-1之间的函数,可以如下:
double randf()
{
return (double)(rand()/(double)RAND_MAX);
}
4: 重载“=”运算符的问题
如果两个类A的对象 a1和a2,则可直接用 a1 = a2 进行赋值,不用重载。(类A的父类或子类对象是否可以放在右边?)。如果右边不是类A的对象才要重载。
5: 类中静态成员变量的初始化。
如在myclass类中有静态成员变量 sa(假设int型)
则应该像全局变量一样,在任何函数体之外来初始化它,而且其形式是 int myclass::sa = 0;
/*****************路径选择窗口********************/
void 类名::OnBrowse()
{
// TODO: Add your control notification handler code here
//::SHBrowseForFolder();
LPCITEMIDLIST itemId;
BROWSEINFO bi;
char folderName[MAX_PATH];
char selectedDir[MAX_PATH];
HWND pHwnd=::FindWindow(NULL,"CustomCtrl");
bi.hwndOwner=pHwnd;
bi.pidlRoot=NULL;
bi.pszDisplayName=folderName;
bi.lpszTitle="请选择所在的根目录";
bi.ulFlags=0;
bi.lpfn=NULL;
bi.lParam=0;
bi.iImage=0;
itemId=::SHBrowseForFolder(&bi);
if(itemId)
{
::SHGetPathFromIDList(itemId,selectedDir);
m_Path.Format("%s",selectedDir);//路径在selectedDir中
UpdateData(FALSE);
}
}
/********************************************************/
/**********使用其他lib时出现重定义问题的solution*********************/
一.project 设置中
1.要用release/debug方式编译 不能用CT debug(crypto++自带的)
2.genernal 页中mfc的设置你的project和cryptlib 要一致,即同时为not using mfc/或其他....
3.c/c++ 页的code generation 的use runtime library 两个project要一致
precompiled headers 均选第一个 不使用
二.如果还不行,试试如下编译方法: compile-batch build (alphakk教的,vc我不熟,有问题找他或老妖,hoto...)
/********************************************************************/