当前位置:文档之家› MFC的工具条和状态栏类

MFC的工具条和状态栏类

MFC的工具条和状态栏类
MFC的工具条和状态栏类

MFC的工具条和状态栏类

MFC使用CToolBarCtrl、CStatusBarCtrl和CToolTipCtrl窗口类分别对工具条、状态栏、Tooltip 控制窗口进行了封装。

但是,直接使用这些类还不是很方便。MFC提供了CToolBar、CStatusBar来处理状态栏和工具条,CToolBar、CStatusBar功能更强大,灵活。这两个类都派生于CControlBar。

在MFC下,建议这些控制条子窗口ID介于AFX_IDW_TOOLBARFIRST(0xE800)和AFX_IDW_CONTROLBAR_LAST(0Xe8FF)之间。这256个ID中,前32个又有其特殊性,用于MFC的打印预览中。

CControlBar派生于CWnd类,是控制条窗口类的基类,它派生出CToolBar、CStatusBar、CDockBar、CDialogBar、COleResizeBar类。CControlBar实现了以下功能:

●和父窗口(边框窗口)的顶部或者底部或者其他边对齐。

●可以包含子条目,这些条目或者是基于HWND的子窗口,或者是基于非HWND的条目。负责分配条目数组。

●支持CBRS_TOP(缺省,控制条放在顶部),CBRS_BOTTOM(放在底部),CBRS_NOALIGN(父窗口大小变化时不重新放置控制条)等几种控制风格。

●支持派生类的实现。几个派生类有一定的共性,或者其中两个有一定的共性,这样CControlBar实现的函数一部分只适用于某个派生类,一部分适用于两个或者多个派生类,还有一部分适用于所有的派生类。所谓适用,这里指派生类直接继承了CControlBar的实现,或者覆盖了其实现但是建立在扩展其实现的基础上。类似地,CControlBar的成员变量也不是为所有派生类所共同适用的。

CStatusBar和CControlBar一方面建立在CControlBar的基础之上,另一方面以Windows的通用控制状态栏和工具条为基础。它们继承了CControlBar类的特性,但是所封装的窗口句柄是相应的Windows控制窗口的句柄,如同CFormView继承了CSrcollView的视类特性,但是其窗口句柄是无模式对话框窗口句柄一样。

典型地,如果在使用AppWizard生成应用程序时,指定了要求工具条和状态栏的支持,则在主边框窗口的OnCreate函数中包含一段如下的代码,用来创建工具条、状态栏和设置一些特性。

//创建工具栏

if (!m_wndToolBar.Create(this) ||!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))

{

TRACE0("Failed to create toolbar\n");

return -1; // fail to create

}

//创建状态栏

if (!m_wndStatusBar.Create(this) ||

!m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)))

{

TRACE0("Failed to create status bar\n");

return -1; // fail to create

}

// TODO: Remove this if you don't want tool tips or a resizeable toolbar

//对工具栏设置Tooltip特征

m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() |

CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC);

//使得工具栏可以泊位在边框窗口

// TODO: Delete these three lines if you don't want the toolbar to

// be dockable

m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);

EnableDocking(CBRS_ALIGN_ANY);

DockControlBar(&m_wndToolBar);

工具条除了Tooltip,Resizeable,Dockable特性外,还可以是Floatable。应用程序可以使用CFrameWnd::SaveBarState保存边框窗口的控制条的有关信息到INI文件或者Windows Register库,使用LoadBarSate从INI文件或者Register库中读取有关信息并恢复各个控制条的设置。

下文,将讨论工具条等的创建、销毁,从中分析CControlBar和派生类的关系,讨论CControlBar如何实现共性,如何支持派生类的特定要求,派生类又如何实现自己的特定需求等。

13.2.1 控制窗口的创建

创建工具条、状态条、对话框工具栏的方法是不同的,所以必须给每个派生类CToolBar、CStatusBar、CDialogBar设计和实现自己的窗口创建函数Create。但是,它们是也是有共性的,共性由CControlBar的PreCreateWindow处理。在窗口创建之后,各个派生类都要进行的处理(共性)由CControlBar的OnCreate完成,特别的处理通过派生类的OnNcCreate完成。

13.2.1.1 PreCreateWindow

首先,讨论CControlBar 类的PreCreateWindow的实现。

BOOL CControlBar::PreCreateWindow(CREATESTRUCT& cs)

{

if (!CWnd::PreCreateWindow(cs))

return FALSE;

//修改窗口风格,强制适用clipsliblings,以防重复绘制

cs.style |= WS_CLIPSIBLINGS;

//default border style translation for Win4

//(you can turn off this translation by setting CBRS_BORDER_3D)

if (afxData.bWin4 && (m_dwStyle & CBRS_BORDER_3D) == 0)

{

DWORD dwNewStyle = 0;

switch (m_dwStyle & (CBRS_BORDER_ANY|CBRS_ALIGN_ANY))

{

case CBRS_LEFT: //控制条在边框窗口的左边显示

dwNewStyle = CBRS_BORDER_TOP|CBRS_BORDER_BOTTOM;

break;

case CBRS_TOP://控制条在边框窗口的顶部显示

dwNewStyle = CBRS_BORDER_TOP;

break;

case CBRS_RIGHT://控制条在边框窗口的右边显示

dwNewStyle = CBRS_BORDER_TOP|CBRS_BORDER_BOTTOM;

break;

case CBRS_BOTTOM://控制条在边框窗口的底部显示

dwNewStyle = CBRS_BORDER_BOTTOM;

break;

}

// set new style if it matched one of the predefined border types

if (dwNewStyle != 0)

{

m_dwStyle &= ~(CBRS_BORDER_ANY);

m_dwStyle |= (dwNewStyle | CBRS_BORDER_3D);

}

}

return TRUE;

}

其中,afxData是一个全局变量,MFC用它来记录系统信息,如版本信息等。这里afxData.bWin4表示Windows版本是否高于4.0。

CToolBar的PreCreateWindow函数修改了窗口风格,也修改状态栏、工具栏等的CBRS_风格。CBRS_风格的改变不会影响窗口风格。因为这些CBRS_风格被保存在成员变量m_dwStyle中。

除了上述在程序中用到的影响工具条、状态栏等显示位置的CBRS_风格外,还有和泊位相关的CBRS_风格,CBRS_ALIGN_LEFT、CBRS_ALIGN_RIGHT、CBRS_ALIGN_BOTTOM、CBRS_ALIGN_TOP、CBRS_ALIGN_ANY,分别表示工具条可以在停泊在边框窗口的左边、右边、底部、顶部或者所有这些位置;和漂浮相关的CBRS_风格CBRS_FLOA T_MULTI,表示多个工具条可以漂浮在一个微型边框窗口中;和Tooltips相关的CBRS_风格CBRS_TOOLTIPS和CBRS_FL YBY。

派生类如果没有特别的要求,可以不覆盖PreCreateWindow函数。CStatusBar因为有更具体和特殊的风格要求,所以它覆盖了PreCreateWindow。CStatusBar的覆盖实现调用了CControlBar的实现。

派生类也可以在覆盖实现中修改PreCreateWindow参数cs,改变窗口风格;修改m_dwStyle,改变CBRS_风格。

13.2.1.2 控制条的窗口创建

CControlBar派生类实现了自己的窗口创建函数Create,CControlBar的PreCreateWindow被派生类的Create函数直接或者间接地调用。以CToolBar为例讨论窗口创建函数和创建过程。(1)CToolBar的窗口创建函数Create

Create函数实现如下:

BOOL CToolBar::Create(CWnd* pParentWnd, DWORD dwStyle, UINT nID)

{

ASSERT_VALID(pParentWnd); // must have a parent

ASSERT (!((dwStyle & CBRS_SIZE_FIXED) &&

(dwStyle & CBRS_SIZE_DYNAMIC)));

// 保存dwStyle指定的CBRS_风格

m_dwStyle = dwStyle;

if (nID == AFX_IDW_TOOLBAR)

m_dwStyle |= CBRS_HIDE_INPLACE;

//去掉参数dwStyle包含的CBRS_风格

dwStyle &= ~CBRS_ALL;

//设置窗口风格

dwStyle |=

CCS_NOPARENTALIGN|CCS_NOMOVEY|CCS_NODIVIDER|CCS_NORESIZE;

//初始化通用控制,可以导致InitCommonControl的调用

VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));

//创建窗口,将调用PreCreateWindow,OnCreate, OnNcCreate等

CRect rect; rect.SetRectEmpty();

if (!CWnd::Create(TOOLBARCLASSNAME, NULL, dwStyle,

rect, pParentWnd, nID))

return FALSE;

// Note: Parent must resize itself for control bar to be resized

return TRUE;

}

其中:

Create函数的参数1表示工具条的父窗口。参数2指定窗口风格和CBRS_风格,缺省值为WS_CHILD | WS_VISIBLE | CBRS_TOP,其中WS_CHILD和WS_VISIBLE是窗口风格,CBRS_TOP是CBRS_风格。参数3指定工具条ID,缺省值为AFX_IDW_TOOLBAR(0X0E800或者59392)。如果还有多个工具栏要显示,在创建它们时则必须给每个工具栏指明ID。首先,Create函数把参数2(dwStyle)指定的窗口风格和CBRS_风格分离出来,窗口风格保留在dwStyle中,CBRS_风格保存到成员变量m_dwStyle中。CToolBar::PreCreateWindow 将进一步修改这些风格。

接着,Create函数调用了函数AfxDeferRegisterClass。它如果没有注册TOOLBARCLASSNAME表示的“窗口类”,就注册该类;否则,返回TRUE,表示已经注册。TOOLBARCLASSNAME表示的字符串是“ToolbarWindow32”,即“窗口类”名称。然后,调用CWnd::Create(7个参数)使用“ToolbarWindow32”“窗口类”创建工具栏。Create在创建窗口的过程中,用MFC的标准窗口过程取代原来的窗口过程,如同CFormView 和CDialog窗口创建时窗口过程被取代一样,并发送WM_CREATE和WM_NCCREATE消息。

