QQ登录

只需一步,快速开始

24上位机VC MFC程序实现自给窗口界面

[ 复制链接 ]
24上位机VC MFC程序实现自给窗口界面

功能展示
很多时候,我们将上位机程序功能编写强大的同时,也希望我们的程序漂亮大方,进而增加用户使用程序的乐趣。程序的美化除了直接加载第三方皮肤文件外,我们还可以通过自绘窗口来实现。我们当前例程就是一个自绘后的程序,抛砖引玉供大家学习,效果如图

24上位机VC MFC程序实现自给窗口界面

24上位机VC MFC程序实现自给窗口界面

要点提示
实现窗口的绘制相对来说比较麻烦,有多处系统处理的函数要我们自行绘制处理,其次是得准备些漂亮的位图用于程序的美化,如美化窗口边框,标题栏等等,而后利用设备上下文类CDC将这些图片绘制在窗体上就可以了。CDC提供了StretchBlt函数,用于绘制图像,其语法
BOOL StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop );
X,Y表示目标区域在上角坐标
nWidth, nHeight表示目标区域的宽度和高度
pSrcDC  表示源设备上下文指针
xSrc, ySrc表示源设备上下文的左上角坐标
nSrcWidth, nSrcHeight表示源设备上下文宽度与高度
dwRop  表示光栅效果

绘制窗口标题栏和边框时不能用GETDC函数,因为GETDC方法获得是窗口客户区域的设备上下文指针,就使用GetWindowDC方法获得窗口设备上下文指针 ;
我们当前例程在标题栏上利用位图绘制了几个按钮,当用户单击不同的按钮时,会执行相应的操作。
在绘制标题栏按钮时,要知道 标题栏按钮的显示区域,该区域会随着窗体的大小变化而不同,知道了按钮的显示区域,当用户鼠标 在标题栏上移动时,判断鼠标是否在按钮区域,如在,将按钮状态m_ButtonState设置为相应的值,然后再处理鼠标左键在非客户区按下时的消息,在消息处理函数中判断m_ButtonState值,根据不同值,执行相应的动作,这栏全实现了标题栏按钮的单击处理;

实现功能
1.新建一个对话框的应用程序
2.添加一些编辑框,文本,按钮等控件,如我们的例程一样,再添加一些位图
3.添加以下的成员变量
private:
        BOOL m_IsMax;         //是否处于最大化状态
        int  m_BorderWidth;   //边框宽度
        int  m_BorderHeight;  //边框高度
        int  m_CaptionHeight; //标题栏的高度
        CString  m_Caption;      //窗口标题
        COLORREF m_CapitonColor; //标题字体颜色
        CFont    m_CaptionFont;  //标题字体
        int m_ButtonWidth;  //按钮位图宽度
        int m_ButtonHeight; //按钮位图高度
        BOOL  m_FirstShow; //窗口首次被显示
        CRect m_OrigonRect;//原始窗口区域
        CRect m_IniRect,m_MinRect,m_MaxRect,m_CloseRect;//标题栏按钮的显示区域
        CButtonState m_ButtonState; //按钮状态
        BOOL m_IsDrawForm;//是否需要绘制窗体                        

