C++编程俱乐部

Author: Date: 1999年 第15期 13版

    问题1:在消息WM_ENABLE中用“GetDlgItem(IDC_BUTTON)->EnableWindow(FALSE);”语句来Disable一个ID_BUTTON按钮时,却没有发生变化,这是为什么?
    答:CWnd类中的EnableWindow函数用来Enable或Disable一个窗口类的对象,因为CButton类继承于CWnd类,所以你也可以用它来操作一个按钮。Enable一个基于窗口类的对象可以用以下代码:
    pWnd->EnableWindow(TRUE);
    Disable一个对象可用
    pWnd->EnableWindow(FALSE);
    其中,pWnd为一个指向窗口对象的指针(这里是指向按钮的指针),该问题关键在于VC中消息WM_ENABLE告诉窗口它正在Disable或Enable,但它并不能使一个窗口Enable或Disable。
    问题2:如何才能将最近使用过的几个文件名(包含路径)显示出来?
    答:你不需要建立一个CRecentFileList类,它已经由CWinApp基类完成了。你只需在 initinstance中调用LoadStdProfileSettings()函数就可以了。CRecentFileList类中有一个CWinApp保护成员变量(如m_pRecentFileList),所以你应该在你的继承类中处理它。
    void CMdiApp::OnFileMruFile1()
    { // TODO: Add your command handler code here
    CString vl_name;
    ASSERT( m_pRecentFileList->GetSize() > 0);
    vl_name = (*m_pRecentFileList)[0];
    CWinApp::OnOpenRecentFile(ID_FILE_MRU_FILE1);
    }
    问题3:在设计浮动菜单时设定为GRAYED的菜单项,如何在运行时激活它?
    答:只要在适当的时候调用EnableMenuItem函数就可以了。EnableMenuItem函数带有两个参数,一个是需要改变的菜单项的ID,而第二个参数则是通知函数应采取的动作,可以用MF_ENABLE或MF_GRAYED。
    void CMyView::OnRButtonDown(UINT nFlags, CPoint point)
    {CScrollView::OnRButtonDown(nFlags, point);
    CMenu *menu, *popup;
    menu = new CMenu();
    // load menu from resource file
    menu->LoadMenu( IDR_POPUPMENU );
    popup = menu->GetSubMenu(0); // item 0 is DUMMY
    UINT nEnable;
    nEnable = MF_BYCOMMAND|MF_GRAYED;
    if( your test )
    {nEnable = MF_BYCOMMAND|MF_ENABLED;}
    popup->EnableMenuItem( ID_YOUR_ID, nEnable );
    //display menu
    ClientToScreen(&point);
    popup->TrackPopupMenu(TPM_LEFTALIGN | TPM_R IGHTBUTTON,point.x, 
point.y, this );
    delete menu;}
    其中your test为判断条件,根据具体情况来改成相应的条件。
    问题4:我创建了一个使用数据库的MFC应用程序,用类模板生成CDaoRecordset直接打开数据库(不通过ODBC),请问应如何打开有密码保护的数据库?
    答:方法一:请试用下面的一段代码:
    DAODBEngine* pDBEngine = AfxDaoGetEngine();
    ASSERT(pDBEngine != NULL);
    COleVariant varUserName (strUserName, VT_BSTRT);
    COleVariant varPassword (strPassword, VT_BSTRT);
    DAO_CHECK(pDBEngine->put_DefaultUser (V_BSTR(&varUserName));
    DAO_CHECK(pDBEngine->put_DefaultPassword (V_BSTR(&varPassword));
    方法二:使用CDaoDatabase的Open方法:
    MyDaoDatabase->Open(″C:\MyDatabaseFile.mdb″,FALSE,FALSE,″;PWD=MyPassWord″);
    注意,请别忘了“;PWD=MyPassWord”前面的“;”号。
    问题5:我想让调用的函数和被调用的函数属于同一个类,结果在调用CreateThread时出现如下错误:
    error C2440: ′type cast′ : cannot convert from ′unsigned long (__stdcall Cdmi::*)(void *)′ to ′unsigned long (__stdcall *)(void *)′
    答:一、unsigned long (__stdcall Cdmi::*)(void *)是指向Cdmi某个成员函数的指针。
    二、unsigned long (__stdcall *)(void *)仅仅是一个C形式函数的指针。
    编译器无法将一转换为二是因为C++成员函数取第一个(隐藏)参数″this pointer″ 作为成员函数,但作为静态成员时则例外。可按如下方法解决:
    class XMyThread
    {public:
    void StartThread(void);
    virtual UINT ThreadFunction(void);
    static UINT __bogusthreadfunc(LPVOID lpparam);};
    void XMyThread::StartThread()
    {AfxBeginThread(__bogusthreadfunc,this);}
    UINT XMyThread::ThreadFunction(void)
    {//here you do all your real work
    return 0;}
    UINT XMyThread::__bogusthreadfunc(LPVOID lpparam)
    {XMyThread* This = dynamic_cast(lpparam);
    return This->ThreadFunction();}
    由于版面有限,我们没有加入停止线程的代码。如果需要,可以继承XMyThread,并重写ThreadFunction()函数,如:
    class XAnotherThread : public XMyThread
    {virtual UINT ThreadFunction(void);};
    UINT XAnotherThread :: ThreadFunction(void)
    {//do some other work here
    return 0;}