至于添加向工具栏添加按钮,则由函数LoadToolBar完成。在分析LoadToolBar函数之前,先讨论OnCreate、OnNcCreate等函数。

(2)处理WM_CREATE消息

CControlBar提供了消息处理函数OnCreate来处理WM_CREATE消息。

int CControlBar::OnCreate(LPCREATESTRUCT lpcs)

{

//调用基类的实现

if (CWnd::OnCreate(lpcs) == -1)

return -1;

//针对工具栏,是否有Tooltip特性

if (m_dwStyle & CBRS_TOOLTIPS)

EnableToolTips();

//得到父窗口,并添加自身到其控制条列表中

CFrameWnd *pFrameWnd = (CFrameWnd*)GetParent();

if (pFrameWnd->IsFrameWnd())

{

m_pDockSite = pFrameWnd;

m_pDockSite->AddControlBar(this);

}

return 0;

}

如果需要支持Tooltips,则OnCreate调用EnableTooltips。

m_pDockSite是CControlBar的和泊位相关的成员变量,这里把它初始化为拥有工具栏的父边框窗口,该边框窗口把控制条加入其控制条列表m_listControlBars中。

在处理WM_CREATE之前,派生类先处理消息WM_NCCREAE。例如,CToolBar覆盖了OnNcCreate函数。

(3)处理WM_NCCREATE消息

CToolBar对WM_NCCREATE消息的处理如下:

BOOL CToolBar::OnNcCreate(LPCREATESTRUCT lpCreateStruct)

{

if (!CControlBar::OnNcCreate(lpCreateStruct))

return FALSE;

// if the owner was set before the toolbar was created, set it now

if (m_hWndOwner != NULL)

DefWindowProc(TB_SETPARENT, (WPARAM)m_hWndOwner, 0);

DefWindowProc(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);

return TRUE;

}

CToolBar覆盖CcontrolBar的该函数用来设置工具条的所属窗口和描述工具条按钮结构的大小,这两个动作都是通过给工具条窗口发送消息来实现的。因为这些消息被送给控制窗口类的窗口过程(Windows提供的)来处理,所以直接调用DefWindowProc,省却了消息发送的过程。

在控制窗口创建之后,对于工具条来说,下一步就是向工具栏添加按钮。

(4)向工具栏添加按钮

通过函数LoadToolBar完成向工具栏添加按钮的任务,其实现如下:

BOOL CToolBar::LoadToolBar(LPCTSTR lpszResourceName)

{

ASSERT_VALID(this);

ASSERT(lpszResourceName != NULL);

//查找并确认按钮位图、字符串等资源的位置

HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_TOOLBAR);

HRSRC hRsrc = ::FindResource(hInst, lpszResourceName, RT_TOOLBAR);

if (hRsrc == NULL)

return FALSE;

//锁定资源

HGLOBAL hGlobal = LoadResource(hInst, hRsrc);

if (hGlobal == NULL)

return FALSE;

CToolBarData* pData = (CToolBarData*)LockResource(hGlobal);

if (pData == NULL)

return FALSE;

ASSERT(pData->wVersion == 1);

//复制与各个位图对应的命令ID到数组pItem

UINT* pItems = new UINT[pData->wItemCount];

for (int i = 0; i < pData->wItemCount; i++)

pItems[i] = pData->items()[i];

//添加按钮到工具栏,指定各个按钮对应的ID

BOOL bResult = SetButtons(pItems, pData->wItemCount);

delete[] pItems;

//设置按钮的位图

if (bResult)

{

// set new sizes of the buttons

CSize sizeImage(pData->wWidth, pData->wHeight);

CSize sizeButton(pData->wWidth + 7, pData->wHeight + 7);

SetSizes(sizeButton, sizeImage);

// load bitmap now that sizes are known by the toolbar control

bResult = LoadBitmap(lpszResourceName);

}

UnlockResource(hGlobal);

FreeResource(hGlobal);

return bResult;

}

LoadToolBar函数的参数指定了资源。ToolBar资源的类型是RT_TOOLBAR,ToolBar位图资源的类型是RT_BITMAP。

在RT_TOOLBAR类型的资源读入内存之后,可以用CToolBarData结构描述。一个这样的结构包括了ToolBar资源的如下信息:

工具条位图的版本,宽度,高度,个数,各个位图对应的命令ID。

然后,LoadToolBar把这些命令ID被复制到数组pItem中;根据位图宽度、高度形成按钮尺寸sizeButton和位图尺寸sizeImage。

接着,调用SetBottons添加按钮到工具栏,把各个按钮和命令ID对应起来;调用SetSizes 设置按钮和位图的尺寸大小;调用LoadBitmap添加或者取代工具条的位图列表。这些动作都是调用工具栏“窗口类”的窗口过程完成的。例如,SetButtons的实现:

BOOL CToolBar::SetButtons(const UINT* lpIDArray, int nIDCount)

{

ASSERT_VALID(this);

ASSERT(nIDCount >= 1); // must be at least one of them

ASSERT(lpIDArray == NULL ||

AfxIsValidAddress(lpIDArray, sizeof(UINT) * nIDCount, FALSE));

//首先,删除工具条中现有的按钮

int nCount = (int)DefWindowProc(TB_BUTTONCOUNT, 0, 0);

while (nCount--)

VERIFY(DefWindowProc(TB_DELETEBUTTON, 0, 0));

if (lpIDArray != NULL)//命令ID数组非空

{

//添加新按钮

TBBUTTON button; memset(&button, 0, sizeof(TBBUTTON));

int iImage = 0;

for (int i = 0; i < nIDCount; i++)

{

button.fsState = TBSTATE_ENABLED;

if ((button.idCommand = *lpIDArray++) == 0)

{

//按钮之间分隔

button.fsStyle = TBSTYLE_SEP;

//按钮之间隔8个像素

button.iBitmap = 8;

}

else

{

//有位图和命令ID的按钮

button.fsStyle = TBSTYLE_BUTTON;

button.iBitmap = iImage++;//设置位图索引

}

//添加按钮

if (!DefWindowProc(TB_ADDBUTTONS, 1, (LPARAM)&button))

return FALSE;

}

}

else//命令ID数组空,添加空按钮

{

TBBUTTON button; memset(&button, 0, sizeof(TBBUTTON));

button.fsState = TBSTATE_ENABLED;

for (int i = 0; i < nIDCount; i++)

{

ASSERT(button.fsStyle == TBSTYLE_BUTTON);

if (!DefWindowProc(TB_ADDBUTTONS, 1, (LPARAM)&button))

return FALSE;

}

}

//记录按钮个数到成员变量m_nCount中

m_nCount = (int)DefWindowProc(TB_BUTTONCOUNT, 0, 0);

//稍后放置按钮

m_bDelayedButtonLayout = TRUE;

return TRUE;

}

函数的参数1是一个数组,数组的各个元素就是命令ID;参数2是按钮的个数。首先,SetButtons删除工具条原来的按钮;然后,添加新的按钮,若命令ID数组非空,则把每一个按钮和命令ID对应并分配位图索引,否则设置空按钮并返回FALSE;最后,记录按钮个数。

从SetButtons的实现可以看出,对工具条的所有操作都是通过工具条“窗口类”的窗口过程完成的,SetSizes、LoadBitmap也是如此,这里不作讨论。

(5)状态栏和对话框工具栏的创建

至此,分析了MFC创建工具条窗口的过程。对于状态栏和对话框工具栏有类似的步骤,但也有不同之处。

CStatusBar的Create使用“msctls_statusbar32”“窗口类”创建状态栏,窗口ID为AFX_IDW_STATUS_BAR(0XE801),然后通过成员函数SetIndictors给状态栏分格,类似于给工具条添加按钮的过程,它实际上是通过状态栏“窗口类”的窗口过程完成的。CDialogBar的Create使用CreateDlg创建对话框工具栏,类似于CFormView的过程。在工具栏窗口创建之后,要添加到父窗口的工具栏列表中,这通过CControlBar::OnCreate完成。这样创建的结果导致窗口过程使用MFC的统一的窗口过程,相应“窗口类”的窗口过程也将在缺省处理中被调用,这一点如同CFormView和CDialog中所描述的。在初始化对话框的时候完成了各个控制按钮的添加。

CStatusBar和CdialogBar都没有处理消息WM_NCCREATE。

关于CStautsBar和CDialogBar创建过程的具体实现,这里不作详细讨论了。

13.2.2 控制条的销毁

描述了控制条的创建,顺便考察其销毁的设计。

工具条、状态栏等这些控制窗口都要使用DestroyWindow来销毁,所有有关操作集中由CControlBar处理。CControlBar覆盖了虚拟函数DestroyWindow、PostNcDestroy和消息处理函数OnDestroy。

当然,各个派生类的虚拟析构函数被实现。如果成员变量m_bAutoDelete为TRUE,则动态创建的MFC窗口将自动销毁。

13.2.3 处理控制条的位置

13.2.3.1 计算控制条位置的过程和算法

工具条等控制条是作为一个子窗口在父边框窗口内显示的。为了处理控制条的布置(Layout),首先需要计算出控制条的尺寸大小,这个工作被委派给工具条等控制窗口自己来完成。为此,CControlBar提供了两个函数来达到这个目的:CalcFixLayout,CalcDynamicLayout。这两个函数都是虚拟函数。各个派生类都覆盖了这两个或者其中一个函数,用来计算自身的尺寸大小。这些计算比较琐碎,在此不作详细讨论。其次,在父窗口位置或者大小变化时,控制条的大小和位置要作相应的调整。

下面,描述MFC确定或者更新工具条、状态栏等位置的步骤:

(1)边框窗口在必要的时候调用虚拟函数RecalcLayout来重新放置它的控制条和客户窗口,例如在创建窗口时、响应消息WM_SIZE时(见5.3.3.5节)边框窗口的初始化)。

