自定义VB系统控件一

来源:互联网 发布:ug看图软件 编辑:程序博客网 时间:2024/05/17 05:19

本篇文章面对的对象是初级VB程序员,最好有些Windows系统应用程序开发知识。在结束文章以前,前边任何内容均有可能更改,如果文中代码有触犯版权等问题,请与作者联系,如果作者本人同意,将会署名发布,如果不同意将予以删除。
由于本人文笔欠佳,所以还真不知能写出什么文章,本来打算写些.net方面的文章,但是由于刚刚接触.net不久,还没有什么经验体会,对于我而言经验最多的应该还是VB吧,毕竟已经用了两年多了。但是这仅仅是我自身比较而言并不是和其他人比较,因此决定将一些平时经验和技巧写下来,也就算整理一下资料吧,虽然是班门弄斧,但是希望这篇文章能对一些VB初学者有些帮助。希望使用VB开发应用的人能通过这篇文章得到一些启发,能从另一个角度来看待VB程序开发。

先谈谈我的个人想法:

不管我们使用什么计算机语言开发,VC,VB,BCB,JAVA,NET你都脱离不开操作系统,它就是我们软件的生存土壤,JAVA的跨平台其实是因为它的虚拟机,实质上虚拟机还是要依靠操作系统,.net可以说博大精深但是它最终还是调用操作系统提供的服务,在Windows2003上运行.net程序和在windows95上运行效果肯定不同,因此只要一种语言提供给我们一种直接调用操作系统服务的接口(API)我们就不能武断的说它某些事做不了。只不过是方便与否,难以程度有差别,说这些话有些位VB申冤的嫌疑,可以说我确实有这点私心,但是如果你选择了VB你就要相信它,想办法了解到,这样才能充分发挥它的功能。

通常一种语言用久了就不知不觉中用它来思考,这有好处也有坏处,真正了解一门语言就要学会在使用中用它来思考,但是因此也会带来思维定式。很多时候局限的不是语言本身而是我们的思想。因此我们需要不停的思考,从不同角度思考,正如我的bLog的标题“我思故我在”,这句话有些唯心,但实际上在没有上学之前,在没有接收唯物主义的哲学思想之前我应该算是唯心主义者。当时我总是想我眼里的世界包括人,动物,植物等所有的一切是否仅仅是在我眼里才呈现这个样子而在别人的眼中,是否这个世界是另一个模样,这个我现在也不知道,因为接触的是用我的双手,我看到的是用的眼睛,我感知的是用我的心灵,我无法代替别人,别人无法代替我。话题好像扯远了。

Visual Basic 是一种RAD工具,之所以说它是RAD工具就是因为很多底层初级的东西已经被IDE封装好,我们只要直接用就好了,因此我们可以用VB来进行快速的应用开发。

举个例子:

如果用代码创建一个正常工作的窗体至少需要调用如下几个API:

RegisterClass或RegisterClassEx:该函数为随后在调用Createwindow函数和CreatewindowEx函数中使用的窗口注册一个窗口类

UnregisterClass:删除一个窗口类,清空该类所需的内存

DefWindowProc:该函数调用缺省的窗口过程来为应用程序没有处理的任何窗口消息提供缺省的处理。该函数确保每一个消息得到处理。调用DefWindowProc函数时使用窗口过程接收的相同参数

GetMessage:该函数从调用线程的消息队列里取得一个消息并将其放于指定的结构

TranslateMessage:该函数将虚拟键消息转换为字符消息

DispatchMessage:该函数调度一个消息给窗口程序,通常调度从GetMessage取得的消息

ShowWindow:用于设置窗口的状态,其中包括窗口的隐藏、显示、最小化、最大化、激活等

UpdateWindow: 立即更新窗口内需要更新的任何部分

CreateWindowEx:该函数创建一个具有扩展风格的重叠式窗口、弹出式窗口或子窗口,其他与CreateWindow函数相同

CallWindowProc:该函数CallWindowProc将消息信息传送给指定的窗口过程。

