大家一定都用过Oicq,是不是觉得里面的拉帘按钮很炫,就是当我们点击好友,陌生人或黑名单时所需的内容就会自动出现在主窗口中,其中按钮有一种被拉起或拉下的感觉。现在我就叫大家作这种特效。
第一:创建
启动Visual C++ =〉New Project => MFC AppWizard(exe) 假定AppName为Oicq
在Step 1中选SDI,在Step 4中不选tool bar,status bar,printing选项,因为用不着。其余各步均按默认选项,创建了一个标准的SDI模板。
第二:设计初始大小和窗口风格
在CMainFrame::PreCreateWindow(CREATESTRUCT& cs)函数中加如下语句
cs.style=WS_OVERLAPPEDWINDOW;//标准窗口类型
cs.lpszName=_T("QQ"); //标题
cs.hMenu=NULL; //取消菜单
cs.cx=100; //初始宽100pixels
cs.cy=700; //初始长700pixels
真么样,有点样子了吧,这只是刚开始,好戏还在后头,慢慢来。
第三:添加按钮
在COicqView中加入三个Button变量
CButton myButton1;
CButton myButton2;
CButton myButton3;
在COicqView中添加消息函数OnCreate(LPCREATESTRUCT lpCreateStruct),添加方法不在详述,利用ClassWizard。以后的消息函数均由ClassWizard添加。在OnCreate中加入下列语句
myButton1.Create(_T("好友"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
CRect(0,0,100,20),this,IDC_BUTTON_GOODFRIEND);
//创建好友按钮
myButton2.Create(_T("陌生人"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
CRect(0,20,100,40),this,IDC_BUTTON_STRANGER);
//创建陌生人按钮
myButton3.Create(_T("黑名单"), WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
CRect(0,40,100,60),this,IDC_BUTTON_BLACKLIST);
//创建黑名单按钮
记住在Resource.h中定义
#define IDC_BUTTON_GOODFRIEND 150
#define IDC_BUTTON_STRANGER 151
#define IDC_BUTTON_BLACKLIST 152
下面加入按钮消息映射,在COicqView中加入三个函数GoodFriend(),Stranger(),BlackList(),分别处理单击三个按钮的消息。
afx_msg void GoodFriend();
afx_msg void BlackList();
afx_msg void Stranger();
在OicqView.cpp中加映射
ON_BN_CLICKED(IDC_BUTTON_GOODFRIEND, GoodFriend)
ON_BN_CLICKED(IDC_BUTTON_STRANGER, Stranger)
ON_BN_CLICKED(IDC_BUTTON_BLACKLIST, BlackList)
注意添加位置,在BEGIN_MESSAGE_MAP(COicqView, CView)和END_MESSAGE_MAP()之间。
第四:准备移动
这一步是关键的一步,它为以后的工作打好基础,在我看来这是非常重要的,要想清楚以后的需要。
1.添加相关宏定义到OicqView.h
#define UP 1 //定义按钮状态
#define DOWN 2
2.添加状态变量
int GoodFriendState;
int BlackListState;
int StrangerState;
3.添加三个CRect变量来表示三个按钮的位置
CRect Button1_Rect;
CRect Button2_Rect;
CRect Button3_Rect;
4.添加一个CSize的变量来表示客户区大小
SIZE OldClientSize;
5.初始化各变量在OnCreate函数中
OldClientSize.cx=100;
OldClientSize.cy=669;
GoodFriendState=UP;
StrangerState=UP;
BlackListState=UP;
6.在COicqView中添加函数GetPosition()来获得各个按钮的当前位置
void COicqView::GetPosition()
{
this->myButton1.GetWindowRect(&Button1_Rect);//获得窗口坐标
ScreenToClient(&Button1_Rect); //转化Client坐标
this->myButton2.GetWindowRect(&Button2_Rect);
ScreenToClient(&Button2_Rect);
this->myButton3.GetWindowRect(&Button3_Rect);
ScreenToClient(&Button3_Rect);
}
7.在OnCreate()中添加GetPosition()
第五:移动
这里只介绍GoodFriend函数的算法,Stranger函数和BlackList函数类似,详见代码下载。
void COicqView::GoodFriend() |
两个关键函数
BOOL MoveWindow( int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE );
BOOL ValidateRect( LPCRECT lpRect );
只要在准备移动部分都看懂了,这是一段不难懂的代码。关键是在MoveWindow后,要用ValidateRect使移动后的空白区域变为有效区。
第六:OnSize函数
运行后不难发现当改变窗口大小时按钮却大小不变,解决方法,添加OnSize消息函数用ClassWizard,在OnSize中加如下代码即时更新按钮大小。
void COicqView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); if(cx!=OldClientSize.cx) { myButton1.MoveWindow(Button1_Rect.left,Button1_Rect.top,cx,Button1_Rect.Height()); myButton2.MoveWindow(Button2_Rect.left,Button2_Rect.top,cx,Button2_Rect.Height()); myButton3.MoveWindow(Button3_Rect.left,Button3_Rect.top,cx,Button3_Rect.Height()); } this->GetPosition(); if(cy!=OldClientSize.cy) { if(DOWN==BlackListState) { myButton3.MoveWindow(Button3_Rect.left,cy-Button3_Rect.Height(),Button3_Rect.Width(),Button3_Rect.Height()); } if(DOWN==StrangerState) { myButton2.MoveWindow(Button2_Rect.left,cy-Button3_Rect.Height()- Button2_Rect.Height(),Button2_Rect.Width(),Button2_Rect.Height()); } } OldClientSize.cx=cx; OldClientSize.cy=cy; this->GetPosition(); } |