(2)CFrameWnd::RecalcLayout调用CWnd的成员函数RepositionBars完成控制条窗口的重新放置。

(3)CWnd::RepositionBars作如下的处理:

RepositionBars首先给各个控制子窗口发送(Send)MFC内部使用的消息WM_SIZEPARENT,把窗口客户区矩形指针传递给它们,给它们一个机会来确认自己的尺寸。

然后,各个控制子窗口用OnSizeParent响应WM_SIZEPARENT消息;ControlBar实现了消息处理函数OnSizeParent,它调用CalcDynamicLayout等函数确定本窗口的大小,并从客户区矩形中减去自己的尺寸。

在所有的控制子窗口处理了OnSizeParent消息之后,RepositonBars利用返回的信息调用函数CalcWindowRect计算客户区窗口(MDI客户窗口、View等)的大小。

最后,调用::EndDeferWindowPos或者::SetWindowPos放置所有的窗口(控制子窗口和客户窗口)。

在窗口被放置的时候,发送消息WM_WINDOWPOSCHANGING和WM_WINDOWPOSCHANGED。MFC的实现中,控制窗口响应了前一个消息,消息处理函数是OnWindowPosChanging。CControlBar、CToolBar和CStatusBar等实现了消息处理函数OnWindowPosChanging。

上述处理过程所涉及的这些函数中,RecalcLayout是CFrameWnd定义的虚拟函数;RepostionBars是CWnd的成员函数;CalcaWindowRect是CWnd的虚拟函数;OnSizeParent 是CControlBar定义的消息处理函数;OnWindowPosChanging是CToolbar、CStatusBar、CDockBar等CControlBar派生类定义的消息处理函数。

下面,对其中两个函数RecalcLayout和RepositionBars作一些分析。

13.2.3.2 CFrameWnd的虚拟函数RecalcLayout

RecalcLayout的实现如下:

void CFrameWnd::RecalcLayout(BOOL bNotify)

{

//RecalcLayout是否正在被调用

if (m_bInRecalcLayout)

return;

m_bInRecalcLayout = TRUE;

// clear idle flags for recalc layout if called elsewhere

if (m_nIdleFlags & idleNotify)

bNotify = TRUE;

m_nIdleFlags &= ~(idleLayout|idleNotify);

//与OLE相关的处理

#ifndef _AFX_NO_OLE_SUPPORT

// call the layout hook -- OLE support uses this hook

if (bNotify && m_pNotifyHook != NULL)

m_pNotifyHook->OnRecalcLayout();

#endif

//是否包含浮动(floating)控制条的边框窗口(CMiniFrameWnd类)

if (GetStyle() & FWS_SNAPTOBARS)

{

//计算控制条和边框窗口的位置、尺寸并设置它们的位置

CRect rect(0, 0, 32767, 32767);

RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposQuery,

&rect, &rect, FALSE);

RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST, reposExtra,

&m_rectBorder, &rect, TRUE);

CalcWindowRect(&rect);

SetWindowPos(NULL, 0, 0, rect.Width(), rect.Height(),

SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOZORDER);

}

else

//是普通边框窗口,则设置其所有子窗口的位置、尺寸

RepositionBars(0, 0xffff, AFX_IDW_PANE_FIRST,

reposExtra, &m_rectBorder);

//本函数处理完毕

m_bInRecalcLayout = FALSE;

}

该函数主要的目的是调用RepositionBars函数,它分两种情况来调用RepositionBars函数。一种情况是当前边框窗口为浮动控制条的包容窗口(微型边框窗口)时;另一种情况是当前边框窗口为普通边框窗口时。

13.2.3.3 CWnd的成员函数RepositionBars

RepositionBars的实现如下:

void CWnd::RepositionBars(UINT nIDFirst, UINT nIDLast, UINT nIDLeftOver,

UINT nFlags, LPRECT lpRectParam, LPCRECT lpRectClient, BOOL bStretch) {

ASSERT(nFlags == 0 || nFlags == reposQuery || nFlags == reposExtra);

AFX_SIZEPARENTPARAMS layout;

HWND hWndLeftOver = NULL;

layout.bStretch = bStretch;

layout.sizeTotal.cx = layout.sizeTotal.cy = 0;

if (lpRectClient != NULL)

layout.rect = *lpRectClient; //从参数6得到客户区

else

//参数lpRectClient空,得到客户区域

GetClientRect(&layout.rect);

if (nFlags != reposQuery)

//准备放置各个子窗口(layout)

layout.hDWP = ::BeginDeferWindowPos(8); // reasonable guess

else

layout.hDWP = NULL; // not actually doing layout

//按一定顺序给各个控制条发送父窗口resize的消息;

//各个控制条窗口收到消息后,从客户区中扣除自己使用的区域;

//并且必要的话每个控制窗口调用::DeferWindowPos

//剩下的区域留给nIDLeftOver子窗口

for (HWND hWndChild = ::GetTopWindow(m_hWnd); hWndChild != NULL;

hWndChild = ::GetNextWindow(hWndChild, GW_HWNDNEXT))

{

UINT nIDC = _AfxGetDlgCtrlID(hWndChild);

CWnd* pWnd = CWnd::FromHandlePermanent(hWndChild);

//如果是指定的nIDLeftOver子窗口,则保存其窗口句柄;

//否则,是控制条窗口,给它们发送WM_SIZEPARENT消息

if (nIDC == nIDLeftOver)

hWndLeftOver = hWndChild;

else if (nIDC >= nIDFirst && nIDC <= nIDLast && pWnd != NULL)

//如果layout->hDWP非空,OnSizeParent则将执行窗口布置的操作

::SendMessage(hWndChild, WM_SIZEPARENT, 0, (LPARAM)&layout);

}

//如果是reposQuery,则得到客户区矩形,返回

if (nFlags == reposQuery)

{

ASSERT(lpRectParam != NULL);

if (bStretch)

::CopyRect(lpRectParam, &layout.rect);

else

{

lpRectParam->left = lpRectParam->top = 0;

lpRectParam->right = layout.sizeTotal.cx;

lpRectParam->bottom = layout.sizeTotal.cy;

}

return;

}

//其他情况下(reposDefault、reposExtra),则需要执行Layout操作

//处理hWndLeftOver(nIDLeftOver子窗口)

if (nIDLeftOver != 0 && hWndLeftOver != NULL)

{

CWnd* pLeftOver = CWnd::FromHandle(hWndLeftOver);

// allow extra space as specified by lpRectBorder

if (nFlags == reposExtra)

{

ASSERT(lpRectParam != NULL);

layout.rect.left += lpRectParam->left;

layout.rect.top += lpRectParam->top;

layout.rect.right -= lpRectParam->right;

layout.rect.bottom -= lpRectParam->bottom;

}

//基于layout.rect表示的客户尺寸计算出窗口尺寸

pLeftOver->CalcWindowRect(&layout.rect);

//导致函数::DeferWindowPos的调用

AfxRepositionWindow(&layout, hWndLeftOver, &layout.rect);

}

//给所有的窗口设置尺寸、位置(size and layout)

if (layout.hDWP == NULL || !::EndDeferWindowPos(layout.hDWP))

TRACE0("Warning: DeferWindowPos failed - low system resources.\n");

}

RepositionBars用来改变客户窗口中控制条的尺寸大小或者位置,其中:

参数1和参数2定义了需要重新放置的子窗口ID的范围,一般是0到0xFFFF。

参数3指定了一个子窗口ID,它拥有客户窗口剩下的空间,一般是AFX_IDW_PANE_FIRST,表示视的窗口ID。

参数4指定了操作类型,缺省是CWnd::ReposDefault,表示执行窗口放置操作,参数5不会用到;若取值CWnd::ReposQuery,则表示尝试进行窗口放置(Layout),但最后不执行这个操作,只是把参数5初始化成客户区的尺寸大小;若取值CWnd::ReposExtra,则把参数5的值加到参数2表示的子窗口的客户区域,并执行窗口放置操作。

参数6表示传递给函数的可用窗口客户区的尺寸,如果空则使用窗口客户区尺寸。

如果执行layout操作的话,该函数的核心处理就是:

首先,调用::BeginDeferWindowPos初始化一个Windows内部的多窗口位置结构(Multiple-window - position structure)hDWP;

然后,让各个子窗口逐个调用::DeferWindowPos,更新hDWP。在调用::DeferWindowPos之前,要作一个确定子窗口大小的工作。这些工作通过给各个控制子窗口发送消息WM_SIZEPARENT来完成。

控制子窗口通过函数OnSizeParent响应WM_SIZEPARENT消息,先确定自己的尺寸,然后,如果需要进行窗口布置(WM_SIZEPARENT消息参数lParam包含了一个非空的HDWP结构(lpLayout->hDWP)),则OnSizeParent将调用AfxRepositionWindow函数计算本控制窗口

的位置,结果保存到hDWP中。

在所有的控制窗口尺寸确定之后,剩下的留给窗口hWndLeftOver(如果存在的话)。确定了hWndLeftOver的大小之后,调用AfxRepositionWindow函数计算其位置,结果保存到hDWP 中。

上面提到的函数AfxRepositionWindow间接调用了::DeferWindowPos。

最后,::EndDeferWindowPos,使用hDWP安排所有子窗口的位置和大小。

至于其他函数,如OnSizeparent、OnWindowPosChanging、CalcWindowRect,这里不作进一步的分析。

13.2.4 工具条、状态栏和边框窗口的接口

13.2.4.1 应用程序在状态栏中显示信息

MFC内部通过给边框窗口发送消息WM_SETMESSAGESTRING、WM_POPMESSAGESTRING的方式在状态栏中显示信息。这两个消息在afxpriv.h里头定义。WM_SETMESSAGESTRING消息表示在状态栏中显示和某个ID对应的字符串信息或者指定的字符串信息,消息参数wParam指定了字符串资源ID,消息参数lParam指定了字符串指针,两个消息参数只有一个有用。一般,一个命令ID对应了一个字符串ID,对应的字符串是命令ID的说明。