4.添加绘制程序窗口用的自定义函数DrawForm()及DrawFormCaption()
void CGkbc8Dlg:rawForm()
{//获取窗口设备上下文
        CDC* pWindowDC = GetWindowDC();
        CBitmap LeftLine;
        BITMAPINFO bitinfo;
        
        CDC memDC;
        memDC.CreateCompatibleDC(pWindowDC);

        CRect Clientrect;
        GetClientRect(Clientrect);

        int leftwidth=0; //左标题的宽度
        int rightwidth = 0; //右标题的宽度
        int leftlinewidth = 0; //左边线宽度
        LeftLine.LoadBitmap(IDB_BITMAP3); //加载右标题
        LeftLine.GetObject(sizeof(bitinfo),&bitinfo);
        rightwidth = bitinfo.bmiHeader.biWidth;
        LeftLine.DeleteObject();

        int x,y;
        //绘制左边线
        //获取位图大小
        LeftLine.LoadBitmap(IDB_BITMAP4);
        LeftLine.GetObject(sizeof(bitinfo),&bitinfo);
        leftlinewidth = x = bitinfo.bmiHeader.biWidth;
        y = bitinfo.bmiHeader.biHeight;
        memDC.SelectObject(&LeftLine);
        pWindowDC->StretchBlt(1-m_BorderWidth,m_CaptionHeight+1,x+1,Clientrect.Height()+2*m_BorderHeight+5,&memDC,0,0,x,y,SRCCOPY);
        LeftLine.DeleteObject();

        /*****************************绘制左标题**************************************/
        LeftLine.LoadBitmap(IDB_BITMAP2);
        //获取位图大小
        LeftLine.GetObject(sizeof(bitinfo),&bitinfo);
        memDC.SelectObject(&LeftLine);
        leftwidth = x = bitinfo.bmiHeader.biWidth;
        y = bitinfo.bmiHeader.biHeight;
        pWindowDC->StretchBlt(-m_BorderWidth,0,x,m_CaptionHeight+4,&memDC,0,0,x,y,SRCCOPY);
        LeftLine.DeleteObject();
        /*****************************绘制左标题**************************************/

        /*****************************绘制中间标题**************************************/
        LeftLine.LoadBitmap(IDB_BITMAP1);
        //获取位图大小
        LeftLine.GetObject(sizeof(bitinfo),&bitinfo);
        memDC.SelectObject(&LeftLine);
        x = bitinfo.bmiHeader.biWidth;
        y = bitinfo.bmiHeader.biHeight;
        pWindowDC->StretchBlt(leftwidth-1,0,Clientrect.Width()-leftwidth-rightwidth ,m_CaptionHeight+4,&memDC,0,0,x,y,SRCCOPY);
        LeftLine.DeleteObject();
        /*****************************绘制中间标题***************************************/

        /*****************************绘制右标题**************************************/
        LeftLine.LoadBitmap(IDB_BITMAP3);
        //获取位图大小
        LeftLine.GetObject(sizeof(bitinfo),&bitinfo);
        memDC.SelectObject(&LeftLine);
        x = bitinfo.bmiHeader.biWidth;
        y = bitinfo.bmiHeader.biHeight;

        pWindowDC->StretchBlt(Clientrect.Width()-x-1,0,x+m_BorderWidth+9,m_CaptionHeight+4,&memDC,0,0,x,y,SRCCOPY);
        LeftLine.DeleteObject();
        /*****************************绘制右标题***************************************/

        /*****************************绘制右边框**************************************/
        LeftLine.LoadBitmap(IDB_BITMAP4);
        //获取位图大小
        LeftLine.GetObject(sizeof(bitinfo),&bitinfo);
        memDC.SelectObject(&LeftLine);
        x = bitinfo.bmiHeader.biWidth;
        
y = bitinfo.bmiHeader.biHeight;
        pWindowDC->StretchBlt(Clientrect.Width()+m_BorderWidth+2,m_CaptionHeight+1,x+m_BorderWidth,Clientrect.Height()+2*m_BorderHeight+5,&memDC,0,0,x,y,SRCCOPY);
        LeftLine.DeleteObject();
        /*****************************绘制右边框***************************************/

        /*****************************绘制底边框**************************************/
        LeftLine.LoadBitmap(IDB_BITMAP5);
        //获取位图大小
        LeftLine.GetObject(sizeof(bitinfo),&bitinfo);
        memDC.SelectObject(&LeftLine);
        x = bitinfo.bmiHeader.biWidth;
        y = bitinfo.bmiHeader.biHeight;
        pWindowDC->StretchBlt(leftlinewidth-m_BorderWidth,Clientrect.Height()+m_CaptionHeight+2,Clientrect.Width()+m_BorderWidth,y+2,&memDC,0,0,x,y,SRCCOPY);
        LeftLine.DeleteObject();
        /*****************************绘制底边框***************************************/

        /*****************************绘制初始化按钮**************************************/
        LeftLine.LoadBitmap(IDB_BITMAP6);
        //获取位图大小
        LeftLine.GetObject(sizeof(bitinfo),&bitinfo);
        memDC.SelectObject(&LeftLine);
        x = bitinfo.bmiHeader.biWidth;
        y = bitinfo.bmiHeader.biHeight;
        pWindowDC->StretchBlt(m_IniRect.left,m_IniRect.top,m_IniRect.right,m_IniRect.bottom,&memDC,0,0,x,y,SRCCOPY);
        LeftLine.DeleteObject();
        /*****************************绘制初始化按钮***************************************/

        /*****************************绘制最小化按钮**************************************/
        LeftLine.LoadBitmap(IDB_BITMAP6);
        //获取位图大小
        LeftLine.GetObject(sizeof(bitinfo),&bitinfo);
        memDC.SelectObject(&LeftLine);
        x = bitinfo.bmiHeader.biWidth;
        y = bitinfo.bmiHeader.biHeight;
        pWindowDC->StretchBlt(m_MinRect.left,m_MinRect.top,m_MinRect.right,m_MinRect.bottom,&memDC,0,0,x,y,SRCCOPY);
        LeftLine.DeleteObject();
        /*****************************绘制最小化按钮***************************************/

        
/*****************************绘制最大化按钮**************************************/
        LeftLine.LoadBitmap(IDB_BITMAP6);
        //获取位图大小
        LeftLine.GetObject(sizeof(bitinfo),&bitinfo);
        memDC.SelectObject(&LeftLine);
        x = bitinfo.bmiHeader.biWidth;
        y = bitinfo.bmiHeader.biHeight;
        pWindowDC->StretchBlt(m_MaxRect.left,m_MaxRect.top,m_MaxRect.right,m_MaxRect.bottom,&memDC,0,0,x,y,SRCCOPY);
        LeftLine.DeleteObject();
        /*****************************绘制最大化按钮***************************************/

        /*****************************绘制关闭按钮**************************************/
        LeftLine.LoadBitmap(IDB_BITMAP6);
        //获取位图大小
        LeftLine.GetObject(sizeof(bitinfo),&bitinfo);
        memDC.SelectObject(&LeftLine);
        x = bitinfo.bmiHeader.biWidth;
        y = bitinfo.bmiHeader.biHeight;
        pWindowDC->StretchBlt(m_CloseRect.left,m_CloseRect.top,m_CloseRect.right,m_CloseRect.bottom,&memDC,0,0,x,y,SRCCOPY);
        LeftLine.DeleteObject();
        m_IsDrawForm = TRUE;
        /*****************************绘制关闭按钮***************************************/
        ReleaseDC(&memDC);
        DrawFormCaption();

}
void CGkbc8Dlg:rawFormCaption()
{
        if (! m_Caption.IsEmpty())
        {
                CDC* pDC = GetWindowDC();
                pDC->SetBkMode(TRANSPARENT);
                pDC->SetTextColor(m_CapitonColor);
                pDC->SetTextAlign(TA_CENTER);
                CRect rect;
                GetClientRect(rect);
                pDC->SelectObject(&m_CaptionFont);
                pDC->TextOut(rect.Width()/2, m_CaptionHeight/3 ,m_Caption);        
        }
}
5.实现标题栏按钮状态的处理,我们添加OnNcMouseMove进行实现
void CGkbc8Dlg::OnNcMouseMove(UINT nHitTest, CPoint point)
{
        CDialog::OnNcMouseMove(nHitTest, point);
        CRect tempIni,tempMin,tempMax,tempClose,ClientRect;
        
        CDC* pWindowDC = GetWindowDC();
        CDC memDC;
        memDC.CreateCompatibleDC(pWindowDC);

        BITMAPINFO bInfo;
        CBitmap LeftLine;
        int x,y;

        GetWindowRect(ClientRect);
        //GetClientRect();
        tempIni.CopyRect(CRect(m_IniRect.left+ ClientRect.left,ClientRect.top+m_IniRect.top,m_IniRect.right+m_IniRect.left+ ClientRect.left,m_IniRect.bottom+m_IniRect.top+ClientRect.top));
        tempMin.CopyRect(CRect(m_MinRect.left+ ClientRect.left,ClientRect.top+m_MinRect.top,m_MinRect.right+m_MinRect.left+ ClientRect.left,m_MinRect.bottom+m_MinRect.top+ClientRect.top));
        tempMax.CopyRect(CRect(m_MaxRect.left+ ClientRect.left,ClientRect.top+m_MaxRect.top,m_MaxRect.right+m_MaxRect.left+ ClientRect.left,m_MaxRect.bottom+m_MaxRect.top+ClientRect.top));
        tempClose.CopyRect(CRect(m_CloseRect.left+ ClientRect.left,ClientRect.top+m_CloseRect.top,m_CloseRect.right+m_CloseRect.left+ ClientRect.left,m_CloseRect.bottom+m_CloseRect.top+ClientRect.top));
        
        if (tempIni.PtInRect(point)) //鼠标在初始化按钮上移动时,更改按钮显示的位图
        {

                LeftLine.LoadBitmap(IDB_BITMAP7);
                LeftLine.GetObject(sizeof(bInfo),&bInfo);
               
                x = bInfo.bmiHeader.biWidth;
                y = bInfo.bmiHeader.biHeight;
                memDC.SelectObject(&LeftLine);
                pWindowDC->StretchBlt(m_IniRect.left,m_IniRect.top,m_IniRect.right,m_IniRect.bottom,&memDC,0,0,x,y,SRCCOPY);
                m_IsDrawForm = FALSE;
                m_ButtonState = bsIni;
                LeftLine.DeleteObject();
        }
        else if(tempMin.PtInRect(point))//鼠标在最小化按钮上移动时,更改按钮显示的位图
        {
                LeftLine.LoadBitmap(IDB_BITMAP7);
                LeftLine.GetObject(sizeof(bInfo),&bInfo);        
               
                x = bInfo.bmiHeader.biWidth;
                y = bInfo.bmiHeader.biHeight;
                memDC.SelectObject(&LeftLine);
                pWindowDC->StretchBlt(m_MinRect.left,m_MinRect.top,m_MinRect.right,m_MinRect.bottom,&memDC,0,0,x,y,SRCCOPY);
                m_IsDrawForm = FALSE;
                m_ButtonState = bsMin;
                LeftLine.DeleteObject();               
        }
        else if (tempMax.PtInRect(point))
        {
                LeftLine.LoadBitmap(IDB_BITMAP7);
                LeftLine.GetObject(sizeof(bInfo),&bInfo);
                x = bInfo.bmiHeader.biWidth;
                y = bInfo.bmiHeader.biHeight;
                memDC.SelectObject(&LeftLine);
                pWindowDC->StretchBlt(m_MaxRect.left,m_MaxRect.top,m_MaxRect.right,m_MaxRect.bottom,&memDC,0,0,x,y,SRCCOPY);
                m_IsDrawForm = FALSE;
                if (m_IsMax)
                {m_ButtonState = bsMax;}
                else
                {m_ButtonState = bsRes;}
                LeftLine.DeleteObject();               
        }
        else if (tempClose.PtInRect(point))
        {
                LeftLine.LoadBitmap(IDB_BITMAP7);
                LeftLine.GetObject(sizeof(bInfo),&bInfo);
                x = bInfo.bmiHeader.biWidth;
                y = bInfo.bmiHeader.biHeight;
                memDC.SelectObject(&LeftLine);
                pWindowDC->StretchBlt(m_CloseRect.left,m_CloseRect.top,m_CloseRect.right,m_CloseRect.bottom,&memDC,0,0,x,y,SRCCOPY);
                m_IsDrawForm = FALSE;
                m_ButtonState = bsClose;
                LeftLine.DeleteObject();                        
        }
        else
        { m_ButtonState = bsNone;
                if (m_IsDrawForm==FALSE) DrawForm(); }
        ReleaseDC(&memDC);
}
6.处理窗口的WM_NCLBUTTONDOWN消息,当用户在非客户区域单击时,根据按钮的状态执行相应操作
void CGkbc8Dlg::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
        // TODO: Add your message handler code here and/or call default
        
        CDialog::OnNcLButtonDown(nHitTest, point);
        switch (m_ButtonState)
        {
        case bsClose: //关闭窗口
                {
                        DestroyWindow();
                }
                break;
        case bsIni: //还原窗口到初始大小和位置
                {
                        m_IsMax = TRUE;
                        MoveWindow(m_OrigonRect.left,m_OrigonRect.top,m_OrigonRect.Width(),m_OrigonRect.Height());
                }
                break;
        case bsMin: //
                {
                        CWnd* pDesk = GetDesktopWindow();
                        CRect rect;
                        pDesk->GetClientRect(rect);
                        SetWindowPos(0 ,(rect.Width()-m_OrigonRect.Width())/2,2,m_OrigonRect.Width(),0,SWP_SHOWWINDOW);
                }
                break;
        case bsMax:
                {
                        m_ButtonState = bsMax;
                        ShowWindow(SW_SHOWMAXIMIZED);
                        m_IsMax = FALSE;
                }
                break;
        
case bsRes:
                {                        
                        ShowWindow(SW_RESTORE);
                        m_IsMax = TRUE;
                }
                break;
        }
}

