天天看點

VC 常識(四)

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)

    {

        ASSERT(lpOleLink != NULL);

        lpUnk = NULL;

        if (lpOleLink->GetBoundSource(&lpUnk) != NOERROR)

        {

            TRACE0("Warning: Link is not connected!/n");

            lpOleLink->Release();

            return NULL;

        }

        ASSERT(lpUnk != NULL);

    }

    LPDISPATCH lpDispatch = NULL;

    if (lpUnk->QueryInterface(IID_IDispatch, &lpDispatch)

        != NOERROR)

    {

        TRACE0("Warning: does not support IDispatch!/n");

        return NULL;

    }

    ASSERT(lpDispatch != NULL);

    return lpDispatch;

}

(17)關于使用者自定義的消息使用?

我寫了一個基于MFC應用程式的對話框,在這個程式中,我建立了等待網絡傳輸資料的線程,一旦該線程接收到資料,它就傳送一個使用者自定義的消息到對話框,使對話框知道有資料過來.但是為何在CMyDialog::PreTranslateMessage(MSG* pMsg)中能捕捉到WM_MYCMD這個消息,卻不能和OnMyCommand相映射?

将你所有自定義消息的基類設為WM_APP,而不是WM_USER.

(18)在打開一個文檔時退出?

我有一個mdi程式,在打開檔案的處理過程中,我想判斷該文檔是不是應用程式需要處理的文檔,是以,我檢測文檔中的某個數字是否符合要求,如何在發現不是該文檔時出現一個錯誤提示,然後不打開該文檔?

給文檔設定某個标志,如果文檔不是所要的就設定它.然後OnOpenDocument中檢測,當發現标志被設定後傳回FALSE.

(19)在CListCtrl控件中多選擇項的删除?

如何從在CListCtrl中删除多個選擇項?

按如下方法處理:如果你的在CListCtrl是m_list,to_delete是個整數數組.

i=3D0;

POSITION pos=3Dm_list.GetFirstSelectedItemPosition();

if(pos)

while(pos)

   to_delete[i++]=3Dm_list.GetNextSelectedItem(pos);

然後用删除儲存在to_delete中的項目,用GetSelectedCount來得到已選項的個數.

(20)工作線程的登入狀态?

我使用循環删除了用AfxBeginThread建立的線程的好幾個執行個體.每個線程打開一個iNET連接配接,打開一個URL并傳回結果.我需要找出哪一個或者何時這些線程進入到登入狀态.

按如下方法處理:(僞代碼)

    // Start Threads

    for( unsigned u = 0; u < NUMBER_OF_THREADS; u++ )

{

    ThreadHandleArray[ u ] = AfxBeginThread( ...... )->m_hThread;

}

DWORD count = NUMBER_OF_THREADS

DWORD dwWait;

while( count )

{

    dwWait = ::WaitForMultipleObjects( count, ThreadHandleArray, FALSE,

INFINITE );

    if( dwWait >= WAIT_OBJECT_0 && dwWait < ( WAIT_OBJECT_0 + count ) )

    {

        dwWait -= WAIT_OBJECT_0;

        // dwWait now has index to thread that completed do whatever

you want to do with it

        // set array back up for next wait

        if( dwWait != ( count - 1 ) )

            ThreadHandleArray[ dwWait ] = ThreadHandleArray[

count - 1 ];

            count--;

    }

}

(21)如何增加視圖中ActiveX控件的事件處理函數?

如果我在對話框中加入微軟的網絡浏覽器,很容易通過類模闆加入對事件的處理.但我現在在視圖中用m_pBrowser=new CWebBrowser2加入了網絡浏覽器,我該如何對事件進行處理?

到www.vcdj.com(inet章節)去看看,有一篇文章名為"Building a Webbrowser in a Afternoon".如下的代碼也可能是你所需要的:

#include // For AFX_EVENT def.

BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)

{

    AFX_EVENT *pEvent = (AFX_EVENT *)pExtra;

    //If this is a control notification event.

    if (nCode == CN_EVENT)

    {

        // If we have information on this event.

        if (pEvent)

        {

            // Event DISPID is stored at pEvent->m_dispid

            // Event DISPPARAMS are stored at pEvent->m_pDispParams

            // Handle the event from here...

        }

    }

    return CWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);

}

