PC Camera 开发日志(二十)------- 窗口背景贴图(图覆盖整个窗口)

 希望上一篇日志不要被骂,但是大的公司确实有能力购买皮肤库。但是小作坊就希望程序员是个千面手,什么都能搞定。

下面说的另外一种美化方法就是我们这种劳动力被压榨之下,想出来的对策。

 

现在看到非常PP的软件,除了用别人写的控件皮肤库之外,最大的特点就是形状都有。什么样的图案,风格都有。

试想一下,我们做桌面的壁纸可以有多PP就有多PP,那么也就是说如果能够把图片资源转化成为我们的界面资源,那么我们的界面想多美就多美。因为只要别人设计的图美我们的界面就一定美。

 

在VC界面美化中,摈弃WINDOW的默认窗口,基本只要其框架和消息响应机制。其他需要对话框,控件的地方,我们都采用OwnerDraw的方式来实现这写对话框、控件的重现。

 

例如:对话框的美化。我们可以在MFC资源管理器中直接拖入一个空白对话框,然后选择对应的OwnerDraw属性。在对话框的OnPaint()函数中装载你想要的背景图片,那么整个Dialog的背景就是一副图片了。网上多数这样的程序是将客户区设有背景,或者这个窗口是有背景,但是保留有标题栏的对话框,虽然整个窗口都被背景图填满,但是有时候标题栏的存在会使刷新出现问题。那么我们有时候干脆去掉Dialog的Border属性,让他只有客户区,然后我们自己定义最大、最小、关闭按钮。

 

如下图所示,我用一张背景图作为Dialog的背景,然后自己放了三个Buttons在上面,自己定义三个Buttons的响应操作。而Buttons控件也是OwnerDraw属性,这样我们才可以将图片加载到Buttons。(当然是因为我们自己封装了新的继承CButton的类实现这个功能)

 

 

需要明白的是,默认的标题栏的功能有:当鼠标点击在标题栏区域的时候,可以实现窗口的拖动。在标题栏区域点击右键可以看到系统菜单。

如果我们去掉了标题栏,为了实现Dialog的美化,那么实现窗口拖动的动作需要自己写。

一般会Override CWnd的WM_LBUTTONDOWN消息处理函数。在处理函数中,判断鼠标的位置,然后发送点击了标题栏的消息就可以了。即假装点击了标题栏。

 

  1. void CMyCamDlg::OnLButtonDown(UINT nFlags, CPoint point)
  2. {
  3.     // TODO: Add your message handler code here and/or call default
  4.     CDialog::OnLButtonDown(nFlags, point);
  5. /*-------------------Sunny--------------------*/
  6.     if(DRAGBORDER<=point.x && point.x<=m_WndWidth-DRAGBORDER && DRAGBORDER<=point.y && point.y<=m_WndHeight-DRAGBORDER)
  7.     {
  8.         // 当鼠标的坐标属于中间区域的时候,不发送拖动窗口的消息。
  9.         // 拖动窗口的效果是通过模拟发送点击Caption的消息来实现的;   WM_NCLBUTTONDOWN,HCAPTION;
  10.         return;    
  11.     }
  12.     else
  13.     {
  14.         PostMessage(WM_NCLBUTTONDOWN,   HTCAPTION,   MAKELPARAM(point.x, point.y)); 
  15.     }
  16. }

DRAGBORDER是我自己定义可拖动的边界的宽度。m_WndWidth,m_WndHeight是我获得的窗口的宽度、高度。

 

按钮的美化基本就是让按钮可以加载BITMAP图片,或者可以加载ICON图标。这样BUTTON就可以比WINDOWS的灰色按钮好看多了。

 

这两类出现比较多的控件,实现了图片化的化,其他控件也基本可以图片化。

 

有些例子,可以上国外的开源网站上学习。

CodeProject 就很好。

 

 

先说下,如何实现窗口贴上背景图。在Dialog去掉Border属性后。

 