void CGkbc8Dlg::OnNcPaint()
{
        DrawForm();
        m_IsDrawForm = TRUE;
        // TODO: Add your message handler code here
        
        // Do not call CDialog::OnNcPaint() for painting messages
}
7.我们在程序初始化函数中OnInitDialog,对我们添加的变量也进行初始化
        m_BorderHeight = GetSystemMetrics(SM_CYBORDER);
        m_BorderWidth = GetSystemMetrics(SM_CXBORDER);
        m_CaptionHeight = GetSystemMetrics(SM_CYCAPTION);        

        //获取按钮位图大小
        CBitmap bitmap;
        bitmap.LoadBitmap(IDB_BITMAP6);
        BITMAPINFO bInfo;
        bitmap.GetObject(sizeof(bInfo),&bInfo);
        m_ButtonWidth = bInfo.bmiHeader.biWidth;
        m_ButtonHeight = bInfo.bmiHeader.biHeight;
        bitmap.DeleteObject();

        CRect rect;
        GetClientRect(rect);
        m_IniRect.CopyRect(CRect(8,(m_CaptionHeight+3*m_BorderHeight -m_ButtonHeight)/2,m_ButtonWidth,m_ButtonHeight));
        m_MinRect.CopyRect(CRect(rect.Width()-45,(m_CaptionHeight+2*m_BorderHeight -m_ButtonHeight)/2,m_ButtonWidth,m_ButtonHeight));
        m_MaxRect.CopyRect(CRect(rect.Width()-32,(m_CaptionHeight+2*m_BorderHeight -m_ButtonHeight)/2,m_ButtonWidth,m_ButtonHeight));
        m_CloseRect.CopyRect(CRect(rect.Width()-19,(m_CaptionHeight+2*m_BorderHeight -m_ButtonHeight)/2,m_ButtonWidth,m_ButtonHeight));
        m_CaptionFont.CreateFont(14,10,0,0,600,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FF_ROMAN,"宋体");
        m_label1.ModifyStyleEx(0,WS_EX_TRANSPARENT);
        m_IsDrawForm =FALSE;
        m_ButtonState=bsNone;
        m_FirstShow = FALSE;
        m_IsMax = TRUE;
        m_CapitonColor =RGB(0,0,255);
        m_Caption = "系统登录";

        DrawForm();