(22)如何建立一個動态的Tree控件?

我想建立一個動态的tree控件,就象彈出視窗一樣,但它并不象想象中那麼容易.

方法一:用CreateWindow(SDK)建立風格為WS_POPUP,WS_CAPTION和WS_TICKFRAME的視窗,并作為父視窗.

方法二:建立一個包含Tree控件的對話框.

(23)SDI程式開始時不打開文檔?

我建立了一個SDI應用,但每次啟動時它都會打開一個文檔("untitled"),如何不讓它打開該文檔呢?

看看InitInstance函數中有沒有關于OnFileNew的調用,去掉它即可.

(24)List控件中整欄選擇?

我在處理List控件時碰到了麻煩,我想建立一個ListView,來依據Tree控件的選擇同時在ListView和ReportView中顯示清單的資訊.以下是相關的代碼:

// Set full line select

ListView_SetExtendedListViewStyle(m_plstCustomers->GetSafeHwnd(),

LVS_EX_FULLROWSELECT);

按如下方法處理:

// -------------------- begin of snippet --------------------------------

bool CCommCtrlUtil32::ListCtrl_ModifyExtendedStyle(CListCtrl& p_rListCtrl,

                                   const DWORD p_dwStyleEx,

                                   const bool p_bAdd)

{

    HWND t_hWnd = p_rListCtrl.GetSafeHwnd();

    DWORD t_dwStyleEx = ListView_GetExtendedListViewStyle(t_hWnd);

    if(p_bAdd)

    {

        if(0 == (p_dwStyleEx & t_dwStyleEx))

        {

            // add style

            t_dwStyleEx |= p_dwStyleEx;

        }

    }

    else

    {

        if(0 != (p_dwStyleEx & t_dwStyleEx))

        {

            // remove style

            t_dwStyleEx &= ~p_dwStyleEx;

        }

    }

    ListView_SetExtendedListViewStyle(t_hWnd, t_dwStyleEx);

    return true;

}

(25)如何重載MRU檔案?

我建立了一個應用程式可以載入圖象檔案,但當我點選FILE菜單下MRU檔案清單時,卻不能從磁盤載入以前曾經打開過的檔案.

下面是我所能想到的解決方案:

(1)在文檔類中定義一個成員函數(例如:CMyDoc::Reopen)來處理重新打開這個問題,指明參數和傳回值.

(2)産生一個CMultiDocTemplate的繼承類(如CMyDocTemplate),定義一個構造函數,取和基類相同的參數,不做任何事,隻是調用基類的構造函數.

(3)重載MatchDocType:

CMyDocTemplate::Confidence CMyDocTemplate::MatchDocType(

    LPCTSTR lpszPath,

    CDocument *&rpDocMatch

    )

{

    Confidence match = CMultiDocTemplate::MatchDocType(lpszPath, rpDocMatch);

    if(yesAlreadyOpen == match) // clear enough

    {

        ASSERT_KINDOF(CMyDoc, rpDocMatch);

        ((CMyDoc *) rpDocMatch)->Reopen();

        // you can take any other actions here...

    }

    return match;

}

當這個函數傳回"yesAlreadyOpen"時,你的文檔架構将會被激活.

--------------------------------------------------

(26)CImageList控件中圖象橙色被顯示為黃色?

我使用了一個CImageList控件來裝入位圖,用于TREE控件,其它的色彩都很正常就是橙色被顯示成為黃色.

你隻能使用系統指定的20種顔色(橙色不包括在内);當然,你也可以用下面的方法來裝載位圖資源而不受顔色數的限制.

HBITMAP LoadResourceBitmap(HINSTANCE hInstance, LPSTR lpString,

                           HPALETTE FAR* lphPalette)

