65.9K
CodeProject 正在变化。 阅读更多。
Home

位于中间的工具栏

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.83/5 (18投票s)

2003年3月20日

3分钟阅读

viewsIcon

133886

downloadIcon

2306

本文介绍如何将工具栏放置在对话框或窗体的正中间。

Sample Image - ArbTB.jpg

引言

想象一下,你有一个对话框,你可以在其中输入文本和其他与文本相关的数据。虽然文本应该被格式化,但普通的数据条目不应该。因此,你将一个工具栏放入你的对话框中,该工具栏具有你所需的所有格式化按钮,然后你发现它只能停靠在对话框的边缘。但是,我(客户)想要这个东西放在它所属的位置:就在可格式化的文本条目的上方。

为了满足客户的需求,需要做的不仅仅是在窗体中间放置一排按钮。

创建工具栏

Step one

像往常一样创建一个工具栏,并向你的对话框添加一个 CToolBar 成员,赋予它任何适合你的名称。对于格式化工具栏,像 m_wndFormatBar 这样的名称听起来很棒。

在你想让工具栏驻留的位置创建一个静态控件。给这个框架一个ID(例如 IDC_STC_TOOLBARFRAME)。让它比工具略大,这样你就可以看到工具栏占据的空间。在类向导中,为此控件分配一个成员。确保它被分配给 CStatic 而不是 CString。随便给它命名(比如 m_Stc_ToolbarFrame)。

第二步

现在是困难的部分。在你的对话框的 OnInitDialog 方法中,放置以下代码。你可以省略注释。

// Positioning of toolbar
CSize sizeToolbar;
CRect mrect;
mrect.SetRectEmpty();
// attach command routing to dialog window
m_wndFormatBar.Create(this); 
m_wndFormatBar.LoadToolBar(IDR_TOOLBAR_FORMAT);
m_wndFormatBar.SetBarStyle(CBRS_ALIGN_TOP | CBRS_TOOLTIPS | CBRS_FLYBY);
m_wndFormatBar.ShowWindow(SW_SHOW);
// Calculate size of toolbar and adjust size of static control to fit size
sizeToolbar = m_wndFormatBar.CalcFixedLayout(false,true);
m_Stc_ToolbarFrame.GetWindowPlacement(&wpl);
wpl.rcNormalPosition.bottom = wpl.rcNormalPosition.top  + 
                                        sizeToolbar.cy + 4;
wpl.rcNormalPosition.right  = wpl.rcNormalPosition.left + 
                                        sizeToolbar.cx + 4;
// Position static control and toolbar
m_Stc_ToolbarFrame.SetWindowPlacement(&wpl);
m_wndFormatBar.SetWindowPlacement(&wpl);
// Adjust buttons into static control
m_Stc_ToolbarFrame.RepositionBars(AFX_IDW_CONTROLBAR_FIRST, 
    AFX_IDW_CONTROLBAR_LAST, 0);
m_Stc_ToolbarFrame.ShowWindow(SW_HIDE);

工作原理

m_wndFormatBar.Create(this) 告诉工具栏,命令要发送到哪个窗口。加载图像,设置栏样式和显示工具栏是很明显的。然后你计算工具栏的大小,并相应地调整静态控件的大小,并留出一些边距。

经过繁重的数值考虑后,我们将静态控件放置到位,并将工具栏放在它的旁边。m_Stc_ToolbarFrame.RepositionBars 告诉工具栏,它应该依偎到哪个窗口。然后让静态控件消失。

省略行或错误地进行计算将导致奇怪的光学结果和应用程序的奇怪行为。检查一下。

虽然命令路由非常简单,但这些命令的视觉更新有点棘手。

第三步

UpdateCommandUI 处理程序添加到你的对话框,并像在每个 Frame/View 应用程序中一样编辑这些方法。不要关心它们何时似乎不起作用。实际上,它们不能。

第四步

添加该行

#include "afxpriv.h"

在对话框的 *cpp* 文件顶部,或将其放在 *stdafx.h* 中。在你的对话框的头文件中,将以下行

afx_msg LRESULT OnKickIdle(WPARAM, LPARAM);

放在消息映射中。最好的位置是在 //}}AFX_MSG 行和 DECLARE_MESSAGE_MAP() 行之间。如果没有行,则按回车键创建一个。在你的对话框的 *cpp* 文件中查找单词 END_MESSAGE_MAP()之前,输入 ON_MESSAGE(WM_KICKIDLE, OnKickIdle)。如果你忘记包含 *afxpriv.h*,编译器会告诉你它对 WM_KICKIDLE 一无所知。(顺便说一句,这个消息是否意味着有人在闲着踢东西?)

OnKickIdle 例程的主体添加到你的对话框类中,并在其中调用 CommandUpdateUI 处理程序。如何?看一看。

LRESULT CArbitraryToolbarDlg::OnKickIdle(WPARAM, LPARAM)
{ 
    CCmdUI cmdUI;
    cmdUI.m_nID = ID_FORMAT_BOLD; // The Command ID
    // Tell the dialog to call the UpdateCommandUI-routine
    cmdUI.DoUpdate(this, FALSE);
    cmdUI.m_nID = ID_FORMAT_DURCHSTRICH;
    cmdUI.DoUpdate(this, FALSE);
    cmdUI.m_nID = ID_FORMAT_KURSIV;
    cmdUI.DoUpdate(this, FALSE);
    cmdUI.m_nID = ID_FORMAT_UNTERSTRICH;
    cmdUI.DoUpdate(this, FALSE);
    cmdUI.m_nID = ID_EDIT_CUT;
    cmdUI.DoUpdate(this, FALSE);
    cmdUI.m_nID = ID_EDIT_COPY;
    cmdUI.DoUpdate(this, FALSE);
    cmdUI.m_nID = ID_EDIT_PASTE;
    cmdUI.DoUpdate(this, FALSE);
    return TRUE;
}

第五步...

添加命令处理程序并进行测试。喝一杯咖啡。

在此整个过程中,你应该将你的源代码与我的进行比较。什么可以适应你的需求,什么不能更改,我说不清。这只能通过经验来教导,你的经验。

提供的示例只有前七个按钮在工作。这是设计好的!毕竟,这是一个示例,而不是一个成熟的应用程序。

压缩 RichEditCtrl 的例程将很快推出,并带有自己的类。敬请关注。

读了这么久,我可以请你帮个忙吗?我的小弟弟现在被派往中东的战争中,请你为他祈祷,让他能平安归来吗?谢谢你。

© . All rights reserved.