77. 想在程式一啟動時就自動關閉視窗,不在工作列裡顯示
用CTRL+W打開ClassWizard;
點選Class Info頁,類名是工程名Dlg,
再在左下方的"Filter"中選擇"Windows";
回到Message Maps頁,就可以看到消息中有WM_WINDOWPOSCHANGING,
加入代碼,如上所示.
這樣運作*.EXE,不但看不到主界面,工作列也沒有,就是任務管理器中的"應用程式"中也不列出,那該如何關閉它?
在任務管理器的"程序"中可以找到它,這是黑客程式常用的方法.
如果需要的話,連"程序"中也看不到.這樣要終止它就是問題了.
78.修改列印預覽的ToolBar
為AFX_IDD_PREVIEW_TOOLBAR這個ID建立一個DialogBar。則系統就會用新建立的DialogBar代替系統預設的那個
79. 如何實作SDI與MDI的轉換?
我想将一個編好的SDI應用程式轉換為MDI,很明顯要有多處的改變。
你可以這樣做:建立一個繼承于CMDIChidWnd的類,不防設為CChldFrm.在CWinApp中作如下變化。
InitInstance()
{
. ...
//instead of adding CSingleDocTemplate
// Add CMultiDocTemplate.
pDocTemplate = new CMultiDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CSDIDoc),
RUNTIME_CLASS(CChldFrm),
// For Main MDI Frame change this frame window from
// CFrameWnd derivative ( i.e. CMainFrame )
// to your CMDIChildWnd derived CChldFrm.
RUNTIME_CLASS(CSDIView));
/// After this it is required to create the main frame window
// which will contain all the child windows. Now this window is
// what was initially frame window for SDI.
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;
.....
}
在從CMDIFrameWnd中繼承的類CMainFrame代替CFramWnd後,所有的類都将從CMDIFrame繼承,而不是CFrameWnd,編譯運作後你就會發現程式已經從SDI變換到MDI。
注意:在CMainFram中必須将構造函數從private改為public.否則會出錯。
80. CDC中的豎排文本?
在OnDraw成員函數中我想讓文本豎直對齊,但CDC類似乎不支援該處理
方法一:如果你的豎直對齊是指旋轉文本的話,下面的代碼會對你有幫助:該代碼檢查一個Check box控制,檢視文本是否需要旋轉.
// m_pcfYTitle is a CFont* to the selected font.
// m_bTotateYTitle is a bool (==TRUE if rotated)
void CPage1::OnRotateytitle()
{
LOGFONT lgf;
m_pcfYTitle->GetLogFont(&lgf);
m_bRotateYTitle=
((CButton*)GetDlgItem(IDC_ROTATEYTITLE))->GetCheck()>0;
// escapement is reckoned clockwise in 1/10ths of a degree:
lgf.lfEscapement=-(m_bRotateYTitle*900);
m_pcfYTitle->DeleteObject();
m_pcfYTitle->CreateFontIndirect(&lgf);
DrawSampleChart();
}
注意如果你從CFontDialog中選擇了不同的字型,你應該自己設定LOGFONT的lfEscapement成員.将初始化後的lfEscapement值傳到CFontDialog中.
方法二:還有一段代碼可參考:
LOGFONT LocalLogFont;
strcpy(LocalLogFont.lfFaceName, TypeFace);
LocalLogFont.lfWeight = fWeight;
LocalLogFont.lfEscapement = Orient;
LocalLogFont.lfOrientation = Orient;
if (MyFont.CreateFontIndirect(&LocalLogFont))
{
cMyOldFont = cdc->SelectObject(&MyFont);
}
81. 如何用鍵盤滾動分割的視口?
我的問題是當我用滑鼠滾動分割視窗時,視口滾動都很正常,但用鍵盤時,卻什麼也沒有發生.
在你的視圖繼承類中加入如下兩個函數,假定該類為CScrollerView:
void CScrollerView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
BOOL processed;
for (unsigned int i=0;i< nRepCnt&&processed;i++)
processed=KeyScroll(nChar);
if (!processed)
CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
}
BOOL CScrollerView::KeyScroll(UINT nChar)
{
switch (nChar)
{
case VK_UP:
OnVScroll(SB_LINEUP,0,NULL);
break;
case VK_DOWN:
OnVScroll(SB_LINEDOWN,0,NULL);
break;
case VK_LEFT:
OnHScroll(SB_LINELEFT,0,NULL);
break;
case VK_RIGHT:
OnHScroll(SB_LINERIGHT,0,NULL);
break;
case VK_HOME:
OnHScroll(SB_LEFT,0,NULL);
break;
case VK_END:
OnHScroll(SB_RIGHT,0,NULL);
break;
case VK_PRIOR:
OnVScroll(SB_PAGEUP,0,NULL);
break;
case VK_NEXT:
OnVScroll(SB_PAGEDOWN,0,NULL);
break;
default:
return FALSE; // not for us
// and let the default class
// process it.
}
return TRUE;
}
82. 如何改變預設的光标形狀?
我試着将光标改變為其它的形狀和顔色,但卻沒有變化.
在對話框/視窗/你需要的地方加上對WM_SETCURSOR消息的處理.
BOOL MyDialog::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
// TOD Add your message handler code here and/or call default
::SetCursor(AfxGetApp()->LoadCursor(IDC_MYCURSOR));
return TRUE;
//return CDialog::OnSetCursor(pWnd, nHitTest, message);
}
你沒有成功的原因是因為視窗類光标風格不能為NULL.
83. 如何選擇CTreeCtrl中的節點文本進行編輯?
在向CTreeCtrl中加入一項後,有什麼方法可以編輯該節點的文本呢?
首先設定你的CcompTreeCtrl具有TVS_EDITLABELS屬性.在設計時用控件屬性來設定在運作時用GetStyle()/SetStyle()成員函數來設定.然後請看下述代碼:
HTREEITEM CCompTreeCtrl::AddSet()
{
static int setCnt =3D 1;
HTREEITEM hItem;
CString csSet;
//create text for new note: New Set 1, New Set 2 ...
csSet.Format( _T( "New Set %d" ), setCnt++ );
hItem =3D InsertItem( csSet, IMG_CLOSEDFOLDER, IMG_CLOSEDFOLDER );
if( hItem !=3D NULL )
EditLabel( hItem );
return hItem;
}
84. CListCtrl中選擇變化時如何獲得通知?
我在Report View中使用了一個CListCtrl(自繪制類型),我想知道什麼時候選擇項發生了改變.
在選擇項變化時,可以使用按鈕有效或失效,按如下操作:
加入LVN_ITEMCHANGED消息處理.
void CYourClassNameHere::OnItemchangedEventList(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
*pResult = 0;
if (pNMListView->uChanged == LVIF_STATE)
{
if (pNMListView->uNewState)
GetDlgItem(IDC_DELETE)->EnableWindow(TRUE);
else
GetDlgItem(IDC_DELETE)->EnableWindow(FALSE);
}
}
85. 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;
}
86. 如何限制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;
}
87. 怎樣實作3D效果?
在對話框中怎樣實作Edit和Listboxes控件的3D效果?(環境95/NT VC5.0)
1). 使用帶WS_EX_CLIENTEDGE标志的::CreateWindowEx來替換::CreateWindow 或者用CWnd::CreateEx替換CWnd::Create.
2).在建立控件之後,調用ModifyStyleEx(0, WS_EX_CLIENTEDGE).
88. How do I update the text of a pane in a status bar?
By default, a CStatusBar pane is not enabled when the pane is created. To activate a pane, you must call the ON_UPDATE_COMMAND_UI() macro for each pane on the status bar and update the panes. Because panes do not send WM_COMMAND messages, you cannot use ClassWizard to activate panes; you must type the code manually. For example, suppose one pane has ID_INDICATOR_PAGE as its identifier and that it contains the current page number in a document. To make the ID_INDICATOR_PAGE pane display text, add the following to a header file (probably the MAINFRM.H file):
afx_msg void OnUpdatePage(CCmdUI *pCmdUI);
Add the following to the application message map:
ON_UPDATE_COMMAND_UI(ID_INDICATOR_PAGE, OnUpdatePage)
Add the following to a source code file (probably MAINFRM.CPP):
void CMainFrame::OnUpdatePage(CCmdUI *pCmdUI)
{
pCmdUI->Enable();
}
To display text in the panes, either call SetPaneText() or call CCmdUI::SetText() in the OnUpdate() function. For example, you might want to set up an integer variable m_nPage that contains the current page number. Then, the OnUpdatePage() function might read as follows:
void CMainFrame::OnUpdatePage(CCmdUI *pCmdUI)
{
pCmdUI->Enable();
char szPage[16];
wsprintf((LPSTR)szPage, "Page %d", m_nPage);
pCmdUI->SetText((LPSTR)szPage);
}
This technique causes the page number to appear in the pane during idle processing in the same manner that the application updates other indicators.
89. 動态修改對話框的大小
[問題提出]
關于如何動态改變對話框的大小,我做了個Demo,大家看看.
[程式實作]
//本函數使用方法:
//第一個參數:如果是TRUE表示顯示擴充的對話框,如果是FALSE,表示縮小對話框。
//第二個參數:表示本對話框的HWND,
//第三個參數:表示縮小後大小的控件的ID
void COptionDlg::ExpandBox(BOOL fExpand, HWND hwnd, int nIDDefaultBox)
{
CWnd *pWndBox=GetDlgItem(nIDDefaultBox);
RECT rcDefaultBox,rcChild,rcIntersection,rcWnd;
pWndBox->GetWindowRect(&rcDefaultBox);
HWND hwndChild = ::GetTopWindow(hwnd);
for (; hwndChild != NULL; hwndChild = ::GetNextWindow(hwndChild,GW_HWNDNEXT))
{
::GetWindowRect(hwndChild, &rcChild);
if (!IntersectRect(&rcIntersection, &rcChild, &rcDefaultBox))
::EnableWindow(hwndChild, fExpand);
}
::GetWindowRect(hwnd, &rcWnd);
if (GetWindowLong(hwnd, GWL_USERDATA) == 0)
{
SetWindowLong(hwnd, GWL_USERDATA,
MAKELONG(rcWnd.right - rcWnd.left,
rcWnd.bottom - rcWnd.top));
::ShowWindow(pWndBox->m_hWnd, SW_HIDE);
}
::SetWindowPos(hwnd, NULL, 0, 0,
rcDefaultBox.right - rcWnd.left,
rcDefaultBox.bottom - rcWnd.top,
SWP_NOZORDER | SWP_NOMOVE);
if(fExpand)
{
DWORD dwDims = GetWindowLong(hwnd, GWL_USERDATA);
::SetWindowPos(hwnd, NULL, 0, 0,
LOWORD(dwDims), HIWORD(dwDims), SWP_NOZORDER | SWP_NOMOVE);
::SendMessage(hwnd, DM_REPOSITION, 0, 0);
}
}
90. 用DoModal()調用模态對話框,總是顯示在正中,我重載了它,并添加了MoveWindow(),可是其m_hWnd是一串零,調用失敗。請問有何方法可使調用的模态對話框顯示于自定義位置?多謝
我不清楚你把MoveWindow()加在什麼地方了,正确的方法是在OnInitDialog中添加MoveWindow,如:
MoveWindow(0, 1, 300, 200);
需要注意的是前兩個參數不能都為0。如果你确實希望把視窗放在(0, 0)處,可以在對話框設計視窗的屬性中選中Absolute Align,然後再加入
MoveWindow(0, 0, 300, 200);
為什麼會是這樣?你看了MFC的源程式就會明白。原來MFC在調用你的OnInitDialog之後,會調用CDialog::CheckAutoCenter()(在dlgcore.cpp中)檢查是否需要将視窗居中,你看了這個函數後就明白為什麼需要上面那麼做了。