VBGood网站全文搜索 Google

搜索VBGood全站网页(全文搜索)
首页 - 经验之谈 - 演示了透明的窗体和不规则窗口
发表评论(0)作者:, 平台:, 阅读:11696, 日期:2000-05-18
VISUAL BASIC三级跳





  在小生的印象中,很多人对Visual Basic是不屑一顾的,他们总是固执的认为Visual Basic干不了大事,但事实上,通过Visual Basic本身快捷的开发模式和Windows API的强大支持,我们完全可以在较短的时间做出漂亮的应用程序来。诚然,用Windows API完成一些功能比较 口罗 嗦,但是决不复杂,不信吗?快来跟着小生一起做Visual Basic 三级跳。

  应该说,一个应用程序给用户最强烈的感受就是这个应用程序的界面,Winamp就是一个最好的例子,如图,这是小生编写的两个小程序,分别演示了透明的窗体和不规则窗口。首先我们来看一下透明窗体是怎样实现的:

  我们知道,在Windows中生成一个新的窗口时,默认的操作是生成长方形的窗口并且会毫不保留的盖住背景,但是我们同时也知道,Windows的窗口无非是能及时响应消息的图形区域罢了,很自然的,我们应该能想到将背景拷贝到窗体中即可实现“透明”的功能,在这里我们将用到几个Windows API,他们的定义如下:

  Declare Function GetDC Lib “user32" (ByVal hwnd As Long) As Long ‘获取窗口句柄

  Declare Function CreateCompatibleBitmap Lib“gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long ‘创建兼容图形设备环景

  Declare Function CreateCompatibleDC Lib “gdi32" (ByVal hdc As Long) As Long

  Declare Function SelectObject Lib “gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long

  Declare Function BitBlt Lib “gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long

  Declare Function DeleteDC Lib “gdi32" (ByVal hdc As Long) As Long

  Declare Function DeleteObject Lib “gdi32" (ByVal hObject As Long) As Long

  接下来,为工程中的窗体添加一个计时器、一个按钮和下面的代码:

  Dim nW, nH, myDC, hDestDC, hBMP, myLeft, myTop

  Private Sub cmdEnd_Click()

  Unload Me

  End Sub

  Private Sub Form_Load()

  '获取窗体的宽和高

  nW = Me.ScaleWidth

  nH = Me.ScaleHeight

  '获取背景的句柄

  hDestDC = GetDC(0)

  myDC = CreateCompatibleDC(hDestDC)

  hBMP=CreateCompatibleBitmap(hDestDC,ScaleX(Screen.Width,1,3),ScaleY(Screen.Height,1,3))

  SelectObject myDC, hBMP

  '把背景的图像拷贝到窗体中

  BitBlt myDC, 0, 0, ScaleX(Screen.Width, 1, 3), ScaleY(Screen.Height, 1, 3), hDestDC, 0, 0, vbSrcCopy

  myLeft = Me.Left

  myTop = Me.Top

  End Sub

  '把背景的图像拷贝到窗体中

  Sub Brush()

  nW = Me.ScaleWidth

  nH = Me.ScaleHeight

  BitBlt Me.hdc, 0, 0, nW, nH, myDC, ScaleX(Me.Left, 1, 3) + 4, ScaleY(Me.Top, 1, 3) + 28, vbSrcCopy

  End Sub

  Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)

  '结束程序时释放资源是每个程序员都必备的素质

  DeleteDC hDestDC

  DeleteObject hBMP

  End Sub

  Private Sub Form_Resize()

  '用Brush过程重画窗体

  Brush

  End Sub

  Private Sub Timer1_Timer()

  '定时检测,如果窗体位置改变则刷新窗体

  If Me.Left <> myLeft Or Me.Top <> myTop Then

  Form_Resize

  myLeft = Me.Left

  myTop = Me.Top

  End If

  End Sub

  好了,现在运行程序应该能看到控件好像悬空一样了吧,但是到这里并没有完,因为你很快就会发现它仅仅对刚刚运行时的背景透明,什么意思呢?就是说当你在多个软件间切换时,我们的窗体并不相应的透明而是依然显示原来的背景,这样,我们可以把Form_Load()过程中的那段代码添加到刷新过程中并强行刷新窗体即可,但是我不得不告诉你的是,这样会极大影响你的应用程序的速度,孰轻孰重就由你自己衡量了。接下来,我们来看一看不规则窗口的实现。同样的,我们也要用到几个Windows API:

  Declare Function ReleaseCapture Lib “user32" () As Long

  Declare Function SendMessage Lib “user32" Alias “SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long

  Declare Function CreateEllipticRgn Lib “gdi32" (ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long

  Declare Function SetWindowRgn Lib “user32" (ByVal hWnd As Long, ByVal hRgn As Long, ByVal bRedraw As Boolean) As Long

  Public Const HTCAPTION = 2

  Public Const WM_NCLBUTTONDOWN = &HA1

  事实上,上述函数中真正完成创建不规则窗口功能的是SetWindowRgn,但是作为一个任意形状的窗口,由于没有了标题栏,我们必须考虑到窗口的移动,因此需要用到ReleaseCapture和SendMessage,而CreateEllipticRgn则是用来创建弧形区域的,下面是实现图中的演示程序的代码:

  Private Sub Form_Load()

  SetWindowRgn hWnd, CreateEllipticRgn(0, 0, 1500, 1200), True

  End Sub

  Private Sub Form_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)

  ReleaseCapture

  SendMessage

  hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0&

  End Sub

  怎么样,够简单吧?当然,你肯定会说这种形状也是有规则的呀,事实上我们也可以创建完全不规则的窗体:比如我们希望用图片中的某一部分来作为游戏主角并且想把它当窗口打整,好了,首先我们要将图片中除主角以外的地方都填充为某种颜色A,然后把图片设成窗体的背景并用Point方法(记住,这里又是一个技巧,通过在Mouse_Down中使用该方法可以获得鼠标当前点的RGB值,把该值转换为16进制后前两位为Red,中间两位为Green)来识别图片,凡是遇到颜色A的地方就跳过,并把每一行(或每一列)剩下的地方创建成一个区域(用Windows API的CreateRectRgn函数),最后用Windows API的CombineRgn函数把这些区域合并成一个区域,并用SetWindowRgn赋给窗体即可,限于篇幅小生就不给出代码,唯一还要提个醒的是最好单独用一个程序来生成区域并存到文件中供主程序调用,否则你的程序将比“瘟到死”的启动还要令人痛恨^-^。

  到这里,想必各位看官已经构思出一幅用Visual Basic制作的优美软件蓝图了,可是接连的说了这么一堆Windows API,小生真的已经犯困了,幸好系统栏图标不用Windows API了,Visual Basic光盘的Tools\SysTray\SysTray.OCX已经有了这个