{

    HRSRC hRsrc;

    HGLOBAL hGlobal;

    HBITMAP hBitmapFinal = NULL;

    LPBITMAPINFOHEADER lpbi;

    HDC hdc;

    int iNumColors;

    if (hRsrc = ::FindResource(hInstance, lpString, RT_BITMAP))

{

hGlobal = ::LoadResource(hInstance, hRsrc);

lpbi = (LPBITMAPINFOHEADER)LockResource(hGlobal);

hdc = ::GetDC(NULL);

*lphPalette = CreateDIBPalette ((LPBITMAPINFO)lpbi, &iNumColors);

if (*lphPalette)

{

   ::SelectPalette(hdc,*lphPalette,FALSE);

   ::RealizePalette(hdc);

}

hBitmapFinal = ::CreateDIBitmap(hdc,

       (LPBITMAPINFOHEADER)lpbi,

       (LONG)CBM_INIT,

       (LPSTR)lpbi + lpbi->biSize + iNumColors * sizeof(RGBQUAD),

                   (LPBITMAPINFO)lpbi,

                   DIB_RGB_COLORS );

::ReleaseDC(NULL,hdc);

// ::UnlockResource(hGlobal);

// ::FreeResource(hGlobal);

}

    return (hBitmapFinal);

}

// internally used by LoadResourceBitmap

HPALETTE CreateDIBPalette (LPBITMAPINFO lpbmi, LPINT lpiNumColors)

{

LPBITMAPINFOHEADER lpbi;

LPLOGPALETTE lpPal;

HANDLE hLogPal;

HPALETTE hPal = NULL;

int i;

lpbi = (LPBITMAPINFOHEADER)lpbmi;

if (lpbi->biBitCount <= 8)

*lpiNumColors = (1 << lpbi->biBitCount);

else

*lpiNumColors = 0; // No palette needed for 24 BPP DIB

if (lpbi->biClrUsed > 0)

*lpiNumColors = lpbi->biClrUsed; // Use biClrUsed

if (*lpiNumColors)

{

hLogPal = GlobalAlloc (GHND, sizeof (LOGPALETTE) +

   sizeof (PALETTEENTRY) * (*lpiNumColors));

lpPal = (LPLOGPALETTE) GlobalLock (hLogPal);

lpPal->palVersion = 0x300;

lpPal->palNumEntries = *lpiNumColors;

for (i = 0; i < *lpiNumColors; i++)

{

   lpPal->pal

PalEntry.

peRed = lpbmi->bmiColors.rgbRed;

   lpPal->palPalEntry.peGreen = lpbmi->bmiColors.rgbGreen;

   lpPal->palPalEntry.peBlue = lpbmi->bmiColors.rgbBlue;

   if (i<=10 || i>=246)

    lpPal->palPalEntry.peFlags = PC_NOCOLLAPSE;

   else

    lpPal->palPalEntry.peFlags = 0;

}

hPal = CreatePalette (lpPal);

GlobalUnlock (hLogPal);

GlobalFree (hLogPal);

}

return hPal;

}

該函數也重載了位圖調色闆,這個功能被CBitmap::LoadBitmap忽略了(它假定位圖隻使用20種顔色).是以要保證在DC中有SelectPalette和RealizePalette.

(27)無法正确改變應用程式的圖示?

我有一個基于對話框的應用程式,在初始化時我使用了AfxGetApp()->LoadIcon(IDI_BRIEFCASE)來載入自己的圖示,當把程式拷貝到桌面上時,圖示是我所期望的.但在資料總管中的圖示卻還是MFC的圖示.

資料總管僅使用16x16的小圖示,可能你在資源編輯器中隻修改了32x32的标準圖示.你需要重建16x16的小圖示.

(28)工具條狀态的問題?

在應用程式中我建立了三個工具條,我想讓它們在應用程式啟動的時候排成一行正好在主菜單的下面,我該如何去做?

在VC CDs上有一個例子:

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

//other stuff here...

    EnableDocking(CBRS_ALIGN_ANY);

    DockControlBar(&m_wndToolBar,AFX_IDW_DOCKBAR_TOP);

    DockControlBarLeftOf(&m_wndListToolBar,&m_wndToolBar);

    return 0;

}

void CMainFrame::DockControlBarLeftOf(CToolBar* Bar,CToolBar* LeftOf)