SetWindowLong,GetWindowLong:用于获取或设置与窗口有关的信息

PostQuitMessage:将一条消息投递到指定窗口的消息队列

DestroyWindow:清除指定的窗口以及下属所有子窗口与包容窗口.

进行几个繁琐的操作才能创建一个窗体。然后还有进行各种消息处理等等,但是有了VB这种RAD工具所有这些我们都可以不用关心,因为VB已经为我们封装好了。

我们所要做的且关心的就是怎么设计我们自己的应用。

做个比喻就像我们已经有了房子只需要按照自己的需要进行装修即可,但是非RAD工具是从楼房的地基(地址有操作系统提供)开始。

但是,凡事没有绝对的优点也没有绝对的缺点。站在不同的角度看待同一个事物却会有不同的结果。

如果我想在VB中在反过来深入底层将是很麻烦的事。

按照自己的想法盖房子和将已经建好的楼房进行改建更麻烦(我这里用的是麻烦,并不是困难),它的难点就是如何找到切入点。

但是如果能够灵活运用系统API,能够找到切入点,将会起到事半功倍的效果。

下面用实际的例子进行一些演示说明,由于本人技术及篇幅有限,不事宜做复杂的说明。那些做为专题讨论,写这篇主要目的是起到抛砖引玉的作用。

严格说来操作系统只知道窗口控件(WinControl)的存在,我这里说的窗口控件可以这么理解就是在VB中具有hWnd(窗口句柄)的控件。他们都靠系统的消息驱动,因为我在这篇文章主要侧重点是利用API来发掘VB,因此涉及的对象基本都是指窗口控件,非窗口控件的创建、更新、销毁又它的父窗口控件来负责。

使用VC++编程的人一定会熟悉很多窗体控件风格常量,然后按照自己的需要创建窗体控件样式,而我们在VB中,这些统统被IDE包装起来的,我和根本看不到,但是利用API我们可以重新定义窗体控件的样式,下面就用实际例子来演示一下:

(这里我没有列出详细的API和常量声明,因为我主要想体现的是方法和思路)

 

  任何一个窗体控件,我们都可以给它加上ControlBox(所谓ControlBox,就是窗体的图标+最小化+最大化+关闭按钮)

Option Explicit
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, _
 ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, _
 ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter As Long,  _
 ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const GWL_STYLE = (-16)
Private Const WS_SYSMENU = &H80000
Private Const SWP_NOZORDER = &H4
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOMOVE = &H2
Private Const SWP_FRAMECHANGED = &H20
Private Const SWP_DRAWFRAME = SWP_FRAMECHANGED

Public Sub ControlSysMenu(ControlName As Control, SetTrue As Boolean)
   Dim dwStyle As Long
   dwStyle = GetWindowLong(ControlName.hwnd, GWL_STYLE)
   If SetTrue Then
      dwStyle = dwStyle Or WS_SYSMENU
   Else
   dwStyle = dwStyle - WS_SYSMENU
   End If
   dwStyle = SetWindowLong(ControlName.hwnd, GWL_STYLE, dwStyle)
    SetWindowPos ControlName.hwnd, ControlName.Parent.hwnd, 0, 0, 0, 0, SWP_NOZORDER Or _
 SWP_NOSIZE Or SWP_NOMOVE Or SWP_DRAWFRAME
End Sub

Private Sub Command1_Click()
ControlSysMenu Picture1, False
End Sub

任何一个窗体组件,我们都可以给它加上标题栏,通过拖动标题栏,可以实现控件的运行时移动。

'在窗体中加入一个按钮和一个图象框,再加入如下代码,
Option Explicit
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, _
 ByVal nIndex As Long) As Long
Private Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hwnd As Long, _
 ByVal nIndex As Long, ByVal dwNewLong As Long) As Long

