天天看點

MFC 技巧之四

31. 如何在編輯控件中以追加的方式添入字元?

 [問題提出]

  SetDlgItemText可以向Edit控件中輸入字元,發送更新的消息也可是Edit控件顯示與其關聯的變量的值,但若是向已有的Edit字元後追加字元,該如何做?

 [程式實作]

  建立名為My的對話框工程,添加一個Edit和一個Button控件.Edit的ID=IDC_EDIT1,Button的ID=IDC_BUTTON1.建立和IDC_BUTTON1的響應函數:OnButton1()

  void CMyDlg::OnButton1()

  {

    CString pText="你好";

    CEdit *m_Edit=(CEdit *)GetDlgItem(IDC_EDIT1);

    int nLen=m_Edit->GetWindowTextLength();

    m_Edit->SetFocus();

    m_Edit->SetSel(nLen, nLen);

    m_Edit->ReplaceSel(pText);

  }

  在Edit控件中輸入字元,想追加時按IDC_BUTTON1按鈕.看看效果.

32.屬性頁标題改名

我用CPropertySheet建立屬性頁,用的CPropertyPage對象隻有一個,也就是每個屬性頁的内容一樣.現在的問題是:這樣每個屬性頁的标題都是一樣的,是對話框的标題!怎樣動态的改變這個标題,使每個屬性頁的标簽的名稱都不同??

CTabCtrl * pCtrl = pSheet->GetTabControl();

TCITEM tc;

tc.mask = TCIF_TEXT;

tc.pszText = "新标題";

pCtrl->SetItem(0,&tc);//0即是你要改的TAb的索引

33. 怎樣去掉屬性頁的Apply與Help按鈕?

//去掉Help

  m_psh.dwFlags |= PSH_HASHELP ;

  m_psh.dwFlags &= ~PSH_HASHELP ;

//除掉應用按鈕 m_psh.dwFlags|=PSH_NOAPPLYNOW;

34. 如何給樹控件加入工具提示

1.首先給樹控件加入TVS_INFOTIP屬性風格,如下所示:

if (!m_ctrlTree.Create(WS_CHILD|WS_VISIBLE|

  TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT|TVS_SHOWSELALWAYS|TVS_INFOTIP, //加入提示TVS_INFOTIP,jingzhou xu(樹控件ID:100)

   CRect(0, 0, 0, 0), &m_wndTreeBar, 100))

  {

   TRACE0("Failed to create instant bar child/n");

   return -1;

  }

2.其次加入映射消息聲明,如下所示:

afx_msg void OnGetInfoTip(NMHDR* pNMHDR,LRESULT* pResult);    //樹控件上加入提示消息,jingzhou xu  

ON_NOTIFY(TVN_GETINFOTIP, 100, OnGetInfoTip)       //樹控件條目上加入提示,jingzhou xu

3.最後加入呼應涵數處理:

void CCreateTreeDlg::OnGetInfoTip(NMHDR* pNMHDR,

                  LRESULT* pResult)

 {

 *pResult = 0;

 NMTVGETINFOTIP* pTVTipInfo = (NMTVGETINFOTIP*)pNMHDR;

 LPARAM itemData = (DWORD) pTVTipInfo->lParam;

 //對應每個條目的資料

 HTREEITEM hItem = pTVTipInfo->hItem;

 CString tip;

 HTREEITEM hRootItem = m_chassisTree.GetRootItem();

 if (hRootItem != pTVTipInfo->hItem)

 {

  tip = "樹結點的提示";

 }

 else

 {

  tip = "樹根上的提示";

 }

 strcpy(pTVTipInfo->pszText, (LPCTSTR) tip);

}

