我自己记录的VC.NET 2003笔记
17.在VC++.NET的对话框中,按钮有时会出现双影,即一个普通的一个XP样式的.比如加入一个CDialog资源.
19.CRgn有应用.CRgn在CReate后再次Create要先调用DeleteObject(),否则会失败.
9.自删除.
10.VC对数据库的处理方式
11.Hook.
1.如何操作XML文件
六.集合类.
CTypedPtrList的使用方法:
第一种使用方法:
CTypedPtrList<CObList,CMyClass*> cL1;
CMyClass *c1=new CMyClass();
c1->m_string="a";
cL1.AddTail(c1);
cL1.AddTail(c2);
for(int i=0;i<cL1.GetCount();i++)
{
CMyClass *p=cL.GetAt(cL1.FindIndex(i));
p->print();
}
CTypedPtrList<CObList,CMyClass2*> cL2;
CMyClass2 c11("a");
cL2.AddTail(&c11);
for(int i=0;i<cL1.GetCount();i++)
{
CMyClass *p=cL.GetAt(cL1.FindIndex(i));
p->print();
}
还有一种:
POSITION i=cL.GetHeadPosition();
POSITION & ii=i;
CMyClass *p;
while(cL.GetTailPosition()!=ii)
{
p=cL.GetNext(ii);
p->print();
}
p=cL.GetNext(ii);
p->print();
七.文档/视图结构与窗体结构的混合.
1. 一个视图与另一个视图的切换.新建两个FromView的窗体.各自创建成它的类Cfv,Csec,注意,创建的类要继承自 CFormView。在菜单项中新建一菜单,在App中写事件代码:
CView* pOldActiveView =((CMainFrame*)GetMainWnd())->GetActiveView();
CRuntimeClass* pOldViewClass=RUNTIME_CLASS(Cfv);
CRuntimeClass* pNewViewClass;
if(pOldActiveView->IsKindOf(pOldViewClass))
{
pNewViewClass=RUNTIME_CLASS(Csec);
}
else
{
pNewViewClass=RUNTIME_CLASS(Cfv);
}
//::SetWindowLong(pOldActiveView->m_hWnd, GWL_ID,1);
CCreateContext context;
context.m_pNewViewClass = pNewViewClass;
context.m_pCurrentDoc =((CMainFrame*)GetMainWnd())->GetActiveDocument();
CView* pNewView = STATIC_DOWNCAST(CView,((CMainFrame*)GetMainWnd())-> CreateView(&context));
if (pNewView != NULL)
{
// the new view is there, but invisible and not active...
pNewView->ShowWindow(SW_SHOW);
pNewView->OnInitialUpdate(); //也可以不调用该函数.
((CMainFrame*)GetMainWnd())->SetActiveView(pNewView);
((CMainFrame*)GetMainWnd())-> RecalcLayout();
// finally destroy the old view...
pOldActiveView->DestroyWindow();
}
2. 文档/视图结构中的互相访问:
更新控件变量的值 updateData(false) ,这样理解: 把控件的值更新到变量 为 TRUE ,反之,把变量值更新到控件为 FALSE。
取得控件变量的值 updateData(true) ,这样理解:改变了控件内容后,要更新一下实际的变量值,其它线程才会取到真实保存的值,所以改变控件值更新是 TRUE , 而改变实后,再更新是 FALSE 。
取得主窗口 ::AfxGetMainWnd()
取得文档 m_pDocument
取得application object(Cwinapp 派生对象)的指针 AfxGetApp()
取得程序的instance handle AfxGetInstance
八.关于序列Serialize.
候俊杰说的一个类要有Serializable能力,这个类要有五个必要条件:
1.从CObject派生下来,
2.类的声明部分必须有DECLARE_SERIAL宏,
3.类的实现部分必须有IMPLEMENT_SERIAL宏.
4.改写Serialize函数.
5.为此类加上一个default函数(无参数构造函数).
但是2.3.条是错误的.类的声明部分有 DECLARE_DYNCREATE 宏,类的实现部分有 IMPLEMENT_DYNCREATE 宏也行.实现如下:
创建一单文档MFC程序seria,添加一FormView,及其类CStringList,序列化部分写在seriaDoc,
在serialDoc.h中写入成员变量,使该成员变量序列化. CStringList m_stringList; CString m_caption;
编写序列化函数void CseriaDoc::Serialize(CArchive& ar).
void CseriaDoc::Serialize(CArchive& ar)
if (ar.IsStoring())
{ar<<m_caption;}
else
{ar>>m_caption;}
经过上面设置后就实现了对成员变量的序列化了,但还没反应出来,还要在void CStringListView::OnInitialUpdate()中
编写如下代码,以实现对读取数据的显示.
void CStringListView::OnInitialUpdate()
{
CFormView::OnInitialUpdate();
m_ctlList.ResetContent();
CStringList& stringList =((CseriaDoc*)m_pDocument)->m_stringList;
POSITION pos = stringList.GetHeadPosition();
while (pos != NULL)
{
CString str = stringList.GetNext(pos);
m_ctlList.AddString(str);
}
GetDlgItem(IDC_CAPTION)->SetWindowText(((CseriaDoc*)m_pDocument)->m_caption);
// TODO: 在此添加专用代码和/或调用基类
}
另外,还要编写新建文件代码,在BOOL CseriaDoc::OnNewDocument()中插入下列代码:
BOOL CseriaDoc::OnNewDocument()
{
m_stringList.RemoveAll();m_caption="字符串";
return TRUE;
}
十.MFC操作.
1.快捷键的实现.(菜单,以及处理过程)
在资源的Accelerator处指定快捷键.
ToolBar的prompt中的文字"\n"前是在ToolBar的提示部分,"\n"后是鼠标悬停的文字.
2. 为什么IsKindOf()会出错,怎么截获它,并知道它是什么错误信息.
3. 传递CString也会出错.
定义函数OnCreateBatFile(CString FileName);在传递时FileName 不能接收到正确的参数.
4. 自定义ActiveX与COM
5. 如何实现把变量的值当作参数之一传递.
如想把"path=c:\windows;"中的"path"变成8个字符宽"path ",编程如何实现.
用CString.Foramt("%s8","path")可得到"path "但这个8是个变量.
解决办法:
char m_FormatStr[48]="%-"; //格式化字符串.
char m_TempStr[48];
CString m_MyString;
int format_Len=8;
wsprintf(m_TempStr,"%ds",2*format_Len);
lstrcat(m_FormatStr,m_TempStr); //这样m_FormatStr就成了"%-16"了.
m_MyString.Format(m_FormatStr,""); //这样m_MyString就成了左对齐的16个空格了.
6.常量中各缩写前缀的意义 .
WS_: Window Style
ES_: Edit Style
_EX_: Extra Style
DFC_: DrawFrameControl
DFCS_: DrawFrameControl Style
CDC: class of device-context;
HDC: Handle to a device context (DC)
7.SubclassDlgItem()只能子类化CDialog及其派生类.不能子类化FormView及其派生类.
解决办法:
在FormView的OnInitialUpdate()中写代码,不要在OnCreate()中写.
if(but.GetSafeHwnd() == NULL)
but.SubclassWindow(GetDlgItem(IDC_BUTTON1)->GetSafeHwnd());
8.控件OwerDraw后,就不能动态生成了.
9.我想把十六进制数字格式化成:"0x34,3433,1344,2434",如何?自已写.
int num=123456789;
int n=0;
char cha[48];
char ret[48]={0};
itoa(num,cha,10);
int len=strlen(cha);
for(int i=0;i<len;i=i+1)
{
if((len-i)%4==0)
{
ret[i+n]=',';
n++;
}
else
{
}
ret[i+n]=cha[i];
}
printf(ret);
10. 这段代码产生出来的文件用记事本修改后换行不能用了,用其它编辑器像.NEt倒可以.可能是它们处理回车换行(\r\n)不同.很奇怪.(m_ctrSpecifiedPorts是List控件)
CStdioFile f("DefaultPorts.txt", CFile::modeCreate|CFile::modeWrite|CFile::typeText);
char buff[10];
for(int i=0; i<m_ctrSpecifiedPorts.GetLineCount(); i++)
{
int len = m_ctrSpecifiedPorts.GetLine(i, buff, 9);
if (len != 0)
{
buff[len] = '\0';
f.WriteString((LPCTSTR)buff);
f.WriteString("\r\n");
}
}
f.Close();
1. 操作文件,报出错误信息,得到当前时间 的例子.
//把错误格式化输出的函数:
LPCTSTR FmtMsg(DWORD errID)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
LPCTSTR retVal = (LPCTSTR) lpMsgBuf;
AfxMessageBox(retVal);
//LocalFree( ( HLOCAL)lpMsgBuf) ; //如果此处 LocalFree 就完了.
return retVal;
}
void CMyTestDlg::OnBnClickedOk()
{
//CString str = "hello";
TCHAR str[24];
DWORD wrt;
hFile = ::CreateFile ( "d:\\test\\ab.txt", FILE_GENERIC_READ | FILE_GENERIC_WRITE , FILE_SHARE_READ | FILE_SHARE_WRITE, NULL , OPEN_ALWAYS ,FILE_ATTRIBUTE_NORMAL , NULL );
wrt = ::GetLastError() ;
if(wrt != NO_ERROR)
{
if ( wrt == ERROR_ALREADY_EXISTS )
{
hFile = ::CreateFile ( "d:\\test\\ab.txt",FILE_GENERIC_READ | FILE_GENERIC_WRITE , FILE_SHARE_READ | FILE_SHARE_WRITE, NULL , OPEN_EXISTING ,FILE_ATTRIBUTE_NORMAL , NULL );
}
else
{
LPCTSTR strMsg = FmtMsg(wrt);
::AfxMessageBox( strMsg);
return;
}
}
::SetFilePointer( hFile , 0 , 0 ,FILE_END );
SYSTEMTIME sysDate;
::GetLocalTime(&sysDate); //如果将此改成 ::GetSystemTime(&sysDate) ,得到的时间值将比当前小8个小时.
int iso = ::GetTimeFormat ( NULL , NULL , &sysDate, "H:mm:ss" , (LPTSTR)str ,10 ) ;
if( iso == 0 )
{
::AfxMessageBox( FmtMsg(::GetLastError()));
}
strcat(str,"\r\nabc");
::WriteFile (hFile,(LPVOID) str,strlen(str),&wrt,NULL);
::CloseHandle(hFile);
}
2. 可变参数的问题.
3.关于键盘钩子的函数及其参数:
LRESULT __declspec(dllexport)__stdcall CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam){}
nCode:
HC_ACTION 表示消息从消息队列中取出,消息队列中不再有该消息.
HC_NOREMOVE表示消息从消息队列中取出,消息队列中还存在该消息.
wParam:
指定按键消息的虚拟码(VK_XXX).
lParam:
32位数值,各位表示含义如下:
0-15:击键重复次数. 16-23:指定扫描码.
24: 指定该键是否是扩展键. 1表示是;0表示否.
29: 指示Alt键是否被按下. 1表示是;0表示否.
30: 指示前一次按键的状态. 1表示消息发送出去以前该键已被按下;0表示消息发送出去以前该键已经弹起.
31:
4. 获取EXE或DLL的实例句柄:LoadLibrary,AfxLoadLibrary,GetModuleHandle.
获取DLL导出函数的地址:GetProcAddress.
把结构拷贝到进程内存:RegisterClass.
5. 关于正规DLL和扩展DLL.
哪个程序调用DLL,DLL就被映射到哪个进程空间中,成为它的一部分.
正规DLL可以被任何Win32编程环境装载,可以导出C风格的函数,但不能导出C++类,成员函数或重载函数,但可以在其内部使用C++类.
扩展DLL支持C++接口,可以导出整个类,客户程序和扩展DLL要一致连接到MFC DLL的相同版本.体积小,装载快.
在扩展DLL中,AfxGetInstanceHandle返回的是Exe的实例句柄,而不是DLL的句柄.
6. WINDOWINFO wininfo;定义出错.要求只包括window.h就可以了,但包括了也不行.但在Win32的程序中可以.
解决:这是版本定义的事,在Stdafx.h中有关于Windows版本的定义,如果是Win2003的话,只保留
#ifndef _WIN32_WINNT // 允许使用 Windows NT 4 或更高版本的特定功能。
#define _WIN32_WINNT 0x0502 //502是win2003版本的值.
#endif
就可以了,去掉_WIN32_WINDOWS WINVER _WIN32_IE 的定义.或者干脆连_WIN32_WINNT去掉也可以.
7. 如何用WIN32API函数的 CreateFile WriteFile ReadFile
hFile = ::CreateFile ( FileName.data() , FILE_GENERIC_READ | FILE_GENERIC_WRITE , FILE_SHARE_READ | FILE_SHARE_WRITE, NULL , OPEN_ALWAYS ,FILE_ATTRIBUTE_NORMAL , NULL );
retD = ::GetLastError() ;
if(retD != NO_ERROR)
{
if ( retD == ERROR_ALREADY_EXISTS )
{
hFile = ::CreateFile ( FileName.data() ,FILE_GENERIC_READ | FILE_GENERIC_WRITE , FILE_SHARE_READ | FILE_SHARE_WRITE, NULL , OPEN_EXISTING ,FILE_ATTRIBUTE_NORMAL , NULL );
}
else
{
if (ShowErrorBoxIfFailure )
{
AfxMessageBox(ErrMsg( retD ).data());
}
return;
}
}
::SetFilePointer( hFile , 0 , 0 ,FILE_END );
六.一些VC的COM数据类型:
1.
转换: (LPTSTR)(_bstr_t)(_variant_t);
_variant_t 是VARIANT的完全包装类。它提供多种构造函数和数据转换函数。本文仅讨论与字符串有关的操作。
// 构造
_variant_t v1 = "char string"; // 从LPCSTR 构造
_variant_t v2 = L"wide char string"; // 从LPCWSTR 构造
_bstr_t bs1 = "Bob";
_variant_t v3 = bs1; // 拷贝一个 _bstr_t 对象
// 数据萃取
_bstr_t bs2 = v1; // 从VARIANT中提取BSTR
_bstr_t bs3 = (_bstr_t) v1; // cast OK, 同上
注意,_variant_t 方法在转换失败时会抛出异常,所以要准备用catch 捕捉_com_error异常。
另外要注意 _variant_t 不能直接转换成MBCS字符串。要建立一个过渡的_bstr_t 变量,用其它提供转换Unicode到MBCS的类函数,或ATL转换宏来转换。
与_bstr_t 不同,_variant_t 数据可以作为参数直接传送给COM方法。_variant_t 继承了VARIANT类型,所以在需要使用VARIANT的地方使用_variant_t 是C++语言规则允许的。
七. 设置RadioButton的选中状态.
方法一: ((CButton *)GetDlgItem(IDC_CPY_SHORTCUT))->SetCheck(BST_CHECKED);
方法二: GetDlgItem(IDC_CPY_SHORTCUT)->SendMessage(BM_SETCHECK,TRUE);
|
作者:NewSea 出处:http://newsea.cnblogs.com/
QQ,MSN:iamnewsea@hotmail.com 如无特别标记说明,均为NewSea原创,版权私有,翻载必纠。欢迎交流,转载,但要在页面明显位置给出原文连接。谢谢。 |

浙公网安备 33010602011771号