⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vc小知识总结(续).txt

📁 一些学C的忠告以及有小程序可学习。应该是终生受用的。
💻 TXT
📖 第 1 页 / 共 5 页
字号:
 VC小知识总结(续)

(1)当文档被修改时,如何在标题上加上标志'*'?
重载CDocument类的虚函数virtual SetModifiedFlag:

void CTest2Doc::SetModifiedFlag(BOOL bModified)
{
    CString strTitle = GetTitle();
    CString strDirtyFlag = " *"; // note space before the '*'
            // so we don't break Save As dialog

    if (!IsModified() && bModified)
    {
        SetTitle(strTitle + strDirtyFlag);
    }
    else if ( IsModified() && !bModified )
    {
        int nTitleLength = strTitle.GetLength();
        int nDirtyLength = strDirtyFlag.GetLength();
        SetTitle( strTitle.Left(nTitleLength - nDirtyLength) );
    }

    UpdateFrameCounts();

    CDocument::SetModifiedFlag(bModified);
}

(2)VC6.0对VC5.0的兼容性?
很不幸,vc6.0在调试模式对vc5.0不兼容,但发行模式没有问题.原因在微软改变了调试模式所用dll的格式,而保留了原文件名. 因此,不要在vc6.0中打开vc5.0的调试版本工程.

(3)打印和打印机的问题?
我碰到这么一个问题:在打印方法中使用了MM_LOMETRIC模式,在LOGFONT结构中改变了字体的大小,但不知道173(或者对于屏幕而言是25)是从哪来的,它是自动的.然而当我用另外一个打印机时173并不适合.我想知道的是:我如何对所有的打印来调整这个数字.

我以前也碰到过类似的问题,我让用户改变字体(大小,颜色等等).这些改变在屏幕上看起来挺好,但是打印时太小(我的同事在程序包中加入一个放大类).原因非常简单:打印机的分辨率可能是300dpi,而屏幕的分辨率则低得多.我是这么解决的:在获得屏幕字体信息后,我获取屏幕字体的毫米级大小(使用LPtoDP,然后将模式变为MM_LOMETRIC,调用DPtoLP),接着对打印机设定了相同的模式,再调用LPtoDP.切换回原来的模式之后,我调用了DPtoLP,这样就得到了想要的字体高度和宽度. 在LOGFONT中使用这个值,并且带有其它诸如下划线,斜体等字体信息,我实现了用户的要求.

(4)CRichEditCtrl滚动条的问题?
我使用了CRichEditCtrl控制来显示某个文件中的数据(将该控制设置为只读).我已经设置了ES_MULTILINE | ES_AUTOVSCROLL,但当数据内容比控制显示多的时候,滚动条并不出现,是不是因为设置了只读属性而引起了其它的问题?

ES_AUTOVSCROLL | ES_AUTOHSCROLL属性只在控制是可编辑时有效.你可心使用下面的滚动条风格来使滚动条出现:WS_VSCROLL | WS_HSCROLL,但是这样一来,不管你的数据量有多大,滚动条总是会出现.

(5)从数据库中读大于32k的内容?
我在从数据库中读数据时碰到了问题.当数据栏包含超过32k的内容时,我就读不出来,我试过ODBC::SQLGetData()也不行.

哪种类型的数据库?MS SQL,SYBASE... 试试设置一下大小:
BOOL CGetBlobStmt::Execute(LPCTSTR stmt)
{
m_cbSize = 0;
m_size = 0;
LPBYTE
  lpData;
lpData = (LPBYTE)GlobalLock(m_hData);

m_retcode = SQLSetStmtOption(GetHandle(),SQL_MAX_LENGTH,m_dwBytesLeft);

m_retcode = SQLExecDirect(GetHandle(),(UCHAR*)stmt,SQL_NTS);
if (m_retcode == SQL_SUCCESS)
{
  m_retcode = SQLFetch(GetHandle());
  if (m_retcode == SQL_SUCCESS ||m_retcode == SQL_SUCCESS_WITH_INFO)
  {
   m_retcode = SQLGetData(GetHandle(),1,SQL_C_BINARY,lpData,254,&m_cbSize);
   while(m_retcode == SQL_SUCCESS_WITH_INFO)
   {
    lpData+= 254;
    m_retcode = SQLGetData(GetHandle(),1,SQL_C_BINARY,lpData,254,&m_cbSize);
   }
   GetError();
  }
}
GlobalUnlock(m_hData);
#if TESTDATA
TRACE("%ld",m_size);
#endif

SaveFile();

return RETVALUE;
}

