Windows 界面设计:拉帘按钮设计

发表于:2007-07-01来源:作者:点击数: 标签:
大家一定都用过Oicq,是不是觉得里面的拉帘按钮很炫,就是当我们点击好友,陌生人或黑名单时所需的内容就会自动出现在主窗口中,其中按钮有一种被拉起或拉下的感觉。现在我就叫大家作这种特效。 第一:创建 启动Visual C++ =〉New Project = MFC AppWizard(e


大家一定都用过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()
{
    int i;
    switch(StrangerState)
    {
    case UP:
        switch(BlackListState)
        {       
        case UP:
            for(i=Button3_Rect.top;i<=OldClientSize.cy-Button3_Rect.Height();i++)
            {
                myButton3.MoveWindow(Button3_Rect.left,i,Button3_Rect.Width(),Button3_Rect.Height(),1);
                ValidateRect(CRect(Button3_Rect.left,i-1,Button3_Rect.right,i));
                myButton2.MoveWindow(Button2_Rect.left,i-Button2_Rect.Height(),
                    Button2_Rect.Width(),Button2_Rect.Height(),1);
                ValidateRect(CRect(Button3_Rect.left,i-Button2_Rect.Height()-1,Button3_Rect.right,i));
             }
            this->GetPosition();
            StrangerState=DOWN;
            BlackListState=DOWN;
            break;
            case DOWN:
            for(i=Button2_Rect.top;i<=Button3_Rect.top-Button2_Rect.Height();i++)
            {
                myButton2.MoveWindow(Button2_Rect.left,i,Button2_Rect.Width(),Button2_Rect.Height());
                ValidateRect(CRect(Button2_Rect.left,i-1,Button2_Rect.right,i));
            }
            this->GetPosition();
            StrangerState=DOWN;
            break;
        }
        case DOWN:
            break;
    }

}

两个关键函数
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();
}
 
现在万事OK了,不难吧!


原文转自:http://www.ltesting.net