VC6中怎样在对话框中使用状态栏,请附源程序!(MFC)

etoy 2000-08-25 08:08:00
...全文
217 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
jumpinwind 2001-03-26
  • 打赏
  • 举报
回复
think
panda_w 2001-03-07
  • 打赏
  • 举报
回复
Toolbars and Statusbars on Dialogs
:::
By default, MFC only allows you to add Toolbars and Statusbars on CFrameWnd subclassed objects. This is great, but if you want to add toolbars on dialogs, you're like an idiot, because you can't do this easily.

The first problem is that every handler function expect the parent to be a CFrameWnd subclassed object, and another one is that you can only show tooltips or statusbar message when the dialog is in IDLE state. In fact, for the control bars to function properly, you'll have to catch some of the messages that the frame window uses.

I'll have to dig a lot in the documentation to find something that helps me doing that. One issue was shown me by Mihai Filimon (see articles posted on Monday 16 march 1998), which was fine, but not very "clean" since you have to make room for the bar with an invisible static object. (I thanks a lot him for showing the light at the end of the tunnel).

Let me expose you what to do if you want a toolbar (fixed, there is no other way possible) and a menu which can talk with any StatusBar in the application (even in the dialog but I think it will be the subject of another article).

I’ll only expose you how to add a Toolbar on a dialog (the menu is obvious since you only have to define one and add it on the resource editor).

First, you’ll have to develop your dialog (with its object) without bothering the place of the ToolBar, and subclass the CDialog class to use this dialog template (nothing new here).

Then, add this code on the CDialog::OnInitDialog function (the m_wndToolBar variable is of type CToolBarEx) :


BOOL CMyDlg::OnInitDialog()
{
// TODO: Add extra initialization here
CDialog::OnInitDialog();

// Add the ToolBar.
if (!m_wndToolBar.Create( this ) ||
!m_wndToolBar.LoadToolBar(IDR_CORPS_EMIS) )
{
TRACE0("Failed to create toolbar\n");
return -1; // fail to create
}

// TODO: Remove this if you don't want tool tips or a resizeable toolbar
m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |
CBRS_TOOLTIPS | CBRS_FLYBY );

// We need to resize the dialog to make room for control bars.
// First, figure out how big the control bars are.
CRect rcClientStart;
CRect rcClientNow;
GetClientRect(rcClientStart);
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST,
0, reposQuery, rcClientNow);

// Now move all the controls so they are in the same relative
// position within the remaining client area as they would be
// with no control bars.
CPoint ptOffset(rcClientNow.left - rcClientStart.left,
rcClientNow.top - rcClientStart.top);

CRect rcChild;
CWnd* pwndChild = GetWindow(GW_CHILD);
while (pwndChild)
{
pwndChild->GetWindowRect(rcChild);
ScreenToClient(rcChild);
rcChild.OffsetRect(ptOffset);
pwndChild->MoveWindow(rcChild, FALSE);
pwndChild = pwndChild->GetNextWindow();
}

// Adjust the dialog window dimensions
CRect rcWindow;
GetWindowRect(rcWindow);
rcWindow.right += rcClientStart.Width() - rcClientNow.Width();
rcWindow.bottom += rcClientStart.Height() - rcClientNow.Height();
MoveWindow(rcWindow, FALSE);

// And position the control bars
RepositionBars(AFX_IDW_CONTROLBAR_FIRST, AFX_IDW_CONTROLBAR_LAST, 0);

return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}

You can see that it is not obvious (I found it in a more complicated sample called DLGCBR32, and I work a lot to find out the functions that are compulsory, and the others)

At that point, you have only a Toolbar in top of your dialog (you see that any toolbar can fit the requirements to be shown in a dialog, since the preceding code is generic enough). You can have many toolbars in your dialog, but you must manage the positions by yourself.

Now, if you want tooltips on your Toolbar, you must handle the following messages TTN_NEEDTEXTA and TTN_NEEDTEXTW (for both ANSI and Unicode characters sets), in the following way :

1. Add the message handlers declaration...

BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
...
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()

2. Declare the function in your header file that way :

// Generated message map functions
//{{AFX_MSG(CMyDlg)
afx_msg BOOL OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult);
//}}AFX_MSG

3. And finally code your OnToolTipText function that way (comes from MFC Sample) :

BOOL CMyDlg::OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult)
{
ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);

// allow top level routing frame to handle the message
if (GetRoutingFrame() != NULL)
return FALSE;

// need to handle both ANSI and UNICODE versions of the message
TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
TCHAR szFullText[256];
CString cstTipText;
CString cstStatusText;

UINT nID = pNMHDR->idFrom;
if (pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND) ||
pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND))
{
// idFrom is actually the HWND of the tool
nID = ((UINT)(WORD)::GetDlgCtrlID((HWND)nID));
}