消息WM_POPMESSAGESTRING用来重新设置状态栏。

这两个消息对应的消息处理函数分别是OnSetMessageString和OnPopMessageString,OnSetMessageString和OnPopMessageString分别实现如下:

(1)OnSetMessageString

LRESULT CFrameWnd::OnSetMessageString(WPARAM wParam, LPARAM lParam)

{

//最近一次被显示的消息字符串IDS(一个消息对应的字符串)

UINT nIDLast = m_nIDLastMessage;

m_nFlags &= ~WF_NOPOPMSG;

//得到状态栏

CWnd* pMessageBar = GetMessageBar();

if (pMessageBar != NULL)

{

LPCTSTR lpsz = NULL;

CString strMessage;

//设置状态栏文本

if (lParam != 0) //指向一个字符串

{

ASSERT(wParam == 0); // can't have both an ID and a string

lpsz = (LPCTSTR)lParam; // set an explicit string

}

else if (wParam != 0)//一个字符串资源IDS

{

//打印预览时映射SC_CLOSE成AFX_IDS_PREVIEW_CLOSE;

if (wParam == AFX_IDS_SCCLOSE && m_lpfnCloseProc != NULL)

wParam = AFX_IDS_PREVIEW_CLOSE;

//得到资源ID所标识的字符串

GetMessageString(wParam, strMessage);

lpsz = strMessage;

}

//在状态栏中显示文本

pMessageBar->SetWindowText(lpsz);

// 根据最近一次选择的消息更新状态条所属窗口的有关记录

CFrameWnd* pFrameWnd = pMessageBar->GetParentFrame();

if (pFrameWnd != NULL)

{

//记录最近一次显示的消息字符串

pFrameWnd->m_nIDLastMessage = (UINT)wParam;

//记录最近一次Tracking的命令ID和字符串IDS

pFrameWnd->m_nIDTracking = (UINT)wParam;

}

}

m_nIDLastMessage = (UINT)wParam; // new ID (or 0)

m_nIDTracking = (UINT)wParam; // so F1 on toolbar buttons work

return nIDLast;

}

OnSetMessageString函数直接或者从ID从字符串资源中得到字符串指针。如果是从ID得到字符串指针,则函数GetMessageString被调用。

和命令ID对应的字符串由两部分组成,前一部分用于在状态栏显示,后一部分用于Tooltip 显示,分隔符号是“\n”。例如,字符串ID_APP_EXIT(对应“退出”菜单、按钮)是“Exit Application\nExit”,当鼠标落在“退出”按钮上时,状态栏显示“Exit Application”,Tooltip 显示“Exit”。根据这种格式,GetMessageString分离出第一部分的文本信息。至于第二部分的用途将在讨论Tooltip的章节将用到。

得到了字符串之后,OnSetMessageString调用状态栏的SetWindowText函数。SetWindowText 导致消息WM_SETTEXT消息发送给状态栏,状态栏的消息处理函数OnSetText被调用,实际上等于调用了SetPaneText(0, lpsz),即在状态栏的第0格中显示字符串lpsz的信息。对于工具栏来说,SetWindowText可以认为是SetPaneText(0, lpsz)的简化版本。

顺便指出,pMessageBar->GetParentFrame()返回主边框窗口,即使pMessageBar指向漂浮的工具条。关于泊位和漂浮,见后面13.2.5节的描述。

关于OnSetText,其实现如下:

LRESULT CStatusBar::OnSetText(WPARAM, LPARAM lParam)

{

ASSERT_VALID(this);

ASSERT(::IsWindow(m_hWnd));

int nIndex = CommandToIndex(0); //返回0

if (nIndex < 0)

return -1;

return SetPaneText(nIndex, (LPCTSTR)lParam) ? 0 : -1;

}

(2)OnPopMessageString

LRESULT CFrameWnd::OnPopMessageString(WPARAM wParam,

LPARAM lParam)

{

//WF_NOPOPMSG表示边框窗口不处理WM_POPMESSAGESTRING

if (m_nFlags & WF_NOPOPMSG)

return 0;

//调用OnSetMessageString

return SendMessage(WM_SETMESSAGESTRING, wParam, lParam);

}

一般,在清除状态栏消息时,发送WM_POPMESSAGESTRING,通过消息参数wParam指定一个字符串资源,其ID 为AFX_IDS_IDLEMESSAGE,对应的字符串是“Ready”。

13.2.4.2 状态栏显示菜单项的提示信息

状态栏的一个重要作用是显示菜单命令或者工具条按钮的提示信息。本节讨论如何显示菜单命令的提示信息,关于工具条按钮在这方面的讨论见后面13.2.4.4章节。

显示菜单命令的提示信息,就是每当一个菜单项被选中之后,在状态栏显示该菜单的功能、用法等信息。这些信息以字符串资源的形式保存,字符串ID对应于菜单项的命令ID。

所以,必须处理菜单选择消息WM_MENUSELECT。CFrameWnd实现了消息处理函数OnMenuSelect,其实现如下:

void CFrameWnd::OnMenuSelect(UINT nItemID,

UINT nFlags, HMENU /*hSysMenu*/)

{

CFrameWnd* pFrameWnd = GetTopLevelFrame();

ASSERT_VALID(pFrameWnd);

//跟踪被选中的菜单项

if (nFlags == 0xFFFF)

{

//取消菜单操作

m_nFlags &= ~WF_NOPOPMSG;

if (!pFrameWnd->m_bHelpMode)

m_nIDTracking = AFX_IDS_IDLEMESSAGE;

else

m_nIDTracking = AFX_IDS_HELPMODEMESSAGE;

//在状态栏显示

SendMessage(WM_SETMESSAGESTRING, (WPARAM)m_nIDTracking);

ASSERT(m_nIDTracking == m_nIDLastMessage);

// update right away

CWnd* pWnd = GetMessageBar();

if (pWnd != NULL)

pWnd->UpdateWindow();

}

else

{

//选中分隔栏、Popup子菜单或者没有选中一个菜单项

if (nItemID == 0 || nFlags & (MF_SEPARATOR|MF_POPUP))

{

// nothing should be displayed

m_nIDTracking = 0;

}

else if (nItemID >= 0xF000 && nItemID < 0xF1F0) // max of 31 SC_s

{

//系统菜单的菜单项被选中

m_nIDTracking = ID_COMMAND_FROM_SC(nItemID);

ASSERT(m_nIDTracking >= AFX_IDS_SCFIRST &&

m_nIDTracking < AFX_IDS_SCFIRST + 31);

}

else if (nItemID >= AFX_IDM_FIRST_MDICHILD)

{

//如果选中的菜单项表示一个MDI子窗口

m_nIDTracking = AFX_IDS_MDICHILD;

}

else

{

//选中了一个菜单项

m_nIDTracking = nItemID;

}

pFrameWnd->m_nFlags |= WF_NOPOPMSG;

}

// when running in-place, it is necessary to cause a message to

// be pumped through the queue.

if (m_nIDTracking != m_nIDLastMessage && GetParent() != NULL)

PostMessage(WM_KICKIDLE);

}

OnMenuSelect的作用在于跟踪当前选中的菜单项,把菜单项对应的ID保存在CFrameWnd 的成员变量m_nIDTracking中。

如果菜单项没有选中,或者选中的是一个子菜单,则设置nIDTracking为0。

如果选中的是系统菜单,则把系统菜单ID转换成一个对应的命令ID;保存该值到nIDTracking中。

如果选中的菜单是MDI子窗口创建时添加的(用来表示MDI子窗口),则转换菜单ID为AFX_IDS_MDICHILD,所有对应MDI子窗口的菜单项都使用AFX_IDS_MDICHILD,保存

该值到nIDTracking中。

其他情况,就是选中菜单项的ID,把它保存到nIDTracking中。

跟踪被选择的菜单项并保存其ID在m_nIDTracking中,OnEnterIdle将用到m_nIDTracking。OnEnterIlde是消息WM_ENTERIDLE的处理函数,CFrameWnd的实现如下。

void CFrameWnd::OnEnterIdle(UINT nWhy, CWnd* pWho)

{

CWnd::OnEnterIdle(nWhy, pWho);

//若不是因为菜单选择进入该函数

//或者当前跟踪到的菜单项ID是最近一次处理的,则返回

if (nWhy != MSGF_MENU || m_nIDTracking == m_nIDLastMessage)

return;

//将发送消息WM_SETMESSAGETEXT

//在状态栏显示m_nIDTracking对应的字符串

SetMessageText(m_nIDTracking);

ASSERT(m_nIDTracking == m_nIDLastMessage);

}

当一个对话框或者菜单被显示的时候,Windows发送WM_ENTERIDLE消息。消息参数wParam取值为MSGF_DIALOGBOX或者MSGF_MENU。前者表示显示对话框时发送该消息,这时消息参数lParam表示对话框的句柄;后者表示显示菜单时发送该消息,这时消息参数lParam表示菜单的句柄。

经过消息映射,wParam的值传递给OnEnterIdle的参数nWhy,参数lParam的值传给参数who。如果参数1取值为MSGF_MENU,并且OnEnterIdle最近一次在菜单显示被调用时的菜单ID不同于这一次,则调用SetMessageText在状态栏显示对应ID命令的字符串,并且记录当前菜单ID到变量m_nIDTracking中(见消息处理函数OnSetMessageText)。

这样,在菜单选择期间,用户选择的菜单项ID被OnMenuSelect记录,在消息WM_ENTERIDLE处理时在状态栏显示ID命令的提示。

13.2.4.3 控制条的消息分发处理

工具条(包括对话框工具条)是一个子窗口,它们可以响应各种消息。如果按标准的Windows 消息和命令消息的分发途径,一些消息不能送到拥有工具条的边框窗口,因为这些消息都将被工具条(对话框工具条)处理掉。所以,CControlBar覆盖了虚拟函数PreTranslateMessage 和WindowProc以便实现特定的消息分发路径。