{

    CRect rect;

    DWORD dw;

    UINT n;

    // get MFC to adjust the dimensions of all docked ToolBars

    // so that GetWindowRect will be accurate

    RecalcLayout();

    LeftOf->GetWindowRect(&rect);

    rect.OffsetRect(1,0);

    dw=LeftOf->GetBarStyle();

    n = 0;

    n = (dw & CBRS_ALIGN_TOP) ? AFX_IDW_DOCKBAR_TOP :n;

    n = (dw & CBRS_ALIGN_BOTTOM && n==0) ? AFX_IDW_DOCKBAR_BOTTOM :n;

    n = (dw & CBRS_ALIGN_LEFT && n==0) ? AFX_IDW_DOCKBAR_LEFT :n;

    n = (dw & CBRS_ALIGN_RIGHT && n==0) ? AFX_IDW_DOCKBAR_RIGHT :n;

    // When we take the default parameters on rect, DockControlBar will dock

    // each Toolbar on a seperate line. By calculating a rectangle, we in effect

    // are simulating a Toolbar being dragged to that location and docked.

    DockControlBar(Bar,n,&rect);

}

(29)在SDI應用程式中使用Active控件?

我剛了解到如何在MFC應用程式中使用Active控件,文檔上說隻能在視圖為CFormView和CDialog時使用,但要是其它的情況該怎麼辦呢?

你可以在你應用程式的任何地方使用Active控件,而不僅僅局限于CFormView和CDialog為視圖基類的情況.DevStudio通過資源編輯器和對話框模闆來使得在上述兩個條件下使用Active控件更容易.是以,你也可以在任何視圖中使用Active控件,條件是你直接操縱該控件,建立它并手工的布置好它的位置(這也是DevStudio為你所做的事).

(30)有RichEdit控件的對話框無法正常顯示?

我在對話框中放置了一個RichEdit控件,但是對話框卻無法正常顯示.

在你的應用程式InitInstance()中調用了::AfxInitRichEdit()嗎?

(31)DLL中的模闆成員函數?

在一個DLL中,我在自己建立的類中使用了模闆成員函數來代替預處理宏.但出現以下錯誤:

error C2664: 'double Data::extract(double &)' : cannot convert parameter 1

from 'class CArray' to 'double &'

為什麼在比對模闆定義時它要尋找一個DOUBLE參數?

我覺得你可能是在表達成員函數(内聯)時出現了問題,請參照下面的示例:

   class AFX_EXT_CLASS Data : public CObject //This is not a template

   {

   public:

      Data();

      Data(BYTE * buffer,int size);

      template

      Data(const CArray& array);

      template

      CArray& extract(CArray& array)

      {

         CArchive ar(&buffer, CArchive::store);

         ar >> array;

      };

      double extract(double&);

                 (...)

   private:

      CMemFile buffer;

   }

(32)CFormView中的上下文幫助?

我想在基于CFormView類的SDI應用程式中加入真正的上下文幫助,但沒有成功.

你應該重載CMyFormView類的OnHelpHitTest函數:

LRESULT CMyFormView::OnHelpHitTest(WPARAM, LPARAM lParam)

{

    LRESULT lResult = (LRESULT)0x00;

    CWnd* pWndChild = ChildWindowFromPoint(CPoint(lParam),

CWP_ALL|CWP_SKIPINVISIBLE);

    if (pWndChild && ::IsWindow(pWndChild->m_hWnd))

    {

        lResult = ::GetWindowLong(pWndChild->m_hWnd, GWL_ID);

        if (lResult)

            lResult += HID_BASE_COMMAND;

    }

    if (lResult == (LRESULT)0x00)

        lResult = ::GetWindowLong(m_hWnd, GWL_ID) + HID_BASE_RESOURCE;

    return lResult;

}

然後你就可以使用平時用的幫助檔案了,但你要保證有正确的字首,請參照

TN028:Context-Sensitive Help Support.

例如:

ID_SOME_MENU_ITEM_OR_COMMAND_BUTTON

IDR_SOME_WINDOW_OR_DIALOG

IDP_PROMPT

IDW_CONTROL_THAT_IS_NOT_A_COMAND_BUTTON

你要确認你所使用的控件的ID包含在檔案resource.hm中.