Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1675983
  • 博文数量: 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:52:25

 MFC 技巧之一
分类: 2.3 VC技巧收集 199人阅读 评论(0) 收藏 举报

1."属性页的添加 :

创建对话框的类,该类要从CpropertyPage继承;然后在要添加该对话框为属性页的类(头文件)里创建CpropertySheet类的一个对象 m_tabsheet和新创建的对话框类的对象m_skatch;最后,在.cpp文件里的OnInitDialog()之类的函数里实现如下代码:
m_tabsheet.Create(this, WS_CHILD | WS_VISIBLE, 0);
"//使选项卡的按钮在下面
"if(m_tabsheet.m_hWnd)
"m_tabsheet.ShowWindow(SW_MAXIMIZE);//显示选项卡
//加入标签,标签名由各个子对话框的标题栏决定
"m_tabsheet.AddPage(&m_skatch);
"//用Create来创建一个属性页
"m_tabsheet.Create(this, WS_CHILD | WS_VISIBLE, WS_EX_CONTROLPARENT);
"
RECT rect;
"m_tabsheet.GetWindowRect(&rect);
"int width = rect.right - rect.left;
"int height = rect.bottom - rect.top;
"
"//调整属性页的大小和位置
"m_tabsheet.SetWindowPos(NULL, 225, 225, width-82, height,SWP_NOACTIVATE);
属性页的添加完成。如果要添加多个属性页,则只需要增加多个对象,如下:m_tabsheet.AddPage(&m_skatch1);
  m_tabsheet.AddPage(&m_skatch2);
. . . . . .


或者

Example

    下面代码演示创建一个属性对话框,通过 CPropertySheet类 用来创建属性窗口,CPropertyPage类为该属性窗口的创建多页时使用,

// This code fragment shows how to create a modeless property sheet // dialog in a command message handler (OnModelessPropertySheet()) // of a CView-derived class.
void CMyView::OnModelessPropertySheet() { // Declare a CPropertySheet object.                              m_dlgPropertySheet is a data      // member of type CPropertySheet in CView-derived class.
     m_dlgPropertySheet = new CPropertySheet("Simple PropertySheet");          ASSERT(m_dlgPropertySheet); // Add two pages to the CPropertySheet object.  Both m_stylePage and // m_colorPage are data members of type CPropertyPage-derived classes // in CView-derived class.
 m_stylePage = new CStylePage;
 m_colorPage = new CColorPage;
 m_dlgPropertySheet->AddPage(m_stylePage);
m_dlgPropertySheet->AddPage(m_colorPage); // Create a modeless CPropertySheet dialog. m_dlgPropertySheet->Create(); 
 } 
// The code fragment below shows how to destroy the C++ objects for // propertysheet and propertypage in the destructor of CView-derived // class. // NOTE:  DestroyWindow() is called in CPropertySheet::OnClose() so // you do not need to call it here.  Property pages are children // of the CPropertySheet, they will be destroyed by their parents.
//在程序结束时删除创建的对象
 CMyView::~CMyView() {
 if (m_dlgPropertySheet) { 
 delete m_stylePage;
 delete m_colorPage;
 delete m_dlgPropertySheet; } } 
2."List Control中标题栏(Column)的添加 :

创建一个List Control,其ID为IDC_LIST,在其Styles属性项下的View项里选择Report、Align项里选择Top、Sort项里选择None.
然后在该List所在对话框的类(头文件)里创建ClistCtrl的一个对象m_list然后在.cpp文件的OnInitDialog()之类的函数里实现如下代码:
CString strname[3];
strname[0]="Screen Name";
strname[1]="Form ID";
strname[2]="Category Path";
for(int i=0;i<3;i++)
{
m_List.InsertColumn(i,strname[i],LVCFMT_LEFT,130);
}
在这之前也要将List Control的ID与ClistCtrl的对象m_list在DoDataExchange(CDataExchange* pDX)函数里绑定,如下:
DDX_Control(pDX, IDC_LIST, m_List);

3."ToolBar和StatusBar中控件的添加 :

