透明浮动窗口

编译环境
 WIN2000以上操作系统,VC++6.0。
技术原理
如何实现透明窗口
    首先,从CWnd派生一个类 CfloatWnd,在Create 函数里加载位图,在OnPaint函数里绘制位图,详见源代码 。
  使用SetLayeredWindowAttributes可以方便的制作透明窗体,此函数在w2k以上才支持,而且如果希望直接使用的话,可能需要下载最新的SDK。不过此函数在w2k的user32.dll里有实现,所以如果你不希望下载巨大的sdk的话,可以直接使用GetProcAddress获取该函数的指针。
 
  SetLayeredWindowAttributes的函数原型如下:
BOOL SetLayeredWindowAttributes(
HWND hwnd, // handle to the layered window
COLORREF crKey, // specifies the color key
BYTE bAlpha, // value for the blend function
DWORD dwFlags // action
);

Windows NT/2000/XP: Included in Windows 2000 and later.
Windows 95/98/Me: Unsupported.(注意了,在win9x里没法使用的)
Header: Declared in Winuser.h; include Windows.h.
Library: Use User32.lib.
  一些常量 :
 
WS_EX_LAYERED = 0x80000;
LWA_ALPHA = 0x2;
LWA_COLORKEY=0x1;
  其中dwFlags有LWA_ALPHA和 LWA_COLORKEY

  LWA_ALPHA被设置的话,通过bAlpha决定透明度
.

  LWA_COLORKEY被设置的话,则指定被透明掉的颜色为crKey,其他颜色则正常显示
.

  要使使窗体拥有透明效果,首先要有WS_EX_LAYERED扩展属性(旧的sdk没有定义这个属性,所以可以直接指定为0x80000).
  例子代码 :

 1. 重载int CFloatWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) 
      if (CWnd::OnCreate(lpCreateStruct) == -1)
           return -1;
                 // 加入 WS_EX_LAYERED 扩展属性
      SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE,
           GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000);
// 加载动态库 User32.DLL
      HINSTANCE hInst = LoadLibrary("User32.DLL");
      if(hInst)
      {
           typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);
           MYFUNC fun = NULL;
         // 取得 SetLayeredWindowAttributes 函数指针
          fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");
          if(fun)fun(this->GetSafeHwnd(),0,100,2);
          FreeLibrary(hInst);
      }
      m_iCount=0;
// WINDOWS 时钟和 SetLayeredWindowAttributes 函数实现淡入淡出的透明效果
      this->SetTimer(1,10,0);
      return 0;
 
2. 重载void CFloatWnd::OnTimer(UINT nIDEvent)
      // m_bAdd 是表示颜色是加深还是减浅的标志
if(m_bAdd)
      {
           m_iCount++;
           if(m_iCount>=255)
           {
                 m_bAdd=false;
           }
      }else
      {
           m_iCount--;
           if(m_iCount<=0)
           {
                 m_bAdd=true;
           }
 
      }
      HINSTANCE hInst = LoadLibrary("User32.DLL");
      if(hInst)
      {
           typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD);
           MYFUNC fun = NULL;
         // 取得 SetLayeredWindowAttributes 函数指针
          fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes");
         
            if(fun)fun(this->GetSafeHwnd(),0,m_iCount,2);
          FreeLibrary(hInst);
      }
      CWnd::OnTimer(nIDEvent);
如何实现浮动
实现浮动有很多方法,可以用钩子函数来做。我采用一种比较简便的方法,就是让操作系统误认为窗口是非客户区的方法。
1.  重载UINT CFloatWnd::OnNcHitTest(CPoint point)函数
      CWnd::OnNcHitTest(point);
     // 始终返回 非客户区的标题区域
       return HTCAPTION ;
    注意:打开CLASSWIZAR,找到CfloatWnd类,在CLASS INFO 标签项下有个MESSAGE FILTER ,选择为WINDOW选项,就可以出现WM_NCHITTEST消息。
2.  重载void CFloatWnd::OnNcLButtonDown(UINT nHitTest, CPoint point)
      //   调整窗口位置
      CRect rt,rt1;
      this->GetWindowRect(&rt);
      CWnd::OnNcLButtonDown(nHitTest, point);
      this->GetWindowRect(&rt1);
      CPoint pt;
      if(GetCursorPos(&pt))
      {
      if(!rt1.PtInRect(pt))
      {
      this->MoveWindow(&rt);
      }
      }
这段代码是因为在只是点击窗口而不拖动的情况下,窗口的位置会变的很乱,显示不到屏幕上;不信的话就不重载OnNcLButtonDown,再点击窗口而不拖动的情况下就会找不到窗口了。我就在在此做了权宜的处理,不知哪位高人有更好的方法解决这个问题,请赐教。
 
请点击图标下载浏览:

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值