怎样让窗体透明而里面的控件不透明?
如图:http://cyoffice.myrice.com/tmp.JPG
怎样达到这样的效果?

解决方案 »

  1.   

    1.
    参考异型窗口的办法,调用SetWindowRgn改变窗口区域,挖掉非控件的窗口区域
    注意该区域是被挖掉了,而不是透明
    2.
    调用Windows 2000新增API中的UpdateLayeredWindow可以精细调整窗口中每一点的Alpha
    只不过UpdateLayeredWindow主要是用来以32位带Alpha通道的图片更新窗口内容的,不适合VB的控件机制
      

  2.   

    http://cyoffice.myrice.com/tmp.JPG该程序用的是方法2
    用UpdateLayeredWindow以32位带Alpha通道的图片更新窗口内容的其中的“控件”是用图片模拟的
    然后再处理一下鼠标事件
    这样就像控件了至于如何用程序动态生成32位带Alpha通道的图片
    建议你找几本专业的《数字图像处理》方面的书看看
    从头讲起太复杂了
      

  3.   

    他的界面用的是PNG图片,你找找 好象是"用PNG图片制作的启动界面"
      

  4.   

    TO zyl910:很荣幸你能赐教!我想借楼主的地方问你请教一二,可否?我们作出的透明对象之所以“透明”,依我的理解,就是把本对象后面的影像,即背景全部或部分(此为“半透明”,需要与本对象的影像进行合成处理)显示出来。当背景无变化时实现透明是不难办到的,而问题就在于变化的背景上如何实现透明,其中关键难点在于如何获取背景改变的消息。我想象中的全透明有如VB中的label对象的透明效果。
      

  5.   

    Windows系统为了减少刷新时的数据量,采用了剪裁窗口无效区机制
    也就是说,当某个窗口处于了下层窗口上面时,对于下层窗口被覆盖的区域就会被自动剪裁掉,在此区域上的绘图操作都立即返回
    所以靠Windows窗口机制是无法实现透明的到了Windows2000,microsoft也认识到透明窗口的重要性,所以提出分层窗口
    之所以叫分层窗口,这因为这种窗口中的图像是位于一个单独的内存位图中的
    当屏幕刷新时,Windows系统负责在桌面图像上叠加分层窗口图像,并将合并结果送往显存至于VB的Label为什么支持透明
    这是因为Label是所谓的“轻量级控件”,而不是Windows窗口VB在处理容器的WM_Paint消息时
    先触发容器的Paint事件,让容器画好背景
    再依次调用容器中的所有轻量级控件的刷新方法VB就是靠这种方法实现“轻量级控件”
    但是这种方法存在对屏幕的多次刷新,所以会发生闪耀比较好的做法是:
    处理WM_Paint时建立一个内存位图
    所有绘图操作都在这个内存位图进行
    全部画好后再一次性提交到窗口上
    (Delphi就是这样做的)只要设计好刷新事件的通知模式,做透明控件其实不难的
    现在存在一个实际问题
    许多VB程序员不懂刷新机制
    总喜欢直接在屏幕上画图
    这样就破坏了良好的刷新事件的通知模式
    人为的增加难度
    所以在VB中最好不要做自身透明的控件一般界面特效只需要控件内的子对象透明就行(比如WinXP资源管理器中“常见任务”的滑动时淡入淡出特效)
    所以可以使用“在内存位图上画好,再一次性提交到窗口”的办法
      

  6.   

    多谢[zyl910]的讲解!
    依你之见,不"直接在屏幕上画图",而先在内存中画,而后一次提交(这是本人已在采用的方法),可有什么办法?难道真的"在VB中最好不要做自身透明的控件"吗?
      

  7.   

    不是做不到,而是受VB刷新机制限制,会很闪的,不实用关键在于VB6出的太早了(1998)
    那时还没流行透明窗口
    所以VB6的刷新机制没设计好
      

  8.   

    看了"用PNG图片制作的启动界面"的实例,可以作出透明窗效果
    但为什么放上的控件都没了?难道真到放两个窗体,一个用来显示背景,一个用来显示控件~?
      

  9.   

    看了"用PNG图片制作的启动界面"的实例,可以作出透明窗效果
    但为什么放上的控件都没了? 这个应该是有办法解决的
      

  10.   

    Private Sub toggleFrame(inFlag As Boolean)
        Dim w As Single, h As Single
        Dim edge As Single, topEdge As Single
        Dim mLeft, mTop
        Dim i As Integer
        Dim R As Long
        Dim outer As Long, inner As Long
        
        mFormRegion = CreateRectRgn(0, 0, 0, 0)
        
        w = ScaleX(Width, vbTwips, vbPixels)
        h = ScaleY(Height, vbTwips, vbPixels)
        
        edge = (w - ScaleWidth) / 2
        topEdge = h - edge - ScaleHeight
        
        If inFlag Then
            outer = CreateRectRgn(0, 0, w, h)
            inner = CreateRectRgn(edge, topEdge, w - edge, h - edge)
            CombineRgn mFormRegion, outer, inner, RGN_DIFF
        End If
        
        For i = 0 To Me.Controls.Count - 1
            mLeft = ScaleX(Me.Controls(i).Left, Me.ScaleMode, vbPixels) + edge
            mTop = ScaleX(Me.Controls(i).Top, Me.ScaleMode, vbPixels) + topEdge
            R = CreateRectRgn(mLeft, mTop, _
                 ScaleX((Me.Controls(i).Width), Me.ScaleMode, vbPixels) + mLeft, _
                 ScaleY((Me.Controls(i).Height), Me.ScaleMode, vbPixels) + mTop)
            CombineRgn mFormRegion, R, mFormRegion, RGN_OR
        Next
        
        SetWindowRgn hwnd, mFormRegion, True
    End Sub自己看著辦吧。
    技術支持:[email protected]
      

  11.   

    这种界面只能用UpdateLayeredWindow来实现,窗体效果用一个PNG图片来实现,不过这种窗体上的VB控件将全部看不到,但是可以感应事件,那幅图里的那些窗体上的控件都是画上去的。