8.最后是在程序需要重绘的地方,加上我们的窗口绘制函数DrawForm();
void CGkbc8Dlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
        CDialog::OnActivate(nState, pWndOther, bMinimized);
        OnPaint() ;        
}
HBRUSH CGkbc8Dlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
        //绘制背景
        if (nCtlColor==CTLCOLOR_DLG)
        {
                CBitmap bitmap;
                bitmap.LoadBitmap(IDB_CLIENTBITMAP);

                CBrush brush(&bitmap);
                CRect rect;
                GetClientRect(rect);
                pDC->SelectObject(&brush);
                bitmap.DeleteObject();
                pDC->FillRect(rect,&brush);
                return brush;
        }
        else if (nCtlColor ==CTLCOLOR_STATIC)
        {
                pDC->SetBkMode(TRANSPARENT);
        }
        else
                return CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
        return NULL;
}
BOOL CGkbc8Dlg::OnNcActivate(BOOL bActive)
{
        OnPaint() ;
        return CDialog::OnNcActivate(bActive);
}
void CGkbc8Dlg::OnNcPaint()
{
        DrawForm();
        m_IsDrawForm = TRUE;
}
void CGkbc8Dlg::OnPaint()
{
        DrawForm();
        m_IsDrawForm = TRUE;
}
void CGkbc8Dlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
        CDialog::OnShowWindow(bShow, nStatus);
        if (m_FirstShow==FALSE)
        {
                m_FirstShow = TRUE;
                GetWindowRect(m_OrigonRect);
        }        
}
void CGkbc8Dlg::OnSize(UINT nType, int cx, int cy)
{
        CDialog::OnSize(nType, cx, cy);
        
        // TODO: Add your message handler code here
        CRect rect;
        GetClientRect(rect);

        m_IniRect.CopyRect(CRect(8,(m_CaptionHeight+3*m_BorderHeight -m_ButtonHeight)/2,m_ButtonWidth,m_ButtonHeight));
        m_MinRect.CopyRect(CRect(rect.Width()-45,(m_CaptionHeight+2*m_BorderHeight -m_ButtonHeight)/2,m_ButtonWidth,m_ButtonHeight));
        m_MaxRect.CopyRect(CRect(rect.Width()-32,(m_CaptionHeight+2*m_BorderHeight -m_ButtonHeight)/2,m_ButtonWidth,m_ButtonHeight));
        m_CloseRect.CopyRect(CRect(rect.Width()-19,(m_CaptionHeight+2*m_BorderHeight -m_ButtonHeight)/2,m_ButtonWidth,m_ButtonHeight));
        
        Invalidate();
}

下面演示下自绘功能实现的整个过程
源码及视频下载
(仅在电脑可见)
请点击此处下载

请先注册会员后在进行下载

已注册会员,请先登录后下载

文件名称:24.上位机VC MFC程序实现自给窗口界面.rar 
文件大小:210.45 KB  售价:10金币
下载权限: 不限 以上或 VIP会员   [购买捐助会员]   [充值积分]   有问题联系我

  

您的支持是我们创作的动力!  

  

您可花点闲钱积分自助任意充值

  

成为VIP会员 全站资源任意下载永久更新!




回复

使用道具 举报

点击查看
快速回复 返回列表 客服中心 搜索