(1)WindowProc

CControlBar 的WindowProc实现了如下的消息分发路径:

用户对控制条的输入消息或者分发给CControlBar及其派生类处理,或者送给拥有控制条的边框窗口处理,或者送给Windows控制“窗口类”的窗口过程处理。

WindowProc的实现如下:

LRESULT CControlBar::WindowProc(UINT nMsg,

WPARAM wParam, LPARAM lParam)

{

ASSERT_VALID(this);

LRESULT lResult;

switch (nMsg)

{

//本函数处理以下消息

case WM_NOTIFY:

case WM_COMMAND:

case WM_DRAWITEM:

case WM_MEASUREITEM:

case WM_DELETEITEM:

case WM_COMPAREITEM:

case WM_VKEYTOITEM:

case WM_CHARTOITEM:

//首先,工具条处理上述消息,如果没有处理,则接着给所属边框窗口处理

if (OnWndMsg(nMsg, wParam, lParam, &lResult))

return lResult;

else

return GetOwner()->SendMessage(nMsg, wParam, lParam);

}

}

// 最后,给基类CWnd,按缺省方式处理

lResult = CWnd::WindowProc(nMsg, wParam, lParam);

return lResult;

}

从上述实现可以看出,对于case范围内的一些消息,如WM_COMMAND、WM_NOTIFY 等,控制条如果不能处理,则优先分发给其父窗口(边框窗口)处理,然后进入缺省处理,对于其他消息直接调用基类CWnd的实现(缺省处理)。基于这样的机制,可以把用户对工具条按钮或者对话框工具条内控制的操作解释成相应的命令消息,执行对应的命令处理。对于工具条,当用户选中某个按钮时(鼠标左键弹起,消息是WM_LBUTTONUP),工具条窗口接收到WM_LBUTTONUP消息,该消息不在CControlBar::WindowProc特别处理的消息范围内,于是进行缺省处理,也就是说,把该消息派发给控制条对应的Windows控制的窗口过程处理(即被MFC统一窗口过程所取代的原窗口过程),该窗口过程则把该消息转换成一条命令消息WM_COMMAND,命令ID就是选中按钮对应的ID,然后,发送该命令消息给拥有工具条的边框窗口,导致相应的命令处理函数被调用。

对于对话框工具条,当工具条的某个控制子窗口被选中之后,则产生一条命令通知消息WM_COMMAND,wParam是控制子窗口的ID。CControlBar::WindowProc处理该消息。WindowProc首先调用OnWndMsg把消息发送给对话框工具条或者对话框工具条的基类处理,如果没有被处理的话,则OnWndMsg返回FALSE。接着,WindowPoc把命令消息传递给父窗口(边框窗口)处理。由于工具条的控制窗口的ID对应的是命令ID,所以,这条WM_COMMAND消息传递给边框窗口时,被解释成一个命令消息,相应的命令处理函数被调用。

(2)PreTranslateMessage

CControlBar覆盖PreTranslateMessage函数,主要是为了在光标落在工具条按钮上时显示FLYBY信息,并且让对话框工具条过滤Dialog消息。

BOOL CControlBar::PreTranslateMessage(MSG* pMsg)

{

ASSERT_VALID(this);

ASSERT(m_hWnd != NULL);

//过滤Tooltip消息

if (CWnd::PreTranslateMessage(pMsg))

return TRUE; //是Tooltip消息,已经被处理

UINT message = pMsg->message;

//控制条的父窗口,对工具条和对话框工具条,总是创建它的边框窗口

CWnd* pOwner = GetOwner();

//必要的话,在状态条显示工具栏按钮的提示

if (((m_dwStyle & CBRS_FLYBY) ||

message == WM_LBUTTONDOWN || message == WM_LBUTTONUP) && ((message >= WM_MOUSEFIRST && message <= WM_MOUSELAST) ||

(message >= WM_NCMOUSEFIRST &&

message <= WM_NCMOUSELAST)))

{

_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();

//确认鼠标在工具栏的哪个按钮上

CPoint point = pMsg->pt;

ScreenToClient(&point);

TOOLINFO ti; memset(&ti, 0, sizeof(TOOLINFO));

ti.cbSize = sizeof(TOOLINFO);

int nHit = OnToolHitTest(point, &ti);

if (ti.lpszText != LPSTR_TEXTCALLBACK)

free(ti.lpszText);

BOOL bNotButton =

message == WM_LBUTTONDOWN && (ti.uFlags & TTF_NOTBUTTON);

if (message != WM_LBUTTONDOWN && GetKeyState(VK_LBUTTON) < 0) nHit = pThreadState->m_nLastStatus;

//更新状态栏的提示信息

if (nHit < 0 || bNotButton)

{

if (GetKeyState(VK_LBUTTON) >= 0 || bNotButton)

{

SetStatusText(-1);

KillTimer(ID_TIMER_CHECK);

}

}

else

{

if (message == WM_LBUTTONUP)

{

SetStatusText(-1);

ResetTimer(ID_TIMER_CHECK, 200);

}

else

{

if ((m_nStateFlags & statusSet) || GetKeyState(VK_LBUTTON) < 0)

SetStatusText(nHit);

else if (nHit != pThreadState->m_nLastStatus)

ResetTimer(ID_TIMER_WAIT, 300);

}

}

pThreadState->m_nLastStatus = nHit;

}

// don't translate dialog messages when in Shift+F1 help mode

CFrameWnd* pFrameWnd = GetTopLevelFrame();

if (pFrameWnd != NULL && pFrameWnd->m_bHelpMode)

return FALSE;

//在IsDialogMessage之前调用边框窗口的PreTranslateMessage,

//给边框窗口一个处理快捷键的机会

while (pOwner != NULL)

{

// allow owner & frames to translate before IsDialogMessage does

if (pOwner->PreTranslateMessage(pMsg))

return TRUE;

// try parent frames until there are no parent frames

pOwner = pOwner->GetParentFrame();

}

//过滤给对话框的消息和来自子窗口的消息

return PreTranslateInput(pMsg);

}

函数PreTranslateMessage主要是针对工具栏的,用来处理工具栏的CBRS_FLYBY特征。对于对话框工具栏,也可以有CBRS_FL YBY特征。但在这种情况下,还需要把一些用户键盘输入解释成对话框消息。为了防止快捷键被解释成对话框消息,在调用函数PreTranslateInput之前,必须调用所有父边框窗口的PreTranslateMessage,给父边框窗口一个机会处理用户的输入消息,判断快捷键是否被按下。

关于Tooltip和本PreTranslateMessage函数处理Tooltip的详细解释见下一节的讨论。13.2.4.4 Tooltip

工具条(或对话框工具条)如果指定了CBRS_TOOLTIPS风格(创建时指定或者创建后用SetBarStyle设置),则当鼠标落在某个按钮上(或者对话框的子控制窗口)时,在鼠标附近弹出一个文本框──Tooltip提示窗口。

C#菜单栏、工具栏、状态栏

1鄢涛2011/5/18《.NET Windows programming 》 yantao@https://www.doczj.com/doc/8918508752.html, Visual studio 2010 yantao@https://www.doczj.com/doc/8918508752.html, 鄢涛2011/5/18《.NET Windows programming 》 yantao@https://www.doczj.com/doc/8918508752.html, Visual studio 20102 Tower 2011/5/https://www.doczj.com/doc/8918508752.html, Windows programming yantao@https://www.doczj.com/doc/8918508752.html, 概述 状态栏(StatusStrip)

3鄢涛2011/5/18 《.NET Windows programming 》 yantao@https://www.doczj.com/doc/8918508752.html, Visual studio 2010 ! 概述

鄢涛2011/5/18《.NET Windows programming 》 yantao@https://www.doczj.com/doc/8918508752.html, Visual studio 20105Tower 2011/5/https://www.doczj.com/doc/8918508752.html, Windows programming yantao@https://www.doczj.com/doc/8918508752.html, ü概述 MenuStrip 工具栏(ToolStrip) MDI 窗体和MenuStrip 合并 6 鄢涛2011/5/18《.NET Windows programming 》 yantao@https://www.doczj.com/doc/8918508752.html, Visual studio 2010

7鄢涛2011/5/18《.NET Windows programming 》 yantao@https://www.doczj.com/doc/8918508752.html, Visual studio 2010

9 鄢涛2011/5/18《.NET Windows programming 》 yantao@https://www.doczj.com/doc/8918508752.html, Visual studio 2010: ToolStripMenuItem 菜单项该类是一个ToolStripDropDownItem ,与ToolStripDropDownMenu 和ContextMenuStrip 一起工作,以便为菜单处理特殊的突出显示、布局和列排列方式。ToolStripMenuItem 类提供使您得以配置菜单项的外观和功能的属性。 10 鄢涛2011/5/18《.NET Windows programming 》 yantao@https://www.doczj.com/doc/8918508752.html, Visual studio 2010 : ToolStripMenuItem 菜单项

实验三,菜单,工具栏与状态栏应用

实验三、菜单、工具栏与状态栏应用 一、实验内容 设计一个应用程序,使用菜单实现运行界面大小的改变、透明度和背景颜色的改变;并使用工具按钮实现响应界面大小、颜色改变,使用上下文菜单实现界面大小的改变;使用状态栏实现界面大小的改变、透明度和背景颜色的改变的三种信息。 二、实验步骤 1、设计程序界面 新建一个C#.NET项目,向窗体中添加一个主菜单控件,并依次添加子菜单项,如图3-1所示;添加一个上下文菜单,实现调整窗体大小的功能,菜单项如图3-2所示;添加工具栏控件及按钮,状态栏及状态面板,以及用于图标显示的imageList1控件(图片由用户自己准备;.NET2005 版中不需要imageList1控件,直接在工具栏控件ToolStrip的Items属性集的Image属性中设置)。适当调整各控件的大小及位置。程序界面设计如图3-3所示(特别说明:以下所有图示是在2003版下完成的) 注意:不同C# 版本中的控件名及属性名、事件均有差别,详见下表: 图3-1 主菜单设计

