如何在标题栏上添加按钮
自从Windows操作系统出现以后,在应用程序中进行人机交互的思想和手段便发生了根本性的改变,计算机的界面变得友好精彩。一个程序的好坏很大程度上决定于人机交互的方便程度。当前,大多数程序的标题栏都千篇一律,如何让自己的程序与众不同是每个程序员的梦想,但改变标题栏的内容的确有相当的难度。该篇文章向你介绍如何在标题栏上添加图标按钮,而且当鼠标经过和点击该图标时,鼠标将有不同的反应。请按照下面的步骤实现。
第一步:打开VC编程环境,生成一个新的基于单文档的工程temp,所有的选项都取默认值,下面,我们就在此工程的标题栏上生成三个按钮图标。
第二步:下载资源文件,共有三个文件:CaptionButton.cpp、CaptionButton.h和Thunk.h。将这三个文件添加到工程中(添加方法不必细说了吧)。
第三步:在Mainfrm.h中定义变量CCaptionButton cbExtra;,当然要包含头文件#include "CaptionButton.h"。
第四步:为工程加载位图资源,ID号分别为IDB_BITMAP1、IDB_BITMAP2、IDB_BITMAP3、IDB_BITMAP6、IDB_BITMAP7。这些位图将显示在标题栏上,至于用什么样的位图就看你的喜好了。
第五步:在Mainfrm.cpp的OnCreate函数中添加如下的代码:
//初识化,m_hWnd是我们要处理的窗口句柄
cbExtra.Init(m_hWnd);
// // 设置标题栏上的原来的按钮(最大化、最小化和关闭)保留的数目
cbExtra.SetNumOfDefaultCaptions(3);
// 设置位图的透明颜色
COLORREF crTransparent = RGB(255,0,255);
cbExtra.SetTransparentColor(crTransparent);
// 鼠标选中一个位图后该位图的样子
cbExtra.SetSelectionBitmap((HBITMAP)LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_BITMAP7),
IMAGE_BITMAP,
0,
0,
LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR));
// 鼠标移动到一个位图后,该位图的变化
HBITMAP hMouseOverBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_BITMAP2),
IMAGE_BITMAP,
0,
0,
LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR);
// 设置位图1
HBITMAP hCaptionAMBitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_BITMAP3),
IMAGE_BITMAP,
0,
0,
LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR);
HBITMAP hCaptionAMBitmapHilite =
CCaptionButton::CombineBitmaps(hCaptionAMBitmap,
hMouseOverBitmap, crTransparent);
// 设置位图2
HBITMAP hCaption2Bitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_BITMAP6),
IMAGE_BITMAP,
0,
0,
LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR);
HBITMAP hCaption2BitmapHilite =
CCaptionButton::CombineBitmaps(hCaption2Bitmap,
hMouseOverBitmap,crTransparent);
// 设置位图三
HBITMAP hCaption3Bitmap = (HBITMAP)LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDB_BITMAP1),
IMAGE_BITMAP,
0,
0,
LR_LOADMAP3DCOLORS|LR_DEFAULTCOLOR);
HBITMAP hCaption3BitmapHilite =
CCaptionButton::CombineBitmaps(hCaption3Bitmap,
hMouseOverBitmap,crTransparent);
// 利用上面的定义创建标题栏上的位图,宝库位图的ID号,鼠标经过时的
file://变换位图,鼠标选择时的变换位图和提示文字。
cbExtra.New(1,hCaptionAMBitmapHilite,hCaptionAMBitmap,"guan");
cbExtra.New(2,hCaption2BitmapHilite,hCaption2Bitmap,"xi");
cbExtra.New(3,hCaption3BitmapHilite,hCaption3Bitmap,"ming");
第六步:现在我们可以先停下来看看我们的成果如何。编译我们的工程,运行,我们可以发现,我们的标题栏上增加了三个按钮,鼠标在上面移动或点击的时候,位图会发生变化。只是我们还没有添加在位图上点击是的处理函数,不要急,接下来我们就添加相应的处理函数。
第七步:当我们在标题栏上点击图标时,将有一个消息WM_CBLBUTTONCLICKED产生,参数WPARAM是指点击图标的ID号。
在mainfrm.h中定义消息映射函数afx_msg LRESULT Hit(WPARAM wParam, LPARAM lParam);
在mainfrm.cpp中定义函数实现:
ON_MESSAGE(WM_CBLBUTTONCLICKED, Hit)
LRESULT CMainFrame::Hit(WPARAM wParam, LPARAM lParam)
{
switch(wParam)
{// begin wParam
case 1:
AfxMessageBox("第一个CAPtion");
break;
case 2:
AfxMessageBox("第二个Caption");
break;
case 3:
AfxMessageBox("第三个Caption");
break;
}
return 1;
}
这样,当我们单击图标时将弹出不同的提示对话框,这只是一个例子,至于实现什么样的功能随你的便了。
第八步:标题栏的动态改变。在程序的执行过程中如果你要改变标题栏的样子你同样可以实现,下面分别给出如何删除一个图标和更改一个图标的样子。
void CMainFrame::OnDelete()
{
cbExtra.Delete(1);
}
void CMainFrame::OnChange()
{
cbExtra.Replace(1,
1,
hCaption4BitmapHilite,
hCaption4Bitmap,
"pNewToolTipText");
}
好了,功能实现了,还算满意吧,希望对你有用。
通过例程分析状态条用法
bull77 yesky
状态条是一个包含信息的控制条,通常用于信息和状态提示,这里信息是有关菜单命令或工具命令的提示字符串以及其它指示/帮助信息,而状态是用来指示SCROLL LOCK 和NUM LOCK等一些键的状态。状态条通常框架窗口的底部。状态条的信息行能显示有关的程序状态或鼠标指向的工具按钮或菜单项的信息。状态条既不能接受用户输入,也不产生命令信息。
实际上,从编程人员的角度出发(至少是那些使用AppWizard创建应用程序的编程人员),状态条是如此普通,它们并不像工具条那样允许用户编辑的资源。在创建程序框架时,用户只需告诉AppWizard为应用程序包含一个状态条,可以说,此时,用户的工作就完成了。但是,我们如果巧妙使用工具条,我们会发现它可以帮我们实现很多功能。
按以下做法我们实现在状态条上显示滚动字符串,鼠标的坐标,动态时钟。
第一步:
运行AppWizard生成一个工程mystatus,接受所有的默认设置,除了下面两步:在step 1中选Single Document ;step 4 中去掉Docking Bar 前的对钩,然后点击 Advanced 按钮,选择Window Styles 中的 Maximized选项。点击Finish按钮,此时我们生成了一个工程。运行我们可以发现程序默认生成的状态条,接下来我们要对这个状态条进行修改。
第二步:
在这一步我们将实现把状态条移到菜单的下边。在MainFrm.cpp中我们可以看到状态条的定义部分
if (!m_wndStatusBar.Create(this) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar ");
return -1; // fail to create
}
我们所要做的是将上面的定义改为
if(!m_wndStatusBar.Create(this, WS_CHILD|WS_VISIBLE|CBRS_TOP,AFX_IDW_STATUS_BAR) ||
!m_wndStatusBar.SetIndicators(indicators,
sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar ");
return -1; // fail to create
}
运行程序,这时我们可以发现,状态条已经移到了上边。
第三步:
在这一步,我们实现在状态条实现滚动文字。
< 1 > 在MainFrm.cpp中,我们可以发现如下的定义
static UINT indicators[] =
{
ID_SEPARATOR,
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
我们将其改为
static UINT indicators[] =
{
ID_SEPARATOR,
ID_STATUS1,
ID_STATUS2,
ID_STATUS3,
ID_INDICATOR_CAPS,
ID_INDICATOR_NUM,
ID_INDICATOR_SCRL,
};
<2>在菜单VIEW中选择Resource Symbols , 在对话框中选择NEW, 在NAME中输入ID_STATUS1,VALUE中取默认值,同样方法定义ID_STATUS2,ID_STATUS3。
<3>定义字符串资源,在ResouceView中选择String Table,在其中为ID_STATUS1定义字符串资源为"me",同样方法定义ID_STATUS2,ID_STATUS3。
<4>在MainFrm.h中定义如下变量:
public:
CString str,str1;
<5>在MainFrm.cpp中修改OnCreate函数如下:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if(!m_wndStatusBar.Create (this,WS_CHILD|WS_VISIBLE|CBRS_TOP,AFX_IDW_STATUS_BAR) || !m_wndStatusBar.SetIndicators(indicators,sizeof(indicators)/sizeof(UINT)))
{
TRACE0("Failed to create status bar ");
return -1; // fail to create
}
m_wndStatusBar.SetPaneInfo(1,ID_STATUS1,SBPS_POPOUT,320);
m_wndStatusBar.SetPaneInfo(2,ID_STATUS2,SBPS_POPOUT,100);
m_wndStatusBar.SetPaneInfo(3,ID_STATUS3,SBPS_POPOUT,100);
str1=str="你好,欢迎使用本程序,祝你合家幸福,事业有成!";
SetTimer(1,200,NULL);
SetTimer(2,10,NULL);
return 0;
}
<6>在类CmainFrame中重载函数OnTimer(),并添加如下代码:
void CMainFrame::OnTimer(UINT nIDEvent)
{
file:// TODO: Add your message handler code here and/or call default
if(nIDEvent==1){
if(str.IsEmpty()) str=str1;
str=str.Right(str.GetLength()-2);
m_wndStatusBar.SetPaneText(1,str);
}
if(nIDEvent==2){
SYSTEMTIME t;
::GetLocalTime(&t);
CString str2;
str2.Format("%d:%d:%d:%d",t.wHour,t.wMinute,t.wSecond,t.wMilliseconds);
m_wndStatusBar.SetPaneText(3,str2);
}
CFrameWnd::OnTimer(nIDEvent);
}
<7>将MainFrm.h中,定义m_wndStatusBar之前的 protected: 改为public:
<8>通过类向导在类CmystatusView中重载WM_MOUSEMOVE,并在实现函数中添加如下代码:
void CMystatusView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CString str3;
str3.Format("X:%d,Y:%d",point.x,point.y);
((CMainFrame*)AfxGetMainWnd())->m_wndStatusBar.SetPaneText(2,str3);
CView::OnMouseMove(nFlags, point);
}
好了,到这里我们所有的功能就都实现了,快编译运行一下吧!怎么样?还满意吗?