Private Declare Function SetWindowPos Lib "user32" (ByVal hwnd As Long, ByVal hWndInsertAfter  _
As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const GWL_STYLE = (-16)
Private Const WS_CAPTION = &HC00000                  '  WS_BORDER Or WS_DLGFRAME
Private Const WS_THICKFRAME = &H40000
Private Const SWP_NOZORDER = &H4
Private Const SWP_NOSIZE = &H1
Private Const SWP_NOMOVE = &H2
Private Const SWP_FRAMECHANGED = &H20        '  The frame changed: send WM_NCCALCSIZE
Private Const SWP_DRAWFRAME = SWP_FRAMECHANGED

Public Sub ControlCaption(ControlName As Control, SetTrue As Boolean)

    Dim dwStyle As Long

    dwStyle = GetWindowLong(ControlName.hwnd, GWL_STYLE)

    If SetTrue Then

       dwStyle = dwStyle Or WS_CAPTION Or WS_THICKFRAME

    Else

       dwStyle = dwStyle - WS_CAPTION - WS_THICKFRAME

    End If

    dwStyle = SetWindowLong(ControlName.hwnd, GWL_STYLE, dwStyle)

     SetWindowPos ControlName.hwnd, ControlName.Parent.hwnd, 0, 0, 0, 0, SWP_NOZORDER Or _
 SWP_NOSIZE Or SWP_NOMOVE Or SWP_DRAWFRAME

End Sub

Private Sub Command1_Click()
ControlCaption Picture1, False
End Sub

任何一个窗体组件,我们都可以控制其显示风格为模式对话框的风格


Public Sub ControlModal(ControlName As Control, SetTrue As Boolean)

    Dim dwStyle As Long

    dwStyle = GetWindowLong(ControlName.hwnd, GWL_STYLE)

    If SetTrue Then

       dwStyle = dwStyle Or WS_POPUP

    Else

       dwStyle = dwStyle - WS_POPUP

    End If

    dwStyle = SetWindowLong(ControlName.hwnd, GWL_STYLE, dwStyle)

     SetWindowPos ControlName.hwnd, ControlName.Parent.hwnd, 0, 0, 0, 0, SWP_NOZORDER Or _
 SWP_NOSIZE Or SWP_NOMOVE Or SWP_DRAWFRAME

End Sub


任何一个窗体组件,我们都可以控制其显示风格为对话框的风格。

Public Sub ControlDialog(ControlName As Control, SetTrue As Boolean)

   Dim dwStyle As Long

   dwStyle = GetWindowLong(ControlName.hwnd, GWL_STYLE)

   If SetTrue Then

      dwStyle = dwStyle Or WS_DLGFRAME

   Else

      dwStyle = dwStyle - WS_DLGFRAME

   End If

   dwStyle = SetWindowLong(ControlName.hwnd, GWL_STYLE, dwStyle)

   SetWindowPos ControlName.hwnd, ControlName.Parent.hwnd, 0, 0, 0, 0, SWP_NOZORDER Or _
 SWP_NOSIZE Or SWP_NOMOVE Or SWP_DRAWFRAME

End Sub


只要有窗口,这是我们的前提,你可以在运行时随便更改它的大小。

Public Sub ControlSize(ControlName As Control, SetTrue As Boolean)

   Dim dwStyle As Long

   dwStyle = GetWindowLong(ControlName.hwnd, GWL_STYLE)

   If SetTrue Then

      dwStyle = dwStyle Or WS_THICKFRAME

   Else

      dwStyle = dwStyle - WS_THICKFRAME

   End If

   dwStyle = SetWindowLong(ControlName.hwnd, GWL_STYLE, dwStyle)

   SetWindowPos ControlName.hwnd, ControlName.Parent.hwnd, 0, 0, 0, 0, SWP_NOZORDER Or _
SWP_NOSIZE Or SWP_NOMOVE Or SWP_DRAWFRAME

End Sub

通过以上几个实例,我们知道了如何使用VB没有提供的窗体风格样式。下面将根据我的实际经历介绍几个具体的窗体控件的某些比较使用的扩展功能。

有两个知识点不能不说,消息机制,子类(Subclass)。

原创粉丝点击