35. 如何在TreeList中加圖示?

 [問題提出]

 請問treeview控件和treectrl控件的用法有何不同呢?向如何imagelist控件中加圖象呀?

 [解決方法]

 1)

  HICON hicon[8];

  m_imageList.Create(16,16,0,8,8);

  hicon[0]=AfxGetApp()->LoadIcon(IDI_ICON0);

  hicon[1]=AfxGetApp()->LoadIcon(IDI_ICON1);

  hicon[2]=AfxGetApp()->LoadIcon(IDI_ICON2);

  hicon[3]=AfxGetApp()->LoadIcon(IDI_ICON3);

  hicon[4]=AfxGetApp()->LoadIcon(IDI_ICON4);

  hicon[5]=AfxGetApp()->LoadIcon(IDI_ICON5);

  hicon[6]=AfxGetApp()->LoadIcon(IDI_ICON6);

  hicon[7]=AfxGetApp()->LoadIcon(IDI_ICON7);

  for(int n=0;n<8;n++)

    m_imageList.Add(hicon[n]);

  CTreeCtrl *pTree=(CTreeCtrl *)GetDlgItem(IDC_TREE);

  pTree->SetImageList(&m_imageList,TVSIL_NORMAL);

 2)

  CImageList cil1;

  cil1.Create(32,32,TRUE,2,2);

  cil1.Add(pApp->LoadIcon(IDI_DAO1));

  cil1.Add(pApp->LoadIcon(IDI_DAO2));

  cil1.Add(pApp->LoadIcon(IDI_DAO3));

  cil1.Add(pApp->LoadIcon(IDI_DAO4));

  cil1.Add(pApp->LoadIcon(IDI_DAO5));

  cil1.Add(pApp->LoadIcon(IDI_DAO6));

  cil1.Add(pApp->LoadIcon(IDI_DAO7));

  cil1.Add(pApp->LoadIcon(IDI_DAO8));

  cil1.Add(pApp->LoadIcon(IDI_DAO9));

  

  //設定圖象清單

  m_list.SetImageList(&cil1,LVSIL_NORMAL);

36. 如何輕按兩下清單框項啟動一個與檔案關聯的程式?

有人問我如何輕按兩下清單框項啟動一個程式?其實這個問題很簡單,Windows中有一個API函數可以打開任何類型的檔案:

ShellExecute(NULL,"open",lpFileName,NULL,NULL,SW_SHOWNORMAL);

參數 lpFileName 是檔案的全路徑名。用這個變量你可以傳遞象“C://MyExcelFile.xls”或者“http://www.vckbase.com”啟動 Excel程式或者浏覽器程式。如果你隻是想擷取與檔案關聯的程式名,而不是要運作程式,那麼調用::FindExecutable就可以了。

37. 如何防止在listbox中添加很多資料出現不停的重新整理?

 [問題提出]

  在listbox添加很多資料的時候,由于控件不停的重新整理,導緻出現閃爍,如何解決?

 [解決方法]

  再添加資料以前,禁止控件重新整理,資料添加完畢以後,再重新整理一次。

 [程式實作](其中:m_ListBox是CListBox的控件類型的變量)

  m_ListBox.LockWindowUpdate();//禁止本listbox重新整理。

  for(int i=0;i<9999;i++)

  {

     m_ListBox.AddString("test");

  }//添加資料。

  this->RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);

38. 如何得到CListBox所選擇項的String?

 [問題提出]

 如何得到CListBox所選擇項的String

 [解決方法]

 用到:CListBox::GetText()

 [程式實作]

 CString scInfo;

 pList->GetText( GetCurSel(),scInfo);

39. 用滑鼠移動基于對話框的無标題欄程式的簡單方法

void CVCTestDlg::OnLButtonDown(UINT nFlags, CPoint point)

{

  //一句話解決問題

  SendMessage(WM_SYSCOMMAND,0xF012,0);

  CDialog::OnLButtonDown(nFlags, point);

}

40. 如何改變框對話或窗體視窗的背景顔色

調用CWinApp : : SetDialogBkColor可以改變所有應用程式的背景顔色。第一個參數指定了背景顔色,第二個參數指定了文本顔色。下例将應用程式對話設定為藍色背景和黃色文本。

BOOL CSampleApp : : InitInstance ( )

{

//use blue dialog with yellow text .

SetDialogBkColor (RGB (0, 0, 255 ), RGB ( 255 , 255 , 0 ) ) ;

}

需要重畫對話(或對話的子控件)時,Windows向對話發送消息WM_CTLCOLOR,通常使用者可以讓Windows選擇繪畫背景的刷子,也可重置該消息指定刷子。下例說明了建立一個紅色背景對話的步驟。

首先,給對話基類增加一人成員變量CBursh :

class CMyFormView : public CFormView

{

private :

CBrush m_ brush ; // background brush

} ;

其次, 在類的構造函數中将刷子初始化為所需要的背景顔色。