在InitialDialog代码中写入代码,OnPaint()函数中写入代码:

 

  1. BOOL CMyCamDlg::OnInitDialog()
  2. {
  3.     CDialog::OnInitDialog();
  4.     // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
  5.     //  执行此操作
  6.     SetIcon(m_hIcon, TRUE);         // 设置大图标
  7.     SetIcon(m_hIcon, FALSE);        // 设置小图标
  8.     // TODO: 在此添加额外的初始化代码
  9. /*-------------------Sunny--------------------*/
  10.     g_Util.SelectSkin(g_Util.m_SkinsVector,_T("orange"));
  11.     // 设置窗口的大小,并初始化窗口背景位图的句柄;
  12.     Skin();
  13.     // Arrange Buttons
  14.     ArrangeButtons();
  15.     //return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
  16. }

 

可以看出来我选择了Orange皮肤,然后Skin()函数设置了窗口大小,窗口大小根据背景图片的大小来定。然后OnPaint()函数中画出这幅背景图。

 

  1. void CMyCamDlg::Skin()
  2. {
  3.     // Get CtlPanel Dialog BkImage from the CtlPanelSkin class;
  4.     CString strPath = _T("");
  5.     strPath.Format(_T("%s//%s//%s"),g_Util.m_SkinPath, g_Util.m_CurrentSkinName,g_Util.m_SkinContainer.m_CtlPanelSkin.m_BkgImgName);
  6.     // paste BkImage;
  7.     BITMAPINFO bInfo;
  8.     CBitmap tempCBMAP;
  9.     m_hBKBMAP = (HBITMAP)::LoadImage(AfxGetInstanceHandle(), strPath, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION|LR_LOADFROMFILE);
  10.     tempCBMAP.Attach(m_hBKBMAP);
  11.     tempCBMAP.GetObject(sizeof(bInfo),&bInfo);
  12.                 
  13.     m_WndWidth = bInfo.bmiHeader.biWidth;
  14.     m_WndHeight = bInfo.bmiHeader.biHeight;
  15.     MoveWindow(100,200,m_WndWidth,m_WndHeight);
  16.     tempCBMAP.Detach();
  17.     tempCBMAP.DeleteObject();
  18. }

strPath中存储了背景图片的完整路径和图片名。

  1. void CMyCamDlg::OnPaint()
  2. {
  3.     CPaintDC dc(this); // 用于绘制的设备上下文
  4.     if (IsIconic())
  5.     {
  6.         //CPaintDC dc(this); // 用于绘制的设备上下文
  7.         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
  8.         // 使图标在工作矩形中居中
  9.         int cxIcon = GetSystemMetrics(SM_CXICON);
  10.         int cyIcon = GetSystemMetrics(SM_CYICON);
  11.         CRect rect;
  12.         GetClientRect(&rect);
  13.         int x = (rect.Width() - cxIcon + 1) / 2;
  14.         int y = (rect.Height() - cyIcon + 1) / 2;
  15.         // 绘制图标
  16.         dc.DrawIcon(x, y, m_hIcon);
  17.     }
  18.     else
  19.     {
  20.         CDialog::OnPaint();
  21.     }
  22.     //Skin();
  23. /*-------------------Sunny--------------------*/
  24.     // paste BkImage;
  25.     CBitmap tempCBMAP;
  26.     ASSERT(m_hBKBMAP!=NULL);
  27.     tempCBMAP.Attach(m_hBKBMAP);
  28.                 
  29.     //在内存中创建一个位图兼容设备
  30.     //CWindowDC   dc(this); 
  31.     CDC dcMemory; 
  32.     dcMemory.CreateCompatibleDC(&dc); 
  33.     //将图片选入兼容设备 
  34.     CBitmap *pOldBmp=dcMemory.SelectObject(&tempCBMAP);
  35.     dc.BitBlt(0,0,m_WndWidth,m_WndHeight,&dcMemory,0,0,SRCCOPY);
  36.     dcMemory.SelectObject(pOldBmp); 
  37.     tempCBMAP.Detach();
  38.     // past the effect tool bar
  39.     tempCBMAP.DeleteObject();
  40.     dcMemory.DeleteDC();
  41.     ReleaseDC(&dcMemory);
  42. }

m_hBKBMAP 在Skinner()中初始化的,就是背景图片资源的句柄,我保留了。当然也可以重新在OnPaint中加载,觉得没有这个必要。除非是前面没有加载图片资源。(LoadImage函数加载图片)。

 

源代码参考(我上载的资源:PC CameraUI2.0中有类似代码)

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值