方法⑴.只能在ToolBar里创建控件:首先,在ToolBar中创建一个Button,其ID为ID_TOOL_COMBO(我们要将创建的控件放在该Button的位置上).
其次,新创建一个类CMainToolBar,要从CToolBar继承(创建过程大概如下:选择工程/增加到工程/新的类;也可以选择工程的根,然后点 击右键,选择新的类;或者CTL+W,选择增加类/新的类 --- 然后在class type里选择Generic Class,在Name栏里输入新类的名字,Base class里输入CToolBar),创建成功后在该类里创建要增加的控件的对象,如:
CComboBox""m_wndMyCombo; 
CStatic""m_wndCategory, m_wndCategoryPath;
CButton""m_wndOpenButton;
Cedit"""m_wndEdit;
然后在构造函数里初始化如:
m_wndMyCombo.m_hWnd = NULL;
m_wndCategory.m_hWnd = NULL;
m_wndCategoryPath.m_hWnd = NULL;
m_wndOpenButton.m_hWnd = NULL;
m_wndEdit.m_hWnd = NULL;
接着在CMainframe的头文件里创建CMainToolBar的一个对象m_wndToolBar,最后在.cpp文件的OnCreate函数的最后实现如下:
"int index = 0;
"CRect rect;  // 可定义在头文件当中
"// ComboBox
"{
""//找到指定的工具项
""while(m_wndToolBar.GetItemID(index)!=ID_TOOL_COMBO)
"""index++;
""//设置指定工具项的宽度并获取新的区域 120是宽度
""m_wndToolBar.SetButtonInfo(index, ID_TOOL_COMBO, TBBS_SEPARATOR, 120);
""m_wndToolBar.GetItemRect(index, &rect);
""
""//设置位置
""rect.top+=1;
""rect.bottom += 200;
""
""// 创建并显示控件
""if(!m_wndToolBar.m_wndMyCombo.Create(WS_CHILD|WS_VISIBLE| CBS_AUTOHSCROLL| 
"""CBS_DROPDOWNLIST | CBS_HASSTRINGS , rect, &m_wndToolBar, ID_TOOL_COMBO))
""{ 
"""TRACE0("Failed to create combo-box/n");
"""return FALSE;
""}
""m_wndToolBar.m_wndMyCombo.ShowWindow(SW_SHOW);
""
""//填充内容"
""m_wndToolBar.m_wndMyCombo.AddString("25%");
""m_wndToolBar.m_wndMyCombo.AddString("50%");
""m_wndToolBar.m_wndMyCombo.AddString("75%");
"
""//选择默认项
""m_wndToolBar.m_wndMyCombo.SetCurSel(0);
""
""//获取到内容并MSGBOX显示出来
""CString strContent;
""m_wndToolBar.m_wndMyCombo.GetWindowText(strContent);

""index = 0;
"}
其他控件都类似创建(只需要注意一下各自的Create函数的参数即可)。
方法⑵.这种方法创建不太容易控制:直接在CMainframe的头文件中创建要增加的控件的对象,如CButton"的对象 m_wndAboutButton,然后创建CToolBar或者CstatusBar的对象,如:CstatusBar的对象 _wndStatusBar;再增加几个函数如下:
Protected:
virtual void RecalcLayout(BOOL bNotify = TRUE);
"afx_msg void CMainFrame::OnViewStatusBar();
接着在.cpp文件中将StatusBar的ID和OnViewStatusBar 函数绑定在一起,如下所示:BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
"  // {{AFX_MSG_MAP(CMainFrame)
"  ON_COMMAND(ID_VIEW_STATUS_BAR, OnViewStatusBar)
"  ON_WM_CREATE()
"  // }}AFX_MSG_MAP
END_MESSAGE_MAP()
然后Create函数的最后(返回值之前)实现如下代码:
CRect rc;
"VERIFY(m_wndAboutButton.Create(_T("MyAbout"),
""  WS_VISIBLE,rc,this,ID_APP_ABOUT));

"// TODO: Remove this if you don't want tool tips or a resizeable toolbar
"m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
"CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);
再在RecalcLayout函数里实现:
CRect rc;
if (m_wndStatusBar.m_hWnd)
{
""m_wndStatusBar.GetWindowRect(&rc);
""ScreenToClient(&rc);
""rc.right -= 50;
""m_wndStatusBar.SetWindowPos(NULL,rc.left,rc.top,rc.Width(),rc.Height(),
"""SWP_NOZORDER);

""rc.left = rc.right;
""rc.right += 50;
""m_wndAboutButton.SetWindowPos(NULL,rc.left,rc.top,rc.Width(),rc.Height(),
"""SWP_NOZORDER);
"}
最后在OnViewStatusBar()里实现:
BOOL bShow = m_wndStatusBar.GetStyle() & WS_VISIBLE;
"m_wndAboutButton.SetWindowPos(NULL, 0, 0, 0, 0,
SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|
(bShow ? SWP_SHOWWINDOW : SWP_HIDEWINDOW));
ToolBar中的创建与此相同,只需更改一下句柄即可。

4."通过Control创建的控件,对其属性的动态控制 :

在对话框类的头文件里创建所要改变属性的控件的对象,如要改变一个Button(其ID为IDC_MyButton)的属性,则需创建Cbutton的对 象m_button。然后在.cpp中的DoDataExchange函数里将Button的ID和创建的对象绑定在一起:
//{{AFX_DATA_MAP(CPrintDlg)
""// NOTE: the ClassWizard will add DDX and DDV calls here
"DDX_Control(pDX, IDC_MyButton, m_button);
"//}}AFX_DATA_MAP
然后可以在该函数的最后进行初始化:
"m_button.EnableWindow(FALSE);
到这里已经实现了改变属性。如果要动态改变其属性,可如下实现(通过两个Button的点击改变起属性):
// RadioAll Button的点击响应函数
void CPrintDlg::OnRadioAll() 
{
""// TODO: Add your control notification handler code here
""m_button.EnableWindow(TRUE);
}

// RadioSelect Button的点击响应函数
void CPrintDlg::OnRadioSelect() 
{
""// TODO: Add your control notification handler code here
""m_button.EnableWindow(FALSE);
}
也可以通过一个Check Button的点击来改变,在其点击响应函数里实现:
m_button.EnableWindow(!m_button.IsWindowEnabled());
其余控件属性的改变都如此。

5."窗口的分割与停靠 :                        
一、新建一个类CMySplitter,基类为CSplitterWnd
二、重载该类的OnMouseMove函数:
void CMySplitter::OnMouseMove(UINT nFlags, CPoint point)

"// 限制切分条的运动范围。 
"if(point.x<228||point.x>600) 
"{ 
""CWnd::OnMouseMove(nFlags, point); 
"} 
"else 
"{ 
""CSplitterWnd::OnMouseMove(nFlags, point); 
"} 
}
三、 然后就可以跟一般的窗口分割那样去做了,if(point.x<228||point.x>600)这里的范围可以随你去设置了 ^_^,够简单吧。 
四、切分窗口 
在MaiFram.h建立切分条对象:
protected: 
CMySplitter m_wndSplitter; //切分窗口对象 
//在MaiFram.cpp中实现窗口切分: 
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/,CCreateContext* pContext) 

"// 创建拆分器窗口 
if (!m_wndSplitter.CreateStatic(this, 1, 2)) 
""return FALSE; 
if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CLeftView),CSize(228,100), pContext) ||!m_wndSplitter.CreateView(0,1, RUNTIME_CLASS(CDataEditView), CSize(100, 100), pContext)) 
"{ 
""m_wndSplitter.DestroyWindow(); 
""return FALSE; 
"} 

"return TRUE; 
}


6. ①怎样在程序开始的时候让它最大化? 
②vc++做出来的exe文件在窗体的右上方是没有最大化和最小化按钮的,怎样实现这一功能? 
③如何在显示窗口时,使最大化按钮变灰?

①在App类里的C…App::InitInstance()中把m_pMainWnd->ShowWindow(SW_SHOW)改成m_pMainWnd->ShowWindow(SW_MAXIMIZE);
②在CreateWidnow时用WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX 风格.
  ③ 第一种方法:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 

if( !CFrameWnd::PreCreateWindow(cs) ) 
return FALSE; 
// TODO: Modify the Window class or styles here by modifying 
// the CREATESTRUCT cs 
// disable the maxmini box 
cs.style &= ~WS_MAXIMIZEBOX; 
return TRUE; 
}
第二种方法:
CMenu *pMenu=AfxGetApp()->m_pMainWnd->GetSystemMenu(FALSE); 
     int x=pMenu->GetMenuItemCount( ); 
     UINT pID=pMenu->GetMenuItemID(x-1); 
     pMenu->EnableMenuItem(pID, MF_DISABLED);
第三种方法:
ModifyStyle(WS_MAXIMIZEBOX, 0); 
这个函数也可以是最大化按钮失效! 
并且可以在程序中动态的改变窗口的风格

7. 更改属性页标题 

void CProSheet::SetPageTitle(int nPage, int nImage, CString strTitle)
{
 TC_ITEM item;
 //item.mask = TCIF_TEXT|TCIF_IMAGE;  //设置图标+文字
 item.mask = TCIF_IMAGE;    //只设置图标
 item.iImage = nImage;
// item.pszText = strTitle.GetBuffer(0);  //设置文字
 GetTabControl ()->SetItem (nPage, &item);
//要设置文字时就将上面2行有注释符的代码前的注释符去掉
}

8. 创建动态菜单 

void CMainFrame::OnSelectState(NMTOOLBAR* pnmtb, LRESULT *plr) 

"CMenu menu; 
"if(!menu.CreateMenu()) 
"return; 
"menu.AppendMenu(MF_STRING,0,"开始"); 
"menu.AppendMenu(MF_STRING,0,"结束"); 
"CRect rc; 
"m_wndToolBar.SendMessage(TB_GETRECT, pnmtb->iItem, (LPARAM)&rc); 
"m_wndToolBar.ClientToScreen(&rc); 
"menu.TrackMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_VERTICAL, 
"""rc.left, rc.bottom, this, &rc); 
//"menu.DestroyMenu(); 
"menu.detach();
}
9.关于打印 

1.要打印哪个视就 
((CMainFrame*)AfxGetMainWnd())->m_wndSplitter.SetActivePane(...) 
//要打印的那个视对应的Pane

2.有一个单文档工程,文档窗口被切分:左视图由CTreeView 的派生类管理,右视图由CListView 的派生类CMyListView(其为风格为LVS_REPORT)管理,我想为右视图添加打印和打印预览,我在MyListView.cpp中添加了 
  ON_COMMAND(ID_FILE_PRINT,CListView::OnFilePrint) 
  ON_COMMAND(ID_FILE_PRINT_PREVIEW,CListView::OnFilePrintPreview)还有 
  BOOL CMyListView::OnPreparePrinting(CPrintInfo* pInfo) 
  { 
     // TODO: call DoPreparePrinting to invoke the Print dialog box 

     // return CListView::OnPreparePrinting(pInfo); 
     pInfo->SetMaxPage(2); 
     BOOL bret=DoPreparePrinting(pInfo); 
     pInfo->m_nNumPreviewPages=2; 
     return bret; 
  }
3. 下面是从MSDN中摘出来的一段,是用来改变消息路由的。用了这段代码之后,CView中的消息(菜单,控件,子窗口)将先被CMyShape类来处理。不知道你要的是不是这样的效果。 

  // This example illustrates extending the framework's standard command 
  // route from the view to objects managed by the view. This example 
  // is from an object-oriented drawing application, similar to the 
  // DRAWCLI sample application, which draws and edits "shapes". 

  BOOL CMyView::OnCmdMsg(UINT nID, int nCode, void* pExtra, 
    AFX_CMDHANDLERINFO* pHandlerInfo) 
  { 
      // Extend the framework's command route from the view to 
      // the application-specific CMyShape that is currently selected 
      // in the view. m_pActiveShape is NULL if no shape object 
      // is currently selected in the view. 
      if ((m_pActiveShape != NULL) 
        && m_pActiveShape->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) 
       return TRUE; 

      // If the object(s) in the extended command route don't handle 
      // the command, then let the base class OnCmdMsg handle it. 
      return CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); 
     } 

     // The command handler for ID_SHAPE_COLOR (menu command to change 
     // the color of the currently selected shape) was added to 
     // the message map of CMyShape (note, not CMyView) using ClassWizard.  

     // The menu item will be automatically enabled or disabled, depending 
     // on whether a CMyShape is currently selected in the view, that is, 
     // depending on whether CMyView::m_pActiveView is NULL. It is not 
     // necessary to implement an ON_UPDATE_COMMAND_UI handler to enable 
     // or disable the menu item.  

   BEGIN_MESSAGE_MAP(CMyShape, CCmdTarget) 
    //{{AFX_MSG_MAP(CMyShape) 
    ON_COMMAND(ID_SHAPE_COLOR, OnShapeColor) 
    //}}AFX_MSG_MAP 
   END_MESSAGE_MAP() 

如果你只是想调用OnFilePrint( )函数,可以试一试下面的代码,就和调用其它类中的函数一样。 

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

// Get the active MDI child window. 
CMDIChildWnd *pChild = 
       (CMDIChildWnd *) pFrame->GetActiveFrame(); 

// or CMDIChildWnd *pChild = pFrame->MDIGetActive(); 

// Get the active view attached to the active MDI child 
// window. 
CMyView *pView = (CMyView *) pChild->GetActiveView(); 

pView->OnFilePrint( );


4.
void CMyReportView::OnFileOpen() 

char Filter[] = "Crystal Report files(*.rpt)|*.rpt|All files(*.*)|*.*||"; 
CRect rect; 
CFileDialog OpenDlg(TRUE,0,0,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,(LPCTSTR)Filter,NULL); 
if(OpenDlg.DoModal()!=IDOK) ///显示文件对话框 
return; 
CString m_fName=OpenDlg.GetPathName(); ///取得文件名 
if(m_CrystalReport) 
m_CrystalReport.DestroyWindow(); 
GetClientRect(rect); 
///////////////////创建控件/////////////// 
if (!m_CrystalReport.Create(AfxRegisterWndClass(0, AfxGetApp()->LoadStandardCursor(IDC_ARROW)),WS_CHILD|WS_VISIBLE,rect,this,IDC_CRYSTALREPORT1)) 