CMyFormView : : CMyFormView ( )

{

// Initialize background brush .

m_brush .CreateSolidBrush (RGB ( 0, 0, 255 ) )

}

最後,使用ClassWizard處理WM_CTLCOLOR消息并傳回一個用來繪畫對話背景的刷子句柄。注意:由于當重畫對話控件時也要調用該函數,是以要檢測nCtlColor參量。

HBRUSH CMyFormView : : OnCtlColor (CDC* pDC , CWnd*pWnd , UINT nCtlColor )

{

// Determine if drawing a dialog box . If we are , return +handle to

//our own background brush . Otherwise let windows handle it .

if (nCtlColor = = CTLCOLOR _ DLG )

return (HBRUSH) m_brush .GetSafeHandle ( ) ;

return CFormView : : OnCtlColor (pDC, pWnd , nCtlColor );

}

41.如何禁止對話框關閉按鈕和浮動工具條上的系統菜單

1、禁止對話框中的關閉按鈕有二種方法。

第一種方法,用ModiftMenu()涵數來實作:

CMenu* pMenu = this->GetSystemMenu(FALSE);

pMenu->ModifyMenu(SC_CLOSE,MF_BYCOMMAND | MF_GRAYED );

第二種方法,用EnableMenuItem()涵數來實作:

CMenu* pMenu = this->GetSystemMenu(FALSE);

pMenu->EnableMenuItem( SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);

2、禁止浮動工具條上的系統菜單。

建立一個CToolBar的派生類CxxToolBar,在新類中的左鍵輕按兩下(CxxToolBar::OnLButtonDblClk(...))

和左鍵單擊(CxxToolBar:: OnLButtonDown(...))涵數中分别加入下面代碼既可:

if (IsFloating()) //工具條正在浮動狀态中

{

  CWnd* pMiniFrame;

  CWnd* pDockBar;

  pDockBar = GetParent();

  pMiniFrame = pDockBar->GetParent();

  //去除其上系統菜單

  pMiniFrame->ModifyStyle(WS_SYSMENU, NULL);

  //重繪工具條

  pMiniFrame->ShowWindow(SW_HIDE);

  pMiniFrame->ShowWindow(SW_SHOW);

}

3、禁止視窗最大化按鈕

在PreCreateWindow()涵數中去掉WS_MAXIMIZEBOX風格顯示既可。

BOOL CxxFrameWnd::PreCreateWindow(CREATESTRUCT& cs)

{

  cs.style &= ~WS_MAXIMIZEBOX;

  return CFrameWnd::PreCreateWindow(cs);

}

42.如何拷貝一個工程的對話框資源到另一個工程中?

 有兩種方法可以實作:

 

 1)你可以直接拷貝resource,用VC++以文本的方式或者直接用文本編輯器打開.rc檔案,将有關的片段從

一個工程拷貝到另一個工程.你可以通過查找如下字樣的片段(此片段用來定義對話框資源)來拷貝你要

的部分:

 

 IDD_MYDIALOG_ID DIALOG DISCARDABLE 0, 0, 235, 55

 

 這裡的IDD_MYDIALOG_ID是你的對話框的ID,将到此片段結尾的部分全拷下來,通常你還要給新的工程

加一個ID(通過DevStudio的工具或者直接修改resource.h檔案).

 2)可以通過DevStudio的copy/paste功能.首先,在編輯器以"auto"模式打開.rc檔案,這時resource

正确的顯示出來.然後,選中要拷貝的對話框的ID,在Edit菜單裡選Copy或者按住Ctrl+C.然後打開目标

resource檔案,在Edit菜單裡選Paste或者按住Ctrl+V.