(6)如何获得CRichEditCtrl中字符的位置?
我想在CRichEditCtrl中使用右键菜单,因此想判定光标处字符的位置,请指点.

查看如下的帮助:
IRichEditOleCallback::GetContextMenu
EM_SETOLECALLBACK

(7)如何限制mdi子框架最大化时的大小?
用ptMaxTrackSize代替prMaxSize,如下所示:

void CChildFrame::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
{
   // TOD Add your message handler code here and/or call default
   CChildFrame::OnGetMinMaxInfo(lpMMI);
   lpMMI->ptMaxTrackSize.x = 300;
   lpMMI->ptMaxTrackSize.y = 400;
}


(8)如何切换视口而不破坏它们?
我创建了一个带有静态分隔区的sdi应用程序,左边显示工作区,右过显示左边选取的东西.我想达到的是如果在分隔区之间进行切换,而不覆盖或破坏原来的CView对象.

以下代码是你所想要的:

class CExSplitterWnd : public CSplitterWnd
{
// Construction
public:
    CExSplitterWnd();
// Overrides
    // ClassWizard generated virtual function overrides
    //{{AFX_VIRTUAL(CExSplitterWnd)
    //}}AFX_VIRTUAL
// Implementation
    virtual ~CExSplitterWnd();
    BOOL AttachView(CWnd* pView, int row, int col);
    BOOL DetachView(int row, int col);
    // Generated message map functions
    //{{AFX_MSG(CExSplitterWnd)
        // NOTE - the ClassWizard will add and remove member functions here.
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

CExSplitterWnd::CExSplitterWnd()
{
}

CExSplitterWnd::~CExSplitterWnd()
{
}

BOOL CExSplitterWnd::AttachView(CWnd* pView, int row, int col)
{
    //Make sure the splitter window was created
    if (!IsWindow(m_hWnd))
    {
        ASSERT(0);
        TRACE(_T("Create the splitter window before attaching windows to panes"));
        return (FALSE);
    }

    //Make sure the row and col indices are within bounds
    if (row >= GetRowCount() || col >= GetColumnCount())
    {
        ASSERT(0);
        return FALSE;
    }

    //Is the window to be attached a valid one
    if (pView == NULL || (!IsWindow(pView->m_hWnd)))
    {
        ASSERT(0);
        return FALSE;
    }

    pView->SetDlgCtrlID(IdFromRowCol(row, col));
    pView->SetParent(this);
    pView->ShowWindow(SW_SHOW);
    pView->UpdateWindow();
    return (TRUE);
}

BOOL CExSplitterWnd::DetachView(int row, int col)
{
    //Make sure the splitter window was created
    if (!IsWindow(m_hWnd))
    {
        ASSERT(0);
        TRACE(_T("Create the splitter window before attaching windows to panes"));
        return (FALSE);
    }

    //Make sure the row and col indices are
    //within bounds
    if (row >= GetRowCount() || col >= GetColumnCount())
    {
        ASSERT(0);
        return FALSE;
    }

    CWnd* pWnd = GetPane(row, col);
    if (pWnd == NULL || (!IsWindow(pWnd->m_hWnd)))
    {
        ASSERT(0);
        return FALSE;
    }

    pWnd->ShowWindow(SW_HIDE);
    pWnd->UpdateWindow();

    //Set the parent window handle to NULL so that this child window is not
    //destroyed when the parent (splitter) is destroyed
    pWnd->SetParent(NULL);
    return (TRUE);
}


(9)改变列表控制时发生闪烁现象?
我创建了一个简单的对话框,在对话框中设置了一个列表控件,这个控件占用了对话框的全部客户区.对话框是可以改变大小的,因此我要保证列表控件在对话框中维持正确的位置,在对话框的ONSize()事件中我对列表控件使用了MoveWindow(),这起到了作用,但当用户改变对话框的大小时,列表控件不停地闪烁.

要解决这个问题,在用MoveWindow之前,先用ShowWindow(SW_HIDE)隐藏列表控件,然后在MoveWindow之后用ShowWindow(SW_SHOW)来显示列表控件.

(10)处理列表控件可见项的问题?
我在一个列表控件中加入了好多条目.我通过获取某个条目是否可见或最后是哪个条目来进行处理.我看了CListCtrl::GetItem()的帮助,但是没有找到如何判断一个条目是否可见的方法.

如果你只想处理可见的条目,你可以用GetTopIndex.它返回最大可见条目的索引值,然后你再用GetCountPerPage来得到在可见区域的条目数.

(11)产生线程的问题?
我在使用CreateThread时碰到了问题.我想让调用的函数和被调用的函数属于同一个类,结果在我调用CreateThread时得到如下错误:

error C2440: 'type cast' : cannot convert from 'unsigned long (__stdcall Cdmi::*)(void *)' to 'unsigned long (__stdcall *)(void *)'

方法一:
(1)'unsigned long (__stdcall Cdmi::*)(void *)'是指向Cdmi某个成员函数的指针.
(2)'unsigned long (__stdcall *)(void *)'仅仅只是一个c形式函数的指针. 编译器无法将(1)转换为(2)是因为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();
}

