zoukankan      html  css  js  c++  java
  • VC++中对话框界面重绘2对话框自身的重绘

    在对话框重绘设计与实现过程中,一般需要绘制的对话框区域主要有标题部分、边框部分和客户区部分。具体的区域划分如下图所示。

    既然要对多个区域进行位图显示输出,所以我们先封装一个bmp位图显示输出函数如下:

    void CCTestDlg::ShowBmp(int x,int y,int w,int h,int nID)

    {//nID 表示位图资源的ID

        CRect winRC;

        CDC* pDC=GetWindowDC();

        CDC memDC;

        memDC.CreateCompatibleDC(pDC);

        BITMAPINFO bmpInfo;

        CBitmap bmp; 

        GetWindowRect(&winRC);

        bmp.LoadBitmap(nID);

        bmp.GetObject(sizeof(BITMAPINFO),&bmpInfo);

        int nBmpCX = bmpInfo.bmiHeader.biWidth;

        int nBmpCY = bmpInfo.bmiHeader.biHeight;

        memDC.SelectObject(bmp);

        pDC->StretchBlt(x,y,w,h,

           &memDC,0,0,nBmpCX,nBmpCY,SRCCOPY);//在窗口中绘制位图

        bmp.DeleteObject();

        ReleaseDC(pDC);

    }

    (1)对各个区域进行位图输出重绘。由于标题栏以及边框主要都是非客户区域绘制,因此应该在WM_NCPAINT 消息中绘制。当然得先通过添加资源的方式将所用到的bmp位图资源导入到项目中。

    首先定义一些常量值,表示对话框各个组成区域部分。代码如下:

     

    #define LEFTTITLE 1//左标题

    #define MIDTITLE 1//中间标题

    #define RIGHTTITLE 1//右标题

    #define MINBUTTON 1//右标题

    #define MAXBUTTON 1//右标题

    #define CLOSEBUTTON 1//右标题

    #define APPICON 1 //程序icon图标

    #define LEFTBAR 1 //左边框

    #define RIGHTBAR 1 //右边边框

    #define BOTTOMBAR 1 //底边框

    在 WM_NCPAINT消息对于的 方法OnNcPaint()中调用对话框绘制方法SetFace()。该方法的功能就是绘制对话框各个区域的位图。主要代码如下:

    void CCTestDlg::SetFact()

    {

        // TODO: 在此添加控件通知处理程序代码

        int nFrameCY = GetSystemMetrics(SM_CYFIXEDFRAME);//获取对话框边框的高度

        int nFrameCX = GetSystemMetrics(SM_CXDLGFRAME);//获取对话边框的宽度

        int m_nBorderCY;

        int m_nBorderCX;

        int m_nTitleBarCY ;

        int m_nTitleBarCX;

        if(GetStyle()&WS_BORDER)//获取对话框是否有边框

        {

            m_nBorderCY = GetSystemMetrics(SM_CYBORDER) + nFrameCY;

            m_nBorderCX = GetSystemMetrics(SM_CXBORDER) +nFrameCX;

        }

        else

        {

            m_nBorderCX = nFrameCX;

            m_nBorderCY = nFrameCY;

        }

        m_nTitleBarCY = GetSystemMetrics(SM_CYCAPTION) + m_nBorderCY;//计算标题栏高度

        m_nTitleBarCX =m_nBorderCX;

        CRect winRect,factRect;

        GetWindowRect(&winRect); //获取窗口区域

        factRect.CopyRect(CRect(0,0,winRect.Width(),winRect.Height()));

        CWindowDC windowsDC(this);//获取窗口设备上下文

        //获取整个MFC窗口的高度和宽度

        int winCX = winRect.Width();

        int winCY = winRect.Height();          

        if(LEFTTITLE)

        {//绘制对话框左标题栏位图

            ShowBmp(0,0,100,m_nTitleBarCY,IDB_RIGHTTITLE);

        }      

        if(RIGHTTITLE)

        {//绘制对话框右标题栏位图

            ShowBmp(winCX-100,0,100,m_nTitleBarCY,IDB_RIGHTTITLE);

        }      

        if(MIDTITLE)

        {//绘制对话框中标题栏位图

           

            ShowBmp(100,0,winCX-200,m_nTitleBarCY,IDB_MIDTITLE);

        }  

        if(LEFTBAR)

    {//绘制对话框左边框位图                  ShowBmp(0,m_nTitleBarCY,m_nBorderCX,factRect.Height()-m_nBorderCY,IDB_LEFTBAR);

        }

        if(BOTTOMBAR)

        {//绘制对话框底边框位图     ShowBmp(m_nBorderCX,winCY-m_nBorderCX,winCX-2*m_nBorderCX,m_nBorderCX,IDB_BOTTOMBAR);

        }  

        if(RIGHTBAR)

        {//绘制对话框左边框位图    ShowBmp(winCX-m_nBorderCX,m_nTitleBarCY,m_nBorderCX,factRect.Height()-m_nBorderCY,IDB_RIGHTBAR);

        }  

        if(MINBUTTON)

        {//给对话框绘制最小化按钮

            ShowBmp(winCX-3-24-3-24-3-24,1,24,24,IDB_MINBUTTON);

        }  

        if(MAXBUTTON)

        {//给对话框绘制最大化按钮

            ShowBmp(winCX-3-24-3-24,1,24,24,IDB_MAXBUTTON);

        }  

        if(CLOSEBUTTON)

        {//给对话框绘制关闭按钮

            ShowBmp(winCX-3-24,1,24,24,IDB_CLOSEBUTTON);

        }

        ReleaseDC(&windowsDC);

        DrawTitleBarText();//输出标题栏文本

    }

    上面代码中最后的绘制对话框标题文本的方法DrawTitleBarText()的主要代码如下:

    CString strTitle ="自绘窗口标题栏和边框";

        CDC* pDC= GetWindowDC();//获取窗口设备上下文

        pDC->SetBkMode(TRANSPARENT);//设置透明的背景模式

        pDC->SetTextColor(RGB(255,255,255));//设置文本颜色

        pDC->SetTextAlign(TA_CENTER);//设置文本对齐方式

        CRect rect;

        GetClientRect(&rect);//获取窗口客户区域

        CSize szText = pDC->GetTextExtent(strTitle);//获取文本高度

        pDC->TextOut(rect.Width()/2,3,strTitle,20);//在窗口中输出文本

        ReleaseDC(pDC);//释放窗口设备上下文

    绘制后的效果图如下图所示。

    在完成对话框相应区域的位图后,并没有完成任务,还需要处理标题栏按钮的热点效果,以及按钮的单击事件。首先得处理鼠标在非客户区域移动时的事件,即WM_NCMOUSEMOVE消息,在其消息处理函数中判断当前的鼠标点是否位于标题栏的按钮区域,如果是则设置按钮的热点效果,并且记录当前的按钮状态,及鼠标点在哪个按钮上。同样的,处理对话框非客户区域的单击事件,即WM_NCLBUTTONDOWN消息,在其消息处理函数中完成单击事件操作。主要代码如下:

    void CCTestDlg::OnNcMouseMove(UINT nHitTest, CPoint point)

    {

        // TODO: 在此添加消息处理程序代码和/或调用默认值

        CRect minRC,maxRC,closeRC,winRC;

       

        GetWindowRect(&winRC);

       

        closeRC.CopyRect(CRect(winRC.Width()-27,1,winRC.Width()-27+24,1+24));  

        maxRC.CopyRect(CRect(winRC.Width()-27*2,1,winRC.Width()-27*2+24,1+24));

        minRC.CopyRect(CRect(winRC.Width()-27*3,1,winRC.Width()-27*3+24,1+24));

        point.Offset(-winRC.left,-winRC.top);//由于point为屏幕坐标,这里将其转换为窗口坐标

        if(closeRC.PtInRect(point)) //判断鼠标是否在关闭按钮区域上

        {      

            ShowBmp(winRC.Width()-3-24,1,24,24,IDB_CLOSEBUTTON2);

        }

        else if(maxRC.PtInRect(point)) //判断鼠标是否在最大化按钮区域上

        {

            ShowBmp(winRC.Width()-27*2,1,24,24,IDB_MAXBUTTON2);

        }

        else if(minRC.PtInRect(point)) //判断鼠标是否在最小化按钮区域上

        {

            ShowBmp(winRC.Width()-27*3,1,24,24,IDB_MINBUTTON2);

        }

        else//鼠标没有在标题栏的按钮区域上

        {      

            ShowBmp(winRC.Width()-3-24-54,1,24,24,IDB_MINBUTTON);

            ShowBmp(winRC.Width()-3-24-27,1,24,24,IDB_MAXBUTTON);

            ShowBmp(winRC.Width()-3-24,1,24,24,IDB_CLOSEBUTTON);

        }

    }

    添加热点效果后的效果如下图所示。

     

  • 相关阅读:
    DIV+CSS布局一行两列问题(Repeater布局)
    JavaScript为DropDownList添加新项
    Indexof的实现
    父类子类构造函数的执行顺序
    微软算法面试题(2)
    Heaven on Earth
    阿里巴巴笔试题马尔科夫(HMM)的特征
    心灵净化启示录
    职场英语:开心工作的十二条秘诀
    MySql错误代码1045的解决方案
  • 原文地址:https://www.cnblogs.com/JczmDeveloper/p/2964929.html
Copyright © 2011-2022 走看看