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中.