Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1609598
  • 博文数量: 585
  • 博客积分: 14610
  • 博客等级: 上将
  • 技术积分: 7402
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-15 10:52
文章存档

2013年(5)

2012年(214)

2011年(56)

2010年(66)

2009年(44)

2008年(200)

分类: C/C++

2012-01-27 03:45:11

MFC 技巧之四
分类: 2.3 VC技巧收集 178人阅读 评论(0) 收藏 举报
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”或者“”启动 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); 
  }
阅读(733) | 评论(0) | 转发(0) |
0

上一篇:MFC 技巧之六

下一篇:MFC 技巧之五

给主人留下些什么吧!~~