天天看點

MFC的一些技巧(八)

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中)檢查是否需要将視窗居中,你看了這個函數後就明白為什麼需要上面那麼做了。

下一篇: VC++操作Excel

繼續閱讀