43.如何實作點一下對話框外面的區域,自動隐藏對話框?

 [問題提出]

  如果想在點選對話框外面的地方使得對話框關閉,該如何做?

 [解決方法]

  試試下面的代碼,原理是在激活對話框時,捕獲滑鼠的動作,當滑鼠點選時判斷是否點選在對話框外,是的話就釋放對話框.

 [程式實作]

  建立名為My的對話框程式.實作如下步驟:

  在MyDlg.h中加入:

  class CShowWindow1Dlg : public CDialog

  {

   // Construction

   public:

     int m_cx;

     int m_cy;

     ......

  };

  在MyDlg.cpp中:

  //定義消息映象,處理滑鼠單擊及激活

  BEGIN_MESSAGE_MAP(CMyDlg, CDialog)

    //{{AFX_MSG_MAP(CMyDlg)

    ON_WM_LBUTTONDOWN()

    ON_WM_ACTIVATE()

    //}}AFX_MSG_MAP

  END_MESSAGE_MAP()

  void CMyDlg::OnLButtonDown(UINT nFlags, CPoint point)

  {

    CRect rect;

    GetClientRect(&rect);

    rect.InflateRect(m_cx, m_cy);

 

    //Release dialog if the user click outside it.

    if(!rect.PtInRect(point))

    {

      EndDialog(IDCANCEL);

    }

    CDialog::OnLButtonDown(nFlags, point);

  }

  void CMyDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)

  {

    CDialog::OnActivate(nState, pWndOther, bMinimized);

    if( nState == WA_ACTIVE || nState == WA_CLICKACTIVE)

      SetCapture();

    else

      ReleaseCapture();

  }

  BOOL CMyDlg::OnInitDialog()

  {

    CDialog::OnInitDialog();

    .....

    

    OSVERSIONINFO info;

    memset((char*)&info, 0, sizeof(OSVERSIONINFO));

    info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

    if(GetVersionEx(&info))

    { //we don't run on Win32s, so check only two values

      if(info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)

      { //On windows 95

       m_cx = GetSystemMetrics(SM_CXFIXEDFRAME);

       m_cy = GetSystemMetrics(SM_CYFIXEDFRAME);

      }

      else

      { //On NT

       m_cx = GetSystemMetrics(SM_CXDLGFRAME);

       m_cy = GetSystemMetrics(SM_CYDLGFRAME);

      }

    }

  }

   說明:

   1)WM_ACTIVATE消息在ClassWizard中沒有,按如下步驟添加,右擊CMyDlg類,選Add Windows Message Handle,接着在Filter for messages available to中選Window,在New Windows messages/events清單中就會出現WM_ACTIVATE,選中,點選Add Handler

   2)SM_CXDLGFRAME,SM_CYDLGFRAME  NT中取得有WS_DLGFRAMEstyle風格的視窗的高和寬 95中已經廢棄而采用SM_CX_FIXEDFRAME和SM_CYFIXEDFRAME

44. 初始化應用程式的大小

如果想使應用程式界面(文檔)在開始運作是按你的尺寸展現在螢幕上,

 添加代碼如下:

 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

 {

   int xsize=::GetSystemMetrics(SM_CXSCREEN);

   int ysize=::GetSystemMetrics(SM_CYSCREEN);

   cs.cx=xsize*5/10;

   cs.cy=ysize*5/10;

   cs.x=(xsize-cs.cx)/2;

   cs.y=(ysize-cs.cy)/2; 

 }

 其中的5/10是你的初始界面占螢幕的百分比,可以自己修改。如果想使應用程式大小固定添加cs.style&=~WS_THICKFRAME;

45. 如何得到視圖指針?

[問題提出]

  現在你有一個多線程的Demo,你想在多線程裡處理視圖指針裡的函數,我們給這個函數起個名字:Put();該如何實作呢?

  //有兩種方法可以實作你的要求:

  //1)第一種方法:

  //要是多線程不是在App.cpp裡出現,那麼要在多線程的.cpp中加上extern CYourApp theApp;

  //獲得文檔模闆:

  POSITION curTemplatePos = theApp.GetFirstDocTemplatePosition();

  CDocTemplate *m_doc=theApp.GetNextDocTemplate(curTemplatePos);

  //獲得文檔:

  curTemplatePos=m_doc->GetFirstDocPosition();

  CYourDoc *m_pdoc=(CA8Doc*)m_doc->GetNextDoc(curTemplatePos);

 

  //獲得視圖:

  curTemplatePos=m_pdoc->GetFirstViewPosition();

  CYourView *m_pview=(CYourView*)m_pdoc->GetNextView(curTemplatePos);

  //調用視圖函數:

  m_pview->Put();

  //2)第二種方法:

  //獲得窗體指針:

  CMainFrame *pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;

  //獲得與該窗體符合的視圖:

  CYourView *m_pView = (CYourView *) pFrame->GetActiveView();

  //調用視圖函數:

  m_pView->Put();