for the sake of clairty, I did not add StopThread and I did not save the
CWinThread* returned by AfxBeginThread.

If you wanted a thread that does other things, simply derive from XMyThread
and override ThreadFunction()

example:
class XAnotherThread : public XMyThread
{
    virtual UINT ThreadFunction(void);
};

UINT XAnotherThread :: ThreadFunction(void)
{
    //do some other work here
    return 0;
}

方法二:Cdmi::MonitorFiles()是个静态的成员函数.

(12)CFile使用了缓冲区吗?
请告诉我CFile到底有没有使用缓冲区来处理文件?

CFile没有使用运行库的I/O缓冲例程,从这个意义上讲CFile并没有使用缓冲.但是有可能操作系统在处理文件时使用了缓冲区,如果你完全不需要缓冲区,你可以设置FILE_FLAG_NO_BUFFERING.CFile工作在这种模式下的唯一的方法是CFile::Attach().

(13)DAO的密码?
我创建了一个使用数据库的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");
btw:不要忘了PWD=前面的;号.

(14)如何知道CListBox什么时候滚动了?
每次绘制列表框都要重绘某项,通过消息WM_CTLCOLOR从父窗口获得DC颜色.因此每欠列表框的滚动你都可以用WM_CTLCOLOR来检验是否滚动.

HBRUSH CParentDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
   // is the control _the_ list box we're interested in?
   if( nCtlColor == CTLCOLOR_LISTBOX &&
      pWnd->GetDlgCtrlID() == IDC_LIST )
   {
      // if the top index changed, the list box has been scrolled

      int iTop = ((CListBox*)pWnd)->GetTopIndex();

      if( iTop != m_iTopOld )
      {
         // keeps tracking of the top index changes
         m_iTopOld = iTop;

         // process scrolling
         ...
      }
   }

   HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
   return hbr;
}
使用这种方法可以不必为了实现这个功能而去产生一个继承类.


(15)视口的不活动性如何处理?
有什么方法使CListView成为类似WM_DIASBLED的风格,或者使它和背景色一致.

方法一:你所要做的是处理CListView的WM_SETFOCUS消息,然后在TreeView中调用SetFocus,
这样,ListView就永远不会获得焦点.
    afx_msg void CMyListView::OnSetFocus(CWnd* pOldWnd);
    {
        // assuming m_pwndTreeView points to the valid TreeView
        // on the left side
        m_pwndTreeView->SetFocus();
    }

方法二:重载PreTranslateMessage,然后当消息为WM_LBUTTONDOWN或WM_RBUTTONDOWN时返回真即可.


(16)如何使用COleClientItem的IDispatch接口?
我创建了一个如何使用COleClientItem对象,我想使用它的自动化方法.有什么方法来获得IDispatch的接口?我试过以CCmdTarget为基类的的GetIDispatch函数但却出错,我用过EnableAutomation和GetIDispatch,却什么也没得到.

MSDN中有一篇关于这个的文章(TN039).如下的代码也可能是你所需要的:

LPDISPATCH CMyClientItem::GetIDispatch()
{
    ASSERT_VALID(this);
    ASSERT(m_lpObject != NULL);

    LPUNKNOWN lpUnk = m_lpObject;

    Run(); // must be running

    LPOLELINK lpOleLink = NULL;
    if (m_lpObject->QueryInterface(IID_IOleLink,
        (LPVOID FAR*)&lpOleLink) == NOERROR)
    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -