MFC 技巧之六

来源:互联网 发布:linux nmon 编辑:程序博客网 时间:2024/04/27 19:33
71. 隐藏标题栏和菜单栏 
隐藏标题栏 ModifyStyle(WS_CAPTION,0)
隐藏菜单栏 SetMenu(NULL)
72. InflateRect 
InflateRect这个函数用于增大或减小一个矩形的大小.
如m_graphRect.InflateRect(-70, -30, -30, -50);
将矩形左边坐标加70,上面加30,右边减30,下面减50。
73. 怎么让无模式对话框显示在主窗口后面 
要解决这个问题的关键在于CDialog的Create并不能建立一个无属主的窗口.必须用另外方式建窗口.  
  
 比如你的对话框类叫CDlgNoOwner,在CMainFrame中加一个CDlgNoOwner类的成员变量,  
 弹出这个对话框的消息处理函数为  
  
 void  CMainFrame::OnNoowner()   
 {  
CDlgNoOwner  *m_dlgTest=new  CDlgNoOwner(this); 
 HWND  hwndDlg=::CreateDialog(AfxGetInstanceHandle(),MAKEINTRESOURCE(CDlgNoOwner::IDD),NULL/*owner*/,NULL/*dlgproc*/);  
 //注意此处DLGPROC为NULL,并不要紧,因为接下要subclass啦  
 m_dlgTest->SubclassWindow  (hwndDlg);//挂接到成员变量!  
 m_dlgTest->ShowWindow  (SW_SHOW);  
 //这时可以看到一个"自由"的对话框弹出,和你的主窗口是平起平坐的.  
 }  
  
 当然不要忘了在对话框关闭时DestroyWindow()..那都是在对话框类中的标准处理了.
74. 隐藏窗口(子窗口没有焦点时) 

在程序启动时  InitDialog  中使用  SetWindowPos  将窗体设置到屏幕以外
然后再隐藏
1.在OnInitDialog()函数里设置定时器:(WINDOWS  API里面响应消息WM_INITDIALOG)  
  
 SetTimer(1,  1,  NULL);  
  
 2.添加处理WM_TIMER的消息处理函数OnTimer,添加代码:  
  
 if(nIDEvent  ==  1)  
  
 {  
  
 DeleteTimer(1);  
  
 ShowWindow(SW_HIDE);  
  
 }  
75.修改视图背景 
How do I change the background color of a view?

To change the background color for a CView, CFrameWnd, or CWnd object, process the WM_ERASEBKGND message. The following code shows how: 

BOOL CSampleView::OnEraseBkgnd(CDC* pDC)
{
  // Set brush to desired background color.
  CBrush backBrush(RGB(255, 128, 128));
  // Save old brush.
  CBrush* pOldBrush = pDC->SelectObject(&backBrush);
  CRect rect;
  pDC->GetClipBox(&rect);   // Erase the area needed.
  pDC->PatBlt(rect.left, rect.top, rect.Width(), 
  rect.Height(), PATCOPY);
  pDC->SelectObject(pOldBrush);
  return TRUE;
}

I solved the problem like this:

HBRUSH dlgtest::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 
{
  switch (nCtlColor)
  {
    case CTLCOLOR_BTN:
    case CTLCOLOR_STATIC:
    {
      pDC->SetBkMode(TRANSPARENT);
    }
    case CTLCOLOR_DLG:
    {
      CBrush*   back_brush;
      COLORREF  color;
      color = (COLORREF) GetSysColor(COLOR_BTNFACE);
      back_brush = new CBrush(color);
      return (HBRUSH) (back_brush->m_hObject);
    }
  }
  return(CFormView::OnCtlColor(pDC, pWnd, nCtlColor));
}
76. 如何实现点击对话框外的地方使对话框到主窗口的后面 
只能将桌面做为父窗口
pMDlg = new CMDlg;
pMDlg->Create(IDD_M_DIALOG,CWnd::GetDesktopWindow()/* 设置父窗口 */);
pMDlg->ShowWindow(SW_SHOW); 
然后在任务栏里隐藏对话框程序
如何让对话框应用程序在在任务栏上不出现,并且不隐藏窗口。
[解决方法]
  把对话框的扩展属性修改成为WS_EX_TOOLWINDOW。
[程序实现]
  把对话框的属性设置成为toolwindow,然后在需要的地方执行本代码。
  DWORD Style = ::GetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE);
  Style = WS_EX_TOOLWINDOW ;
  AfxGetMainWnd()->ShowWindow(FALSE);
  ::SetWindowLong(AfxGetMainWnd()->m_hWnd,GWL_EXSTYLE,Style); 
  AfxGetMainWnd()->ShowWindow(TRUE);
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中)检查是否需要将窗口居中,你看了这个函数后就明白为什么需要上面那 么做了。
0 0
原创粉丝点击