zoukankan      html  css  js  c++  java
  • PNG透明窗体全攻略(控件不透明)

    http://blog.csdn.net/riklin/article/details/4417247

     
        看好了,这是XP系统,未装.net。我的Photoshop学的不太好,把玻璃片弄的太透了些,如果你们有好的美术,再加上这种技术,肯定会如鱼得水。下面就来详细说说它的制作过程吧: 
        第 一步:在VC6中使用GDI+:你得从网上弄个GDI+ for XP的库,大约500K。如果找不到的话,找我QQ要吧,我会把这个窗口的源程序一起发给你的。把它解压后,将所有文件还包括子目录中的文件复制到你的项 目目录。在stdafx.h中加入以下代码: 
                 #include "gdiplus.h" 

                using namespace Gdiplus; 
                #pragma comment(lib, "gdiplus.lib") ////请修改为你的.lib文件路径 
        我的项目名为Test,所以在TestApp中加入全局变量 
    ULONG_PTR gdiplusToken; 
        在BOOL CTestApp::InitInstance()中加入这两行: 
           GdiplusStartupInput gdiplusStartupInput; 
           GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); 
        记住在线程退出后要御掉GDI+,它很占资源的,在int CTestApp::ExitInstance() 中加入这行: 
          GdiplusShutdown(gdiplusToken); 
        一切准备工作就绪,开始制作窗口了。 

        二、制作PNG图像:这不是程序员的事,是美工的事,可是目前美术技术都是我一人,所以干脆连PNG一起教你们做了吧。 
        先打开Photoshop(简称PS),打开一张背景图,在背景图上使用圆角矩形工具 画个矩型,再用图层样式调出如下绿色玻璃片: 
     
        什么?怎么个调出来的?你还真以为我什么都教你?要是我连PS的过程都写上来,那我干脆写本书得了。体谅一下吧,写教程是需要大量时间的,所以能省则省。 
        将背景去掉,将玻璃保存成PNG图片,不需要设置任何参数,PNG是自动使用这种与背景溶合透明的,强大吧^_^! 
        再用同样的方法,制作绿色按钮 ,记住做界面的时候,一般要使用一种主色调,在这里我随便用了下绿色作为主色调,现在网络流行的是蓝色。文字则不能用RGB色彩,这样用户容易产生视觉疲劳。我做这个界面只是想试试绿玻璃好不好看,结果觉得不怎么好看,以后有空再弄个蓝玻璃试试吧。 
        按钮不需要保存成PNG,因为我不准备将它透明。至于这种“透明控件”的文章,你在网上一搜一大堆。 
        继续吧!还要做其它3个按钮,“确定”的按下效果,“取消”的拾起和按下效果,在这里我就不截图了。 
        美术都搞定,开始写代码。 

        三、写代码之前,我先说说工序:先用SetWindowLong将对话框设置成层级窗体,再使用GDI+显示图片。显示成功后再用UpdateLayeredWindow函数进行透明处理。 
        现在问题出来了,你会发现你原来在窗口上画的控件一概不显示,怎么办呢?我是在这个窗口上再盖上另一个对话框,设置成启动窗体那种样式,所有消息都在这个前景窗体上处理。 
        问题又来了,前景窗体盖上去,后面窗口又看不见了,怎么办呢?我又想了办法,在前景窗体加了透明色,在这里我是用粉红色,因为在电脑中粉红色用的最少,因为它很刺眼。用这个方法的缺点就是你的控件不能有粉红色。 
        最后将两个按钮改成位图按钮即可。 

        现在来看详细制作过程吧: 
        定义成员变量:在TestDlg.h中定义 
    BLENDFUNCTION m_Blend; 
    HDC m_hdcMemory; 

        改成层级窗体:在BOOL CTestDlg::OnInitDialog()函数中加入如下代码: 
    //窗体样式为0x80000为层级窗体 
    DWORD dwExStyle=GetWindowLong(m_hWnd,GWL_EXSTYLE); 
    SetWindowLong(m_hWnd,GWL_EXSTYLE,dwExStyle^0x80000); 

        加载PNG图片: 
    //绘制内存位图 
    HDC hdcTemp=GetDC()->m_hDC; 
    m_hdcMemory=CreateCompatibleDC(hdcTemp); 
    HBITMAP hBitMap=CreateCompatibleBitmap(hdcTemp,500,500); 
    SelectObject(m_hdcMemory,hBitMap); 

    //使用GDI+载入PNG图片 
    HDC hdcScreen=::GetDC (m_hWnd); 
    RECT rct; 
    GetWindowRect(&rct); 
    POINT ptWinPos={rct.left,rct.top}; 
    Graphics graph(m_hdcMemory);   //GDI+中的类 
    Image image(L"bk.png",TRUE);   //GDI+中的类 
    graph.DrawImage(&image,0,0,267,154); //后面两个参数要设置成跟图片一样大小,否则会失真 

        窗口透明贴图: 
    //使用UpdateLayerWindow进行窗口透明处理 
    HMODULE hFuncInst=LoadLibrary("User32.DLL"); 
    typedef BOOL (WINAPI *MYFUNC)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);           
    MYFUNC UpdateLayeredWindow; 
    UpdateLayeredWindow=(MYFUNC)GetProcAddress(hFuncInst,"UpdateLayeredWindow"); 
    SIZE sizeWindow={267,154}; 
    POINT ptSrc={0,0}; 
    UpdateLayeredWindow( m_hWnd,hdcScreen,&ptWinPos,&sizeWindow,m_hdcMemory,&ptSrc,0,&m_Blend,2); 

        使用上述代码后,运行程序,你会发现你的窗口已经是透明的了,下面进行控件处理: 

        四、前景窗体 
        新建对话框,画上控件,我在这里起名为COnWindow,随便起的,不要笑我^_^。 
     
        读者奇怪的是,这上面怎么没有“用户名、密码”两个Label控件?不好意思,因为我的玻璃做的太透,这些文字在玻璃上已经很难看清楚,所以我干脆用PS描了下边,直接画到前景上去了,就成了这种效果 ,忽优了你们一下,不好意思,快去画吧^_^。 
       
        定义成员变量:在OnWindow.h中定义: 
    CBrush m_brush;  //背景画刷 
    CBitmapButton m_ok; 
    CBitmapButton m_cancel; 

        设置画笔:在在BOOL COnWindow::OnInitDialog()加入一行: 
      m_brush.CreateSolidBrush(RGB(255,0,255));  //背景设置为粉红色 


        改为层级窗体: 
    //SetWindowsLong将窗体设置为层级窗体 
    DWORD dwExStyle=GetWindowLong(m_hWnd,GWL_EXSTYLE); 
    SetWindowLong(m_hWnd,GWL_EXSTYLE,dwExStyle|0x80000); 

        设置透明色: 
    //用SetLayeredWindowAttributes设置透明色为0,它比UpdateLayeredWindow的使用要简单些 
    HMODULE hInst=LoadLibrary("User32.DLL"); 
    typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD); 
    MYFUNC SetLayeredWindowAttributes = NULL; 
    SetLayeredWindowAttributes=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes"); 
    SetLayeredWindowAttributes(this->GetSafeHwnd(),0xff00ff,0,1); 
    FreeLibrary(hInst); 

        不要忘记把窗体前景刷成粉红色:在HBRUSH COnWindow::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) 消息映射函数中加入代码: 
    HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); 
    // TODO: Change any attributes of the DC here 
    if(nCtlColor=CTLCOLOR_DLG) 
      return m_brush; 
    return  CDialog::OnCtlColor(pDC,   pWnd,   nCtlColor);   

        现在要把前景窗体和背景窗体联动,这可是关键点: 
        把 前景窗体设置成启动窗体,无标题栏,样式为Popup弹出式。写到这里,我不得不说的是:我曾想把前景窗体设置成Child,发现前景窗体又被“透明”掉 了,什么都看不见,郁闷呀,所以只好用OnMove消息来设计窗体同步了。如果有对窗体机制比较熟悉的高手朋友,希望帮助我用更好的解决方法。 

        组合窗口,并保持联动: 
        在TestDlg.h中加入头文件:#include "OnWindow.h",再定义变量COnWindow *pChildWnd; 

        在void CTestDlg::OnMove(int x, int y) 加入如下代码,看清楚了,这里是CTestDlg透明窗口。矩形的坐标运算你可以自己修改,关键要跟背景对齐: 
    CDialog::OnMove(x, y); 
    // TODO: Add your message handler code here 
    CRect rcWindow;                  // 使用MoveWindow函数的示例 
    GetWindowRect(rcWindow); 
    rcWindow.bottom-=10; 
    rcWindow.left+=10; 
    rcWindow.right-=10; 
    rcWindow.top+=20; 
    pChildWnd->MoveWindow(&rcWindow); 

        创建窗体时:在int CTestDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) 加入如下代码: 
    //创建子窗体 
    pChildWnd=new COnWindow(this); 
    pChildWnd->Create(IDD_ONWINDOW_DIALOG); 
    pChildWnd->ShowWindow(SW_SHOW); 

        你现在看到窗体上没有标题栏吧?你把鼠标移到窗口顶部,还可以照样移动窗口,知道为什么吗?因为窗口虽然透明了,但是背景窗口的任何控件都是存在的,只是不显示,它还能照样响应事件,不信你在背景窗口上放上个按钮试试。不错吧?又省掉一些代码。 

        五、最后,我们来处理位图按钮:VC6的CBitmapButton::LoadBitmaps方法不能直接贴上16位真彩按钮,于是我将两个真彩色按钮用Acdsee32转换成256色的,就可以直接载入了,相信你们也没看出来吧? 
        处理成256色后,再在BOOL COnWindow::OnInitDialog() 写入代码: 
    //载入按钮位图 
    m_ok.LoadBitmaps(IDB_OK1,IDB_OK2); 
    m_cancel.LoadBitmaps(IDB_CANCEL1,IDB_CANCEL2); 
    m_ok.SubclassDlgItem(IDOK, this); 
    m_cancel.SubclassDlgItem(IDCANCEL, this); 
        现在按下按钮只能关闭自己,给父窗口发个消息吧:在void COnWindow::OnOK()和void COnWindow::OnCancel() 都加入代码:
    HWND hWnd=GetParent()->m_hWnd;
    ::SendMessage(hWnd,WM_CLOSE,0,0);

    http://blog.csdn.net/witch_soya/article/details/6889939

  • 相关阅读:
    LeetCode Power of Three
    LeetCode Nim Game
    LeetCode,ugly number
    LeetCode Binary Tree Paths
    LeetCode Word Pattern
    LeetCode Bulls and Cows
    LeeCode Odd Even Linked List
    LeetCode twoSum
    549. Binary Tree Longest Consecutive Sequence II
    113. Path Sum II
  • 原文地址:https://www.cnblogs.com/findumars/p/6147171.html
Copyright © 2011-2022 走看看