if (nID != 0) // will be zero on a separator
{
AfxLoadString(nID, szFullText);
// this is the command id, not the button index
AfxExtractSubString(cstTipText, szFullText, 1, '\n');
AfxExtractSubString(cstStatusText, szFullText, 0, '\n');
}

// Non-UNICODE Strings only are shown in the tooltip window...
if (pNMHDR->code == TTN_NEEDTEXTA)
lstrcpyn(pTTTA->szText, cstTipText,
(sizeof(pTTTA->szText)/sizeof(pTTTA->szText[0])));
else
_mbstowcsz(pTTTW->szText, cstTipText,
(sizeof(pTTTW->szText)/sizeof(pTTTW->szText[0])));
*pResult = 0;

// bring the tooltip window above other popup windows
::SetWindowPos(pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0,
SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE);


return TRUE; // message was handled
}

Now you have a toolbar with tooltips (the text shown in the tooltip box is defined the classic way, with the resource editor). (pheeew ;-) ).

Now, if you want the mainframe's status bar to display the text that would normally be prompted, the only line (right, the ONLY one) of code you have to add is in the above function (it is useful for System modal dialog boxes since they are usually small), just before the return statement (it also assume that m_wndStatusBar is public) :


// Display the text in the mainframe's status bar (assumes the Help pane text
// is at the index zero.
((CMainFrame*)GetParent())->m_wndStatusBar.SetPaneText(0, cstStatusText);

That's all for today.

No, let me tell you just one more thing, if you want your dialog menu to display text in the mainframe's status bar (on in any other status bar you have created) you can add the following code to the handler of WM_MENUSELECT (window-type handler) :


void CMyDlg::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
{
CDialog::OnMenuSelect(nItemID, nFlags, hSysMenu);

TCHAR szFullText[256];
CString cstStatusText;
// TODO: Add your message handler code here
// Displays in the mainframe's status bar
if (nItemID != 0) // will be zero on a separator
{
AfxLoadString(nItemID, szFullText);
// this is the command id, not the button index
AfxExtractSubString(cstStatusText, szFullText, 0, '\n');
((CMainFrame*)GetParent())->m_wndStatusBar.SetPaneText(0,cstStatusText);
}
}


Note that you can't use the ON_UPDATE_COMMAND_UI message on this toolbar, since it can only be refresh when the dialog enters in idle state. To do so, you must subclass the CToolBar (or CStatusBar) class - in CMyToolBar for instance -, add the message handler for WM_IDLEUPDATECMDUI, and write the following code in this function :


/////////////////////////////////////////////////////////////////////////////
// CMyToolBar::OnIdleUpdateCmdUI
// OnIdleUpdateCmdUI handles the WM_IDLEUPDATECMDUI message, which is
// used to update the status of user-interface elements within the MFC
// framework.
//
// We have to get a little tricky here: CToolBar::OnUpdateCmdUI
// expects a CFrameWnd pointer as its first parameter. However, it
// doesn't do anything but pass the parameter on to another function
// which only requires a CCmdTarget pointer. We can get a CWnd pointer
// to the parent window, which is a CCmdTarget, but may not be a
// CFrameWnd. So, to make CToolBar::OnUpdateCmdUI happy, we will call
// our CWnd pointer a CFrameWnd pointer temporarily.

LRESULT CMyToolBar::OnIdleUpdateCmdUI(WPARAM wParam, LPARAM)
{
if (IsWindowVisible())
{
CFrameWnd *pParent = (CFrameWnd *)GetParent();
if (pParent)
OnUpdateCmdUI(pParent, (BOOL)wParam);
}
return 0L;
}


In order to have the toolbar updated you MUST override the ContinueModal() function that way:


BOOL CMyDlg::ContinueModal()
{
m_wndToolbar.SendMessage( WM_IDLEUPDATECMDUI, WPARAM(TRUE), 0);


return CDialog::ContinueModal();
}


For AfxLoadString to compile you must Include the file "Afxpriv.h" at the beginning of the CPP file.
ufc 2000-09-10
  • 打赏
  • 举报
回复
我给你源程序,请给我加分
在对话框中加状态栏上如下实现
在OnInitDialog中或其它适当的位置加如下代码:

CStatusBarCtrl *m_StaBar=new CStatusBarCtrl;
RECT m_Rect;
GetClientRect(&m_Rect);
m_Rect.top=m_Rect.bottom-20;
m_StaBar->Create(WS_BORDER|WS_VISIBLE|CBRS_BOTTOM,m_Rect,this,3);
m_StaBar->ShowWindow(SW_SHOW);

这样就行了,至于向里面加别的,就可以参考CStatusBarCtrl类参考了.





etoy 2000-08-29
  • 打赏
  • 举报
回复
该问题已经通过查阅官方资料解决!
Ideal 2000-08-26
  • 打赏
  • 举报
回复
在对话框中加入 ToolBar 你会吗?方法或许一样(我没试过,我只试过加入 ToolBar)。

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