46. 如何使我的程式在啟動時不建立一個新文檔?

[問題]

如何使我的程式在啟動時不建立一個新文檔?

[解答]

在程式的InitInstance中的ProcessShellCommand函數之前加入: cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing

47. 如何将标題欄上的右鍵菜單屏蔽掉?

 [解決方法]

  右鍵菜單是系統菜單,隻要将其WS_SYSMENU的屬性去掉即可.

 [程式實作]

  int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

  {

     ........

  long style = GetWindowLong(m_hWnd, GWL_STYLE);

     style &= ~WS_SYSMENU;

     SetWindowLong(m_hWnd, GWL_STYLE, style);

  return 0;

  }

48.如何全屏顯示(沒有标題,沒有菜單,沒有工具條)

 [解決方法]

  重載CMainFrame的ActivateFrame函數:

  void CMainFrame::ActivateFrame(int nCmdShow)

  {

     CRect cRectdesktop;

     WINDOWPLACEMENT windowplacement;

     ::GetWindowRect(::GetDesktopWindow(),&cRectdesktop);

     ::AdjustWindowRectEx(&cRectdesktop,GetStyle(),TRUE,GetExStyle());

     windowplacement.rcNormalPosition=cRectdesktop;

     windowplacement.showCmd=SW_SHOWNORMAL;

     SetWindowPlacement(&windowplacement);

     CFrameWnd::ActivateFrame(nCmdShow);

  }

49.如何設定有背景顔色的文本

(1)[解決方法]

  用到了CDC::SetBkMode();

 

 [程式實作]

  void CMyView::OnDraw(CDC* pDC)

  {

    CMyDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    CRect rcView;//加這兩句

    GetClientRect(rcView);

    // TODO: add draw code for native data here

    CString str (_T("Perfect Text..."));

    pDC->SetBkMode(TRANSPARENT);

    rcView.OffsetRect (1,1);

    pDC->SetTextColor(RGB (0,0,0));

    pDC->DrawText(str,str.GetLength(),rcView,DT_SINGLELINE | DT_CENTER | DT_VCENTER);

    rcView.OffsetRect(-1,-1);

    pDC->SetTextColor(RGB (255,0,0));

    pDC->DrawText(str,str.GetLength(),rcView,DT_SINGLELINE | DT_CENTER | DT_VCENTER);

  }

(2) 建立名為My的SDI或MDI,并響應WM_ERASEBKGND.

  BOOL CMyView::OnEraseBkgnd(CDC* pDC)

  {

   // TODO: Add your message handler code here and/or call default

   CBrush Brush (RGB(114,147,171));

   // Select the brush into the device context .

   CBrush* pOldBrush = pDC->SelectObject(&Brush);

   // Get the area that needs to be erased .

   CRect ViewClip;

   pDC->GetClipBox(&ViewClip);

   //Paint the area.

   pDC->PatBlt(ViewClip.left,ViewClip.top,ViewClip.Width(),ViewClip.Height(),PATCOPY);

   //Unselect brush out of device context .

   pDC->SelectObject (pOldBrush );

   // Return nonzero to half fruther processing .

   return TRUE;

   return CView::OnEraseBkgnd(pDC);

  }

  此方法也适合基類是EditView的SDI或MDI的情況,但是字型的顔色和底色不行.建議用WM_CTLCOLOR.

50.串太長時往讓其末尾顯示一個省略号(在SDI或MDI的View中)

 [問題提出]

  如何在串太長時往讓其末尾顯示一個省略号(在SDI或MDI的View中)?

 [程式實作]

  建立名為My的SDI或MDI工程.

  void CMyView::OnDraw(CDC* pDC)

  {

    CMyDoc* pDoc = GetDocument();

    ASSERT_VALID(pDoc);

    // TODO: add draw code for native data here

    pDC->DrawText(CString("It's a long string,so we will add a '...' at the end."),CRect (110, 110, 180, 130),DT_LEFT | DT_END_ELLIPSIS);

    //Add ellpsis to middle of string if it does not fit

    pDC->DrawText(CString("It's a long string,so we will add a '...' at the end."),CRect (110, 140, 300, 160),DT_LEFT | DT_PATH_ELLIPSIS);

  }