AfxMessageBox("控件创建失败!"); 
return ; 

m_CrystalReport.SetWindowParentHandle((long)(this->m_hWnd));///设置父窗口 
m_CrystalReport.SetWindowBorderStyle(0); ///设置为没有边框 
m_CrystalReport.SetWindowLeft(0); ///左空间 
m_CrystalReport.SetWindowTop(0); ///顶部空间 
m_CrystalReport.SetWindowControls(FALSE); ///不显示工具条 
m_CrystalReport.SetReportFileName(m_fName); ///设置报表文件 
m_CrystalReport.SetWindowWidth(rect.Width()); ///设置窗口宽度 
m_CrystalReport.SetWindowHeight(rect.Height()); ///设置窗口高度 
m_CrystalReport.SetFormulas(0, "Company=/"VC知识库/""); ///将报表中的Company变量的值设置为VC知识库 
m_CrystalReport.SetDestination(0); ///设置输出对象是屏幕 
m_CrystalReport.PrintReport(); ///显示报表 

void CMyReportView::OnFilePrint() 

if(m_CrystalReport && m_CrystalReport.GetReportFileName() != "") 

m_CrystalReport.SetDestination(1); ///设置输出对象是打印机 
m_CrystalReport.PrintReport(); ///打印
}

10. Scroll 

创建一个基于CScrollview的SDI Project(在第6步中选CScrollview) 
若你已创建了,这步可以省略。 
然后: 
改为如 
void CTestView::OnInitialUpdate() 

CScrollView::OnInitialUpdate(); 

CSize sizeTotal; 
// TODO: calculate the total size of this view 
sizeTotal.cx = 1024; //改这两个 
sizeTotal.cy = 768;  // 
SetScrollSizes(MM_TEXT, sizeTotal);

 

 

 

PS:本文转载自:http://hi.baidu.com/percommouse/blog/item/63cd0a60fdf0eb40eaf8f8d6.html

阅读(931) | 评论(0) | 转发(0) |
0

上一篇:MFC 技巧之二

下一篇:VC小技巧20个

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