图3-2 上下文菜单设计 图3-3 程序界面设计 2、设置对象属性 为了在工具按钮上显示图标,设置imageList1的Images图标,并设置工具栏toolBar1的ImageList 属性值为imageList1,为工具按钮“红色”、“绿色”、“兰色”、“黄色”、“紫色”分别设置ImageIndex 属性为0、1、2、3、4,以便显示图标。为状态栏设置3个状态面板,分别用于显示窗体大小、背景颜色以及透明度。其他控件的属性设置见图3-1、图3-2、图3-3。 3、编写事件代码 菜单“窗体”中子菜单项“大”有3种情况。实现窗体运行中显示为设计时窗体3倍的代码如下: private void menuItem15_Click(object sender, System.EventArgs e) { this.Size=new Size(900,600); menuItem15.Checked=true; // 设置选中状态为真 menuItem16.Checked=false; menuItem17.Checked=false; menuItem3.Checked=false; menuItem4.Checked=false; statusBarPanel1.Text="3倍大小"; // 在状态栏中显示窗体的大小} 实现窗体运行中显示为设计时窗体2倍的代码如下: private void menuItem16_Click(object sender, System.EventArgs e) { this.Size=new Size(600,400); menuItem15.Checked=false; menuItem16.Checked=true; menuItem17.Checked=false; menuItem3.Checked=false; menuItem4.Checked=false; statusBarPanel1.Text="2倍大小"; } 实现窗体运行中显示为设计时窗体1.5倍的代码如下: private void menuItem17_Click(object sender, System.EventArgs e) {

【26-编辑菜单栏】什么是菜单栏和工具栏

【26-编辑菜单栏】什么是菜单栏和工具栏 编辑菜单栏“编辑”菜单“编辑”菜单中的一些命令主要是对文件进行编辑的,比如复制、粘贴、填充、描边等。“编辑”菜单是photoshop软件操作中最为常用的菜单之一。 1.“还原”命令这个命令用来将操作进行还原,它的快捷键是CTRL+Z,当时它只能还原一次,如果想要尽可能多地还原操作步骤,那么可以按CTRL+ALT+Z键。 2.“剪切”命令当画面中存在选框的时候,这个命令能将画面中选框中的部分进行裁切,下面我们通过一个练习来讲解。 一:打开这一张图片,然后用选区工具(M)选出一个选区。 二:选择编辑>剪切(CTRL+X),这样选框中的部分就被剪切掉了,如下图。 再选择编辑>粘贴(CTRL+V)就可以把剪切的部分粘贴到画面中。 3.“拷贝”和“粘贴”命令这两个命令基本上是组合来使用的,在画面中制作选框后,选择编辑>拷贝(CTRL+C)命令将其复制然后再选择编辑>粘贴(CTRL+V)将复制的部分粘贴到画面中。与前面的”剪切”命令不同的是,剪切后的图片在选框中的部分就没有了,

当时使用“拷贝”和“粘贴”命令后,原图片是完整的。所以大家要注意这两个的区别。 4.“填充”命令“填充”命令的功能与工具箱中的“油漆桶”工具基本相同,只不过它将一些主要的命令和选项集中在一起。如图:在下拉列表中可以选择很多选项,我们可以选择这些相应的选项来得到不同的效果,不过最为常用的就是前两个选项。其他的大家自己尝试吧。。。。 在“模式”下拉列表中我们可以选择填充的模式,这与前面讲过的混合模式是相同的。如“不透明度”用于改变填充颜色的透明程度。 5.“描边”命令描边命令用于对选框或者对象进行描边,下面通过一个实例来讲解下一:新建文件,然后使用矩形选框工具(M)在画面中做出选框。 二:选择编辑>描边命令,按照下图设置。 三:完成后得到如下效果。 6“自由变换”命令“自由变换”命令是我非常喜欢的一个命令,它灵活多变,用户可以完全地自行控制,做出任何变形。 自由变换:编辑——自由变换(快捷键:Ctrl+T)辅助功能键:Ctrl、Shift、Alt。 其中,Ctrl键控制自由变化;Shift控制方向、角度和等比例放大缩小;Alt键控制中心对称。

Excel 2007 与 Excel 2003 菜单工具栏比较

一.Excel 2007 与Excel 2003 菜单工具栏比较 相信很多人在刚接触到Excel 2007时,都有种无从下手的感觉,特别是原先在Excel 2003或以前的版本中熟悉的菜单和工具栏不见了,好多命令都不知道“隐藏”到哪儿去了。下面,我们对Excel 2003和Excel 2007进行比较,看看Excel2003中的菜单和工具栏在Excel2007中是如何组合的。 Excel 2003的基本界面 图1.1:Excel2003界面 如上图1.1所示,为大家很熟悉的Excel2003及以前版本的界面。 Excel 2007的界面 图1.2:Excel2007界面

Excel2007操作将功能进行逻辑分类,分别放在相应的“带形功能区”中,共分9类,即开始、插入、页面布局、公式、数据、审阅、视图、开发工具、加载项。每个功能区中又分成几块小的区域,分别集中相应的功能命令按钮。同时,一些命令按钮旁有下拉箭头,含有相关的功能选项。在区域的右下角,有扩展箭头可显示该区域功能的对话框。 下面将详细地进行比较 (1)Office按钮 这两项调到了07版的 【页面布局】 相当于03版的 [工具]->[选项] Office 07版Office按钮Office 03版文件选项 单击Office按钮,则显示与文件操作相关的命令,相当于以前版本中的“文件”菜单中的大多数内容,但变化还是比较大的,在新版本中移除了“页面设置”和“打印区域”,增加了“Excel选项”。 如果对方的版本过低又没安装补丁的话是开不打新版的文件的,我们可以在“另存为”里选择“Excel 97-2003工作簿”另存一个副本给他。 打印预览,在“打印里”,我们最好将“打印预览”和“快速打印”添加到快速访问工具栏里,这样方便我们工作。 设置访问密码有两个方法:1.在“准备”里的“加密文件”可以设置,但只可以设置访问密码,不能设置修改密码。 2. 在“另存为”界面“保存”旁边有一个“工具”按钮,点击“工具”按钮右边的小三角,在弹出菜单中选择“常规选 项”。这时我们就可以在“常规选项”中设置密码了。设置“打开权限密码”后,他人可以用这个密码阅读这个Excel文件。设置“修改权限密码”后,他人可以用这个密码打开和修改这个Excel文件。 一般我们发布的知通都以PDF文件格式发布,这时我们可以点击“发送”再选择“PDF电子邮件附件”。

工具,菜单,及工具栏

工具,菜单,及工具栏 Ps丶杰丨Forever Photo shop 工具箱中包含了用于创建和编辑图像、图稿、页面元素的工具和按钮。单击工具箱顶部的双箭头切换为单排和双排。 移动工具箱 默认的情况下,工具箱停放在窗口左侧。将光标放在工具箱顶部双箭头

右侧,可以将工具箱从停放中拖出,放在窗口的任意位置。 程序栏:可以调整photo shop窗口大小,将窗口最大化、最小化或关闭。还可以切换工作区,显示参考线,网络等。 菜单栏:菜单中可以执行各种命令。单击菜单名称即可打开相应的菜单。 标题栏:显示了文档名称、文件格式、窗口缩放比例和颜色模式等等。如果包含多个图层,则标题栏中还会显示当前工作的图层的名称。 图中的文档名称为鱼老大,格式为psd,缩放比例为33.3%,颜色模式为RGB。括号里面则为:我选择的图层。

工具箱:包含用于各种操作的工具,如创建选区,移动图像,绘画,绘图等 工具选项栏:用来设置工具的各种选项,它会随着所选工具的不同而变换内容。 魔棒工具选项栏 渐变工具选项栏 面板:可以帮助我们编辑图像。有的用来设置编辑内容,有的用来设置颜色属性。 状态栏:可以显示文档大小,文档尺寸,当前工具和窗口缩放比较等信息。 图中缩放比例为33.33%,文档尺寸为146.05毫米* 216.03毫米 文档窗口:是显示和编辑图像的区域。 选项卡:打开多个图像时,它们会最小化到选项卡中,单击各个文件的名称即到相应的文件。 在photo shop中打开一个图像时,便会创建一个文档窗口。如果打开了多个图像,则各个文档窗口会以选项卡的形式显示。 按下Ctrl+ Tab键,即可照前后顺序窗口切换。按下Ctrl+ Shift+ Tab键,可按照相反的顺序切换窗口。 单击一个标题栏将其从选项卡中拖出,它便成为可任意移动位置的浮动窗口。

WIN7中任务栏,菜单栏和工具栏的基本设置

WIN7中任务栏,菜单栏和工具栏的基本设置 WIN7的任务栏和XP的任务栏相比有很大的区别,下面我们就来看看WIN7中的变化。 WIN7的任务栏中没有了快速启动栏,这是因为WIN7中增加了一项新的功能,可以将桌面快捷方式附到任务栏,其方法很简单,只要将你想要附到任务栏的桌面快捷方式托到任务栏即可,如果要将其从任务栏移除则只要在选中后“右键”则会显示“解除任务栏锁定”,单击即可。 有些时候我们会发现有些朋友的电脑的任务栏显示在电脑的右面或者上面,也有一些同学的电脑的任务栏就没有,这是怎么设置的呢?在任务栏空白处右键,会看到下图

我们只要将“锁定任务栏”前的勾去掉,那么我们就可以将任务栏托动到电脑的上下左右了,如果要隐藏任务栏则将下面的“自动隐藏任务栏”前的勾给勾上就可,要显示任务栏时只要我们将鼠标移动到最下方就会再次显示。“屏幕上的任务栏位置”也可以设置任务栏的位置,在此就不多说了。

“在任务栏按钮”我们可以作一些设置,具体操作很简单,在此就省略了。 WIN7中新增了AERO PEEK预览功能,有些时候我们会发现我们在任务栏里面的“使用AERO PEEK功能”前面的勾我们也勾上了,可就是没法使用预览功能,这很可能是我们还有一个地方忘了设置。具体方法是“计算机——属性——高级系统设置——高级——性能——设置——视觉效果”

将启用AERO PEEK前的勾给勾上就可以了。 有些时候我们会发现我们电脑里面的开始菜单里面的一些程序或项目不见了(如有些电脑里的开始菜单没有运行项),这时候我们就要到“开始菜单”项里设置了,在开始菜单里我们单击“自定义”会看到下图

VC对话框程序添加目录菜单、工具条和状态栏

一、引言 对于不需要文档/视图结构支持的程序一般都采用对话框做为程序的基础框架。虽然在对话框程序上可以通过修改其属性来添加系统菜单,但对比SDI和MDI程序的工具条和状态栏未免使界面显得简单、单调。虽然在V isual Basic 中提供有独立的工具条和状态栏标准控件可以直接在对话框上使用,但V isual C++ 6.0所提供的26种基本Windows标准控件却没有将它们包含其中。因此要在对话框程序中实现工具条和状态栏只能通过编程来动态实现。 二、工具条的实现过程 MFC对于工具条和状态栏分别提供了CToolBar和CStatusBar两个基本类库,但由于在实现时MFC 对其做了过多的封装,以至无法了解内部的一些核心技术。因此本文在实现过程中放弃了相对比较方便的CToolBar和CStatusBar类的使用,而是通过SDK(Software Developers Kit,软件开发工具箱)式的WinAPI 应用程序接口来实现的。在API函数中经常需要用到对话框的窗口句柄和当前的实例句柄,在SDK程序设计中以上两个句柄可以直接从入口函数WinMain()中引出,而在MFC下也对其做了封装,不能直接获取。但MFC也为其留有接口:CWnd窗口类提供的GetSafeHwnd()可以返回对话框的窗口句柄;函数AfxGetInstanceHandle()则可以获取当前应用程序的实例句柄。由于对话框和状态栏属于程序界面的一部分,需要程序启动时就显示出来,因此获取句柄的代码和后面创建显示工具条、状态栏的全部代码都应当放在对话框初始化消息WM_INITDIALOG的响应函数OnInitDialog()中进行: HWND hDlg=GetSafeHwnd(); HINSTANCE hInstance=AfxGetInstanceHandle(); 对于待添加的工具条按钮可以根据情况细分为两种: 一种是Windows标准的一些工具条按钮比如打开文件、打印预览、在线帮助等等,这类工具条按钮可以直接使用预定义好的按钮图标的ID号,在VC自带的CommCtrl.h头文件中有详细定义; 另一种就是用户自己添加的工具栏按钮,只能由用户在资源视图中为其指定相应的图标。不论是那种工具条按钮的创建都是通过对TBBUTTON结构的设置来决定每一个工具条按钮的状态,对于第一个填充好的工具条按钮可以用CreateToolbarEx()来直接将其加入到工具条上,并返回指向工具条的窗口句柄,而对于以后工具条按钮的添加则只能通过向工具条发送TB_ADDBUTTONS消息来实现: …… //填充工具条按钮结构: TBBUTTON ptoolbar[30]={{STD_HELP, //指定Windows的标准帮助图标 MU_ONE, //工具条按钮的ID TBSTA TE_ENABLED, //可用状态 TBSTYLE_BUTTON, //指定创建一个可以下按的按钮 0, //保留,由应用程序定义该参数意义 0}, //按钮字串索引 //创建一个分割按钮用的竖线 {0,0,TBSTA TE_ENABLED,TBSTYLE_SEP,0,0}};

什么是菜单、栏工具栏、标题栏

什么是工具栏,什么是菜单栏、什么是标题栏? 回答1、 菜单栏就是窗口最上方,标题栏下方的那部分,通常有“文件,编辑,查看,工具,帮助”等选项。 工具栏一般在菜单栏下方,通常有“前进,后退”等按钮。 回答2、 最上面的是标题栏,下面就是菜单栏,再下面就是工具栏 回答3、 菜单栏就是标题栏下面的一栏,有文件,编辑,查看,工具,帮助等等, 工具栏就菜单栏下面的所有栏目的统称.像前进,后退,主页.刷新等 标题栏就是整个窗口最上面的一栏,上面的标题说明当前窗口是什么位置 菜单栏和工具栏是什么区别 (菜单栏是应用程序里所有功能的集大成,非常丰富。可是要使用菜单栏里的功能,您通常得点好多下鼠标。为了方便用户,就把最常用的功能放在工具栏里。工具栏里通常都是图形按钮,图形按钮使用起来很方便,点一下鼠标就可以了。

小结: 在功能上,工具栏其实是菜单栏的子集、包含菜单栏里最常用的功能;在使用方式上,工具栏比菜单栏方便,点一下鼠标就行

仅供个人用于学习、研究;不得用于商业用途。 For personal use only in study and research; not for commercial use. Nur für den pers?nlichen für Studien, Forschung, zu kommerziellen Zwecken verwendet werden. Pour l 'étude et la recherche uniquement à des fins personnelles; pas à des fins commerciales. толькодля людей, которые используются для обучения, исследований и не должны использоваться в коммерческих целях. 以下无正文

实验12 菜单、工具栏和状态栏

实验内容 创建一个单文档应用程序Ex_SDI,开始运行时主框架窗口的大小为屏幕的1/4大小,并移动到屏幕的右上角。当单击工具栏上的圆圈按钮,该按钮呈按下状态,此时在窗口的客户区的光标为一个圆圈,双击鼠标,则状态栏上显示“你在(x,y)处双击鼠标”(x,y为鼠标在客户区的位置)。若再单击工具栏上的圆圈按钮,该按钮呈正常状态,光标变成原来的箭形,双击鼠标,状态栏上不再显示任何文本。如图T12.1所示是单击圆圈按钮时的程序界面。 实验准备和说明 (1)在教程第5章全部讲授后进行本次实验。 (2)构思本次上机所需要的程序。 实验步骤 1.创建工作文件夹 打开计算机,在“D:\Visual C++程序、LiMing”文件夹中创建一个新子文件夹“实验12” 2.改变运行时窗口的大小和位置 改变运行时窗口的大小和位置设置步骤如下。 (1)启动Visual C++6.0。 (2)用 MFC AppWizard 创建一个默认的单文档应用程序Ex_SDI。在“新建”对话框中将项目文件夹定位到“D:\Visual C++程序\ LiMing\实验12”。 (3)将项目工作去窗口切换到Class View 页面,打开并定位到 CEx_SDIApp::InitInstance 函数处。 (4)在CEx_SDIApp::InitInstance 函数的最后添加下列代码: BOOL CEx_SDIApp::InitInstance() { … m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); CRect rcDesktop; ::GetWindowRect(GetDesktopWindow(),rcDesktop); // 获取屏幕大小 m_pMainWnd->MoveWindow(rcDesktop.Width()/2.0, rcDesktop.Width()/2, rcDesktop.Height()/2); return TRUE; }

实验5 菜单、工具栏和状态栏

实验 实验目的和内容 (1)创建一个单文档应用程序Ex_SDI。在“查看”菜单下添加一个子菜单“鼠标位置”,ID为ID_VIEW_MOUSE,当选择该菜单命令后,鼠标当前的位置显示到状态栏上, 同时该菜单项呈选中状态。再次选择该菜单命令,状态栏不再显示当前鼠标位置, 同时该菜单项的选中状态被去除。 (2)在工具栏上添加并设计一个工具按钮图标,使该按钮和ID_VIEW_MOUSE菜单命令联动,并添加一个快捷键Ctrl+M和该菜单命令联动。 (3)在窗口客户区中右击鼠标,弹出快捷菜单,显示主菜单“查看”中的菜单命令。结果如图5.1所示。 图5.1 Ex_SDI运行结果 实验准备和说明 (1)具备知识:菜单、工具条和状态栏。 (2)创建本次实验工作文件夹“…\Visual C++程序\实验\实验5”。 实验内容和步骤 1.启动Visual C++ 6.0 打开计算机,启动Visual C++ 6.0系统。 2.用MFC AppWizard(exe)创建一个默认的单文档应用程序Ex_SDI ①选择“文件”→“新建”菜单,在弹出的“新建”对话框中选择“工程”标签,在应用程序项目类型列表框中选择MFC AppWizard(exe)的项目类型,将工程文件夹定位到“…\Visual C++程序\实验\实验5”,并在工程框中输入项目名Ex_SDI。 ②单击“确定”按钮,从出现的对话框中,选择单个文档(Single Document,SDI)应用程序类型。 ③保留其他的默认选项,单击“完成”按钮出现一个对话框,显示出用户在步骤中作出的选择,单击“确定”按钮,系统开始创建。

3.添加菜单 ① 在项目工作区窗口中选择ResourceView 页面,双击资源Menu 项中的IDR_ MAINFRAME ,则菜单编辑器窗口出现在主界面的右边,相应的Ex_SDI 项目的菜单资源被显示出来。 ② 单击“查看”菜单,则在该菜单的最后一项,Visual C++为用户留出了一个空位置,用来输入新的菜单项。 ③ 在菜单的空位置上双击鼠标左键,则出现它的属性对话框,如图5.2所示,在标题框中输入“鼠标位置(&M )\tCtrl+1”,在ID 框输入该菜单项的资源标识:ID_VIEW_MOUSE ,在提示框中输入“在状态栏上显示当前鼠标位置\n 鼠标位置”,其中\n 前一部分的文本是显示在状态栏上的,后一部分是联动的工具图标按钮的提示文本。 图5.2 菜单项属性设置 4.添加并设计一个工具图标按钮 ① 在项目工作区窗口的ResourceView 页面中,双击Toolbar 中的IDR_MAINFRAME ,打开工具栏资源。 ② 单击工具栏最右端的空白按钮,在资源编辑器的 按钮设计窗口中绘制一个“箭头”,颜色为黑色,然后将 其拖动到“帮助”按钮的前面,并使该按钮的前后均有 半个空格,结果如图5.3所示。 ③ 双击刚才设计的工具按钮,在弹出的属性对话框 中将其ID 设为ID_VIEW_MOUSE 。 5.菜单命令和工具按钮的更新 ① 为CMainFrame 类添加一个BOOL 型的成员变量m_bIsMouse ,在CMainFrame 类构造函数中将m_bIsMouse 的初值设为FALSE 。 ② 用MFC ClassWizard 在CMainFrame 类中添加工具按钮ID_VIEW_MOUSE 的COMMAND 和UPDA TE_COMMAND_UI 消息映射函数,并添加下列代码: void CMainFrame::OnViewMouse() { m_bIsMouse = !m_bIsMouse; } void CMainFrame::OnUpdateViewMouse(CCmdUI * pCmdUI) { pCmdUI ->SetCheck(m_bIsMouse); } ③ 编译运行并测试。 6.设置快捷键 ① 在项目工作区窗口的ResourceView 页面中,双击Accelerator 中的IDR_ MAINFRAME ,打开快捷键资源。 图5.3 设计的工具按钮

实验5 菜单、工具栏和状态栏

实验5 菜单、工具栏和状态栏 实验目的 1、掌握菜单的实现机制和创建过程 2、掌握普通下拉菜单和上下文菜单的创建 3、掌握工具栏的创建和消息处理过程 实验内容: 本节主要掌握菜单、工具栏的使用方法,内容包括菜单的创建和使用、工具栏的创建和使用。 例1.要求创建一个应用程序,实现在客户区绘制椭圆和矩形的功能。为应用程序添加一个“图形”菜单项,该菜单项包含两个子菜单“椭圆”和“矩形”。 步骤: (1)用AppWizard创建一个基于MFC的SDI应用程序,工程名为ex61。 (2)在ResourceView页面中,双击Menu文件夹,可以看到一个ID为ID_MAINFRAME 的菜单,此菜单为应用程序的主菜单。双击ID_MAINFRAME菜单,进入菜单编辑器,在编辑框窗口中出现菜单栏。 (3)菜单项的添加:1)“图形”菜单项的添加。在ID_MAINFRAME菜单的最右端有一个空的菜单项,双击该菜单项弹出该菜单项的属性对话框,在该对话框中,选定弹出(pop-up),表示本菜单项中包含弹出子菜单,在标明(caption)编辑框中输入该菜单项的标题“图形”,使该菜单项下产生一个空的子菜单项。2)添加“椭圆”和“矩形”子菜单项。双击“图形”菜单项下的空子菜单,其属性对话框中各项为: (4)增加“椭圆”和“矩形”的消息处理……1)利用ClassWizard为ID_ELLIPSE在CEx61View类中添加消息映射,如下图。双击COMMAND弹出对话框,要求在该对话框中输入消息处理函数的名称,选择默认函数名,确定后,双击消息处理函数OnEllipse进行编辑(矩形同样进行编辑,消息处理函数为OnRectangle),代码如下:

