工控编程吧
标题:
24上位机VC MFC程序实现自给窗口界面
[打印本页]
作者:
qq263946146
时间:
2015-11-14 22:03
标题:
24上位机VC MFC程序实现自给窗口界面
24上位机VC MFC程序实现自给窗口界面
功能展示
很多时候,我们将上位机程序功能编写强大的同时,也希望我们的程序漂亮大方,进而增加用户使用程序的乐趣。程序的美化除了直接加载第三方皮肤文件外,我们还可以通过自绘窗口来实现。我们当前例程就是一个自绘后的程序,抛砖引玉供大家学习,效果如图
(, 下载次数: 4)
上传
点击文件名下载附件
要点提示
实现窗口的绘制相对来说比较麻烦,有多处系统处理的函数要我们自行绘制处理,其次是得准备些漂亮的位图用于程序的美化,如美化窗口边框,标题栏等等,而后利用设备上下文类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();
}
下面演示下自绘功能实现的整个过程
[iqiyi]http://player.video.qiyi.com/4ae358240cafe433cbdab6d8c0c682e9/0/0/w_19rt8zbn15.swf-albumId=4891712309-tvId=4891712309-isPurchase=0-cnId=27[/iqiyi]
[flash=750,425]
http://v.youku.com/v_show/id_XMTM4NjEwMzk4OA==.html
[/flash]
源码及视频下载
(仅在电脑可见)
(, 下载次数: 1)
上传
点击文件名下载附件
[note]1[/note]
欢迎光临 工控编程吧 (https://www.gkbc8.com/)
Powered by Discuz! X3.4