我自己记录的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);

posted @ 2009-03-09 01:01  NewSea  阅读(738)  评论(0)    收藏  举报