天天看点

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

继续阅读