实验四 .资源菜单、工具栏和状态栏

实验五.资源菜单、工具栏和状态栏 1.实验目的 掌握菜单资源的访问,添加和消息响应响应; 资源菜单对应加速键的添加、快捷工具栏的添加。 2.实验装置 机房 3.实验内容 1)建立win32 Application项目文件:Hello添加键盘消息处理功能,判断当前按下的键是不是A或a键,并给出相应的提示。 2)建立MFC APPwizard(.exe)项目,添加菜单资源和与菜单资源相关联的工具栏选项,设置加速键。具体步骤如下: (1)建立单文档在一级菜单中添加了“字体颜色”的菜单项,其下创建子菜单项ID_ColorRed和ID_ColorGre两个菜单项,请为其设置加速键为Ctrl+R和Ctrl+G。 并在工具栏添加其对应的快捷工具选项。 ….编辑快捷工具选项 …建立响应,双击工具图标

….添加快捷键,在资源中打开“Accelerator”的最后两栏为ID_ColorRed和ID_ColorGre两个菜单项添加加速键,并为其分别设置快捷键为Ctrl+R和Ctrl+G。 ….消息响应编辑。 3)用资源编辑器和MFC库的CMenu::TrackPopupMenu函数创建快捷菜单,即当用户按下鼠标右键时,就会相应地弹出一个浮动菜单,其中提供了几个与当前选择内容相关的选项。…因为快捷菜单是在视图区的鼠标操作,故在视图类中添加代码。 创建一个默认的单文档应用程序Ex_ContextMenu。 用MFC ClassWizard在CEx_ContextMenuView类添加WM_CONTEXTMENU消息映射,并在映 射函数中添加下列代码: void CEx_ContextMenuView::OnContextMenu(CWnd* pWnd, CPoint point) { CMainFrame* pFrame=(CMainFrame*)AfxGetApp()->m_pMainWnd;// 获得主窗口指针CMenu* pSysMenu = pFrame->GetMenu(); // 获得程序窗口菜单指针 int nCount = pSysMenu->GetMenuItemCount(); // 获得顶层菜单个数 int nSubMenuPos = -1; for (int i=0; iGetMenuString(i, str, MF_BYPOSITION); if (str.Left(4) == "文件") { nSubMenuPos = i; b reak; } } if (nSubMenuPos<0) return; // 没有找到,返回 pSysMenu->GetSubMenu( nSubMenuPos) ->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x, point.y, this); } …在Ex_ContextMenuView.cpp文件的前面添加CMainFrame类的文件包含: #include "Ex_ContextMenuView.h" #include "MainFrm.h" …运行程序 4)MFC的CStatusBar类封装了状态栏的大部分操作,包括增减窗格、在状态栏中显示 文本、改变状态栏的风格和大小等。状态栏中的窗格可以分为信息行窗格和指示器窗格两类若在状态栏中增加一个信息行窗格,则只需在indicators数组中的适当位置中增加一个ID_SEPARATOR标识即可;若在状态栏中增加一个用户指示器窗格,则在indicators数组中的适当位置增加一个在字符串表中定义过的资源ID。 将鼠标在窗口客户区的位置显示在状态栏上 (a) 创建一个默认的单文档应用程序Ex_SDIMouse。 (b) 将项目工作区切换到ClassView页面,展开CMainFrame所有项,双击构造函 数CMainFrame,在文档窗口中出现该函数的定义,在它的前面就是状态栏数组 的定义。 (c) 将状态栏indicators数组的定义改为下列代码: static UINT indicators[] = { ID_SEPARATOR,

VB 菜单、工具栏和状态栏

菜单、工具栏和状态栏 1菜单 1.1菜单编辑器 VB提供的菜单编辑器来设计实现。 菜单编辑器的启动方式: (1)选择“工具/菜单编辑器”命令。 (2)利用快捷键来调用“菜单编辑器”。 1.2创建最简菜单 在菜单的属性设置区域中有诸多的属性需要设置,其中,“标题”和“名称”属性是必须要设置的,其他的属性可以采用默认值,或者不进行设置。仅设置了“标题”和“名称”属性的菜单就是最简菜单。 注意:“标题”属性和“名称”属性必须都设置,缺一不可,否则将不被菜单编辑器接受。 1.3设置菜单的快捷键和访问键 快捷键是用于执行一个命令的功能键或者组合键,例如,为复制操作。 访问键是指用户按下键同时又按下的键。例如,用于打开“文件”菜单,这里的键即为访问键。

1.4创建级联菜单 在菜单编辑器中,以缩进量显示级联菜单的形式。在菜单编辑器的菜单列表区中由内缩进符号表明菜单项所在的层次,每4个点表示一层,最多可以有5个内缩符号,最后面的菜单项为第5层。 1.5创建复选菜单 通过复选菜单可以实现在菜单中执行或取消执行某项操作。菜单的复选标记有两个作用:一是表示打开或关闭的条件状态,选取菜单命令可以交替地添加或删除复选标记;二是指示几个模式中哪个或哪几个在起作用。 1.6 设置菜单分隔条 利用菜单分隔条可使功能相近的菜单放在一组,使子菜单看起来更加清晰、明了。1.7 设置菜单无效 有些菜单对于不同权限的操作用户的使用权限是不同的,如系统设置方面的菜单,只有系统管理员才能使用,当普通用户进入系统中时,这些菜单将被设置为无效。

实验五 菜单、工具栏、状态栏程序设计

实验五菜单、工具栏、状态栏程序设计 【实验目的】 1、掌握主菜单程序设计方法 2、学会工具栏程序设计 3、掌握快捷菜单程序设计方法 4、学会增加状态栏窗格 【实验内容】 1、建立一个单文档应用程序,添加菜单显示,其中包含“文本”和“图形”2 个菜单项,分别输出文本和图形。 参考代码: void CSDIDispView::OnText() { // TODO: Add your command handler code here CClientDC dc(this); dc.TextOut(20,20,"我已经学会了如何设计菜单程序!"); } void CSDIDispView::OnPicture() { // TODO: Add your command handler code here CClientDC dc(this); CBrush *BrushOld,BrushNew; BrushNew.CreateSolidBrush(RGB(255,0,0)); BrushOld=dc.SelectObject(&BrushNew); //选用画刷 dc.Rectangle(50,50,250,150); dc.SelectObject(BrushOld); //还原画刷 BrushNew.DeleteObject(); //释放画刷 } 2、为上述应用程序添加菜单控制功能,选中“文本”时,“图形”菜单项无效; 当选中“图形”时,“文本”菜单项无效。 参考代码: void CSDIDispView::OnText() { // TODO: Add your command handler code here CClientDC dc(this); dc.TextOut(20,20,"我已经学会了如何设计菜单程序!"); m_picture=false; } void CSDIDispView::OnPicture() {

相关主题
文本预览
相关文档 最新文档