我想了解FTP控件应用全过程!(不够分可再加!系统不能让我给再多的分)

解决方案 »

  1.   

    如何在属性窗口显示About?
    用鼠标点选About的子程序,然后点过程属性菜单,选Advanced,Programe ID选AboutBox即可! 同样,如果要使控件的属性能绑定数据库,以及要能使控件在对象浏览器为显示属性、事件、方法的相关说明,也是使用这一菜单弹出的对话框。 控件开发的原则控件开发的原则首先是,控件中不可以再用Activex控件。因此,我们最多只能以基本控件做控件组件。但是,事实上,有时我们用这些反而不好!
    因为有时不用基本控件也行!
    运行以下代码,你可以看出,代码一样可以生成我们所要的组件:Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
    End Type' flags for DrawFrameControlPrivate Const DFC_CAPTION = 1 'Title bar
    Private Const DFC_MENU = 2 'Menu
    Private Const DFC_SCROLL = 3 'Scroll bar
    Private Const DFC_BUTTON = 4 'Standard buttonPrivate Const DFCS_CAPTIONCLOSE = &H0 'Close button
    Private Const DFCS_CAPTIONMIN = &H1 'Minimize button
    Private Const DFCS_CAPTIONMAX = &H2 'Maximize button
    Private Const DFCS_CAPTIONRESTORE = &H3 'Restore button
    Private Const DFCS_CAPTIONHELP = &H4 'Windows 95 only:
    'Help buttonPrivate Const DFCS_MENUARROW = &H0 'Submenu arrow
    Private Const DFCS_MENUCHECK = &H1 'Check 
    Private Const DFCS_MENUBULLET = &H2 'Bullet
    Private Const DFCS_MENUARROWRIGHT = &H4Private Const DFCS_SCROLLUP = &H0 'Up arrow of scroll
    'bar
    Private Const DFCS_SCROLLDOWN = &H1 'Down arrow of
    'scroll bar
    Private Const DFCS_SCROLLLEFT = &H2 'Left arrow of
    'scroll bar
    Private Const DFCS_SCROLLRIGHT = &H3 'Right arrow of
    'scroll bar
    Private Const DFCS_SCROLLCOMBOBOX = &H5 'Combo box scroll
    'bar
    Private Const DFCS_SCROLLSIZEGRIP = &H8 'Size grip
    Private Const DFCS_SCROLLSIZEGRIPRIGHT = &H10 'Size grip in
    'bottom-right
    'corner of windowPrivate Const DFCS_BUTTONCHECK = &H0 'Check boxPrivate Const DFCS_BUTTONRADIO = &H4 'Radio button
    Private Const DFCS_BUTTON3STATE = &H8 'Three-state button
    Private Const DFCS_BUTTONPUSH = &H10 'Push buttonPrivate Const DFCS_INACTIVE = &H100 'Button is inactive
    '(grayed)
    Private Const DFCS_PUSHED = &H200 'Button is pushed
    Private Const DFCS_CHECKED = &H400 'Button is checkedPrivate Const DFCS_ADJUSTRECT = &H2000 'Bounding rectangle is
    'adjusted to exclude the
    'surrounding edge of the
    'push buttonPrivate Const DFCS_FLAT = &H4000 'Button has a flat border
    Private Const DFCS_MONO = &H8000 'Button has a monochrome
    'borderPrivate Declare Function DrawFrameControl Lib "user32" (ByVal _
    hDC&, lpRect As RECT, ByVal un1 As Long, ByVal un2 As Long) _
    As Boolean'********************************************************************
    ' Helper function that allows a you to load a rect on one line
    '********************************************************************
    Private Function MakeRect(l As Long, t As Long, w As Long, _
    h As Long) As RECT
    With MakeRect
    .Left = l
    .Top = t
    .Right = l + w
    .Bottom = t + h
    End WithEnd FunctionPrivate Sub Form_Load()
    ScaleMode = vbPixels
    AutoRedraw = True'Captions
    DrawFrameControl hDC, MakeRect(10, 10, 15, 15), DFC_CAPTION, _
    DFCS_CAPTIONCLOSEDrawFrameControl hDC, MakeRect(10, 30, 15, 15), DFC_CAPTION, _
    DFCS_CAPTIONRESTOREDrawFrameControl hDC, MakeRect(10, 50, 15, 15), DFC_CAPTION, _
    DFCS_CAPTIONMAX Or DFCS_INACTIVE' Menus
    DrawFrameControl hDC, MakeRect(30, 10, 15, 15), DFC_MENU, _
    DFCS_MENUARROWDrawFrameControl hDC, MakeRect(30, 30, 15, 15), DFC_MENU, _
    DFCS_MENUCHECKDrawFrameControl hDC, MakeRect(30, 50, 15, 15), DFC_MENU, _
    DFCS_MENUBULLET' Scrollbars
    DrawFrameControl hDC, MakeRect(50, 10, 15, 15), DFC_SCROLL, _
    DFCS_SCROLLUPDrawFrameControl hDC, MakeRect(50, 30, 15, 15), DFC_SCROLL, _
    DFCS_SCROLLSIZEGRIPDrawFrameControl hDC, MakeRect(50, 50, 15, 15), DFC_SCROLL, _
    DFCS_SCROLLRIGHT Or DFCS_INACTIVE' Checkboxes
    DrawFrameControl hDC, MakeRect(70, 10, 15, 15), DFC_BUTTON, _
    DFCS_BUTTONCHECKDrawFrameControl hDC, MakeRect(70, 30, 15, 15), DFC_BUTTON, _
    DFCS_BUTTONCHECK Or DFCS_CHECKEDDrawFrameControl hDC, MakeRect(70, 50, 15, 15), DFC_BUTTON, _
    DFCS_BUTTONCHECK Or DFCS_CHECKED Or DFCS_BUTTON3STATE' Option Buttons
    DrawFrameControl hDC, MakeRect(90, 10, 15, 15), DFC_BUTTON, _
    DFCS_BUTTONRADIODrawFrameControl hDC, MakeRect(90, 30, 15, 15), DFC_BUTTON, _
    DFCS_BUTTONRADIO Or DFCS_CHECKEDDrawFrameControl hDC, MakeRect(90, 50, 15, 15), DFC_BUTTON, _
    DFCS_BUTTONRADIO Or DFCS_CHECKED Or DFCS_FLAT' Push Button
    DrawFrameControl hDC, MakeRect(110, 10, 50, 20), DFC_BUTTON, _
    DFCS_BUTTONPUSHDrawFrameControl hDC, MakeRect(110, 40, 50, 20), DFC_BUTTON, _
    DFCS_BUTTONPUSH Or DFCS_PUSHEDEnd Sub
    由此,如果你要做一个观象ComboBox的控件,你是否要用ComboBox加Hook或者DriveBox加Hook?一定不需要,你只要一个TextBox或者一个PictureBox就足够了!
    可以吗?你试试,一定能做出来的!
    好了,我们已经说了各种原料的加工过程。那么,现在我们就做一个“汉堡坯”,将PictureBox用代码改为ComboBox的外观:模块:
    Option ExplicitPrivate Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
    End Type' flags for DrawFrameControl
    Private Const DFC_SCROLL = 3 'Scroll barPrivate Const DFCS_SCROLLCOMBOBOX = &H5 'Combo box scroll
    Private Const DFCS_INACTIVE = &H100 'Button is inactive
    '(grayed)
    Private Const DFCS_PUSHED = &H200 'Button is pushedPrivate Const DFCS_FLAT = &H4000 'Button has a flat border
    Private Const DFCS_MONO = &H8000 'Button has a monochrome
    'borderPrivate Declare Function DrawFrameControl Lib "user32" (ByVal _
    hDC&, lpRect As RECT, ByVal un1 As Long, ByVal un2 As Long) _
    As BooleanPrivate Declare Function GetClientRect Lib "user32" (ByVal _
    hwnd As Long, lpRect As RECT) As LongPublic Sub DrawComboBtn(Ctl As Control, bPushed As Boolean, bFlat As Boolean)Dim BtnFlags As LongCtl.ScaleMode = vbPixelsBtnFlags = DFCS_SCROLLCOMBOBOX Or (-bPushed * DFCS_PUSHED) _
    Or (-bPushed * DFCS_FLAT) Or (-bFlat * DFCS_MONO)DrawFrameControl Ctl.hDC, _
    MakeRect(Ctl.Width - 20, 0, 16, Ctl.Height - 4), _
    DFC_SCROLL, BtnFlags
    Ctl.Refresh
    End SubPrivate Function MakeRect(l As Long, t As Long, w As Long, _
    h As Long) As RECT
    With MakeRect
    .Left = l
    .Top = t
    .Right = l + w
    .Bottom = t + h
    End WithEnd Function
    窗体部分只要处理三个事件:Private Sub Form_Load()DrawComboBtn Picture1, False, FalseEnd SubPrivate Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Sin
    gle, Y As Single)
    If X >= Picture1.Width - 20 And X <= Picture1.Width - 4 And _
    Y > 0 And Y <= Picture1.Height - 4 ThenDrawComboBtn Picture1, True, False
    End IfEnd SubPrivate Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Singl
    e, Y As Single)
    If X >= Picture1.Width - 20 And X <= Picture1.Width - 4 And _
    Y > 0 And Y <= Picture1.Height - 4 Then
    DrawComboBtn Picture1, False, False
    End If
    End Sub运行一下,看看,是不是一个可用的坯子?你还可以改为浮动的!
    由此,我们不再需要用HOOK改造ComboBox或DriveBox了。
      

  2.   

    那个HOOK代码如何写呢:
    以下即是:
    Option ExplicitPublic Declare Function CallWindowProc Lib "user32" Alias "Ca
    llWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal 
    Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Public Declare Function SetWindowLong Lib "user32" Alias "Set
    WindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong
    As Long) As Long
    Public m_FrmhWnd As Long
    Public m_Hook As Boolean
    Private m_PrevWndProc As Long
    Public Sub Hook()
    If Not m_Hook Then
    m_PrevWndProc = SetWindowLong(m_FrmhWnd, GWL_WNDPROC, AddressOf Wind
    owProc)
    m_Hook = True
    End If
    End SubPublic Sub Unhook()
    If m_Hook Then
    Call SetWindowLong(m_FrmhWnd, GWL_WNDPROC, m_PrevWndProc)
    m_Hook = False
    End If
    End SubPrivate Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, ByVal wPar
    am As Long, ByVal lParam As Long) As LongSelect Case uMsgCase WM_NCACTIVATE
    WindowProc = CallWindowProc(m_PrevWndProc, hw, uMsg, 1, lParam)Case Else
    WindowProc = CallWindowProc(m_PrevWndProc, hw, uMsg, wParam, lPa
    ram)End Select
    End Function只要你在前面的窗体获取焦点前Hook父窗体,则一切就能如何所愿了。
    如何我们再看看这个原工程,就会发现,工具条窗口中的标题栏是用label加上按钮做的
    一个假的标题栏。同样DreamWaver也是这样!这当然节省资源。不过如果你要做得逼真,则你需要用PictureBox,这样可以进行色彩渐变,同时用我们
    上面的API生成标题栏按钮,则就是真的标题栏了。如果你还有想法,则还可以加上图标
    ,并显示系统菜单!
    须要注意的是,标题栏的色彩渐变是HLS模式峭是RGB,你得使用相关的API函数。接下来,我们再谈一个问题:
    关于枚举的使用。控件中为什么要用枚举?因为使用枚举,则使用户在录入属性时不会
    录入非法属性。同时也可以与系统中的其它控件的属性设置保持一致。
    但是,有很多控件就是实现不了这个一致,因为,变量不可以数字开头,则 3D 这个A
    ppearance属性的枚举就不允许存在,同样, Fixed Single 这种中问有空格的也不行。
    然而你又不能用上系统中缺省的枚举,怎么办?事实上你忘了标点符号的用法了,如果你记得,有这么一个特殊的标点:[]
    用这一对标点,你就可以实现了!
    我们定义以下枚举:Public Enum cApperance
    [Flat] = 0
    [3D] = 1
    End EnumPublic Enum cBorderStyle
    [None] = 0
    [Fixed Single] = 1
    End Enum然后你可以用此来设定你的控件的Appearance与BorderStyle属性,
    在使用你的控件时,你一定会发现,与系统中的一样!
    其实,写ActiveX控件最难的地方是,别人写不出来的你要能写出来。
    通常,我们编程只要需要,找控件用就行了。但是Activex中你不能再调用ActiveX,这
    样会使你的控件失去稳定性以及实用性,并增加了对你所用的ActveX的依赖性。所以,
    所有的一切,你都得自己去写。比如,高级的控件中,选项卡随处可见。就如VB开发环
    境中的色彩下拉,其中就有选项卡,难道还要引用选项卡控件?
    如果这样,前者注册不成功,则后者运行不了!
    因此,我们这里给一个选项卡的例子:(工程见光盘中的源程序)Private Sub Form_Load()
    TabCtl_loadEnd Sub
    Private Sub LabTit_Click(Index As Integer)
    TabCtlSet IndexEnd Sub
    Sub Draw3dCtl(F As Form, C As Control, Optional b3Line As String = "0&q
    uot;)Const White = &HFFFFFF
    Const DarkGrey = &H80000015
    Dim X1 As Integer
    Dim X2 As Integer
    Dim Y1 As Integer
    Dim Y2 As Integer
    Dim cHeight As Integer
    Dim cWidth As Integer
    Dim cLeft As Integer
    Dim cTop As Integer
    Dim LForColor As LongLForColor = C.BackColor
    F.DrawWidth = 3cLeft = C.Left
    cTop = C.Top
    cHeight = C.Height
    cWidth = C.Width'Top
    X1 = cLeft
    X2 = cLeft + cWidth
    Y1 = cTop
    Y2 = cTop
    If b3Line = "4" Then
    F.ForeColor = LForColor
    Else
    F.ForeColor = White
    End If
    F.Line (X1, Y1)-(X2, Y2)'Left
    X1 = cLeft
    X2 = cLeft
    Y1 = cTop
    Y2 = cTop + cHeight
    If b3Line = "4" Then
    F.ForeColor = LForColor
    Else
    F.ForeColor = White
    End If
    F.Line (X1, Y1)-(X2, Y2)
    'Buttom
    X1 = cLeft
    X2 = cLeft + cWidth
    Y1 = cTop + cHeight
    Y2 = cTop + cHeight
    If b3Line = "0" Then
    F.ForeColor = DarkGrey
    ElseIf b3Line = "1" Then
    F.ForeColor = LForColor
    ElseIf b3Line = "2" Then
    F.ForeColor = White
    End If
    F.Line (X1, Y1)-(X2, Y2)'Right
    X1 = cLeft + cWidth
    X2 = cLeft + cWidth
    Y1 = cTop
    If b3Line = "2" Then
    Y2 = cTop + cHeight - 35
    Else
    Y2 = cTop + cHeight
    End If
    If b3Line = "4" Then
    F.ForeColor = LForColor
    Else
    F.ForeColor = DarkGrey
    End If
    F.Line (X1, Y1)-(X2, Y2)
    End Sub
    Private Sub Pictab_Click(Index As Integer)TabCtlSet IndexEnd Sub
      

  3.   

    Private Sub TabCtlSet(Optional Index As Integer = 0)
    Dim i As Integer
    Static sIndex As Integer
    If Index = sIndex Then
    Exit Sub
    End If
    PicTab(sIndex).Tag = "2"PicTab(Index).Tag = "1"Fratab(sIndex).Visible = False
    MakeCtlSize PicTab(sIndex), False
    MakeCtlSize PicTab(Index), True
    For i = 0 To 3
    Draw3dCtl Me, Fratab(i)
    Next i
    For i = 0 To 3
    Draw3dCtl Me, PicTab(i), PicTab(i).Tag
    Next i
    Fratab(Index).Visible = TruesIndex = Index
    Fratab(Index).ZOrder
    PicTab(Index).ZOrder
    LabTit(Index).ZOrder
    Refresh
    End Sub
    Private Sub TabCtl_load()
    Dim i As Integer
    For i = 0 To 3
    PicTab(i).BackColor = Me.BackColor
    Fratab(i).BackColor = Me.BackColor
    Fratab(i).Left = 180
    Fratab(i).Top = 570
    Next i
    MakeCtlSize PicTab(0), True
    For i = 1 To 3
    PicTab(i).Height = 310
    MakeCtlSize PicTab(i), False
    Next i
    PicTab(0).Tag = "1"
    For i = 0 To 3
    Draw3dCtl Me, Fratab(i)
    Draw3dCtl Me, PicTab(i), PicTab(i).Tag
    Next i
    Fratab(0).Visible = True
    Fratab(0).ZOrder
    PicTab(0).ZOrder
    LabTit(0).ZOrder
    Refresh
    End SubPrivate Sub MakeCtlSize(C As Control, Optional ByVal IsGranda As Boolean = F
    alse)
    If IsGranda = False Then
    If C.Height = 370 Then
    Draw3dCtl Me, C, "4"
    C.Height = 310
    C.Top = C.Top + 35
    C.Left = C.Left + 35
    C.Width = C.Width - 35
    Else
    Exit Sub
    End If
    Else
    If C.Height = 370 Then
    Exit Sub
    Else
    Draw3dCtl Me, C, "4"
    C.Height = 370
    C.Top = C.Top - 35
    C.Left = C.Left - 35
    C.Width = C.Width + 35
    End If
    End If
    End Sub注意,这一例子,Form的AutoRedraw属性为True
    同样,ListBox有时可以用现成的,有时同样要你自己写。用什么:PictureBox
    农历控件中日期显示部分实际就是一个list,不过不是List控件。这样,你的Activex中
    所用的控件才会少,占用资源才会少!
    真正开发,说起来是很简单。新建一个控件工程,按需要,可以增加UserControl类,然
    后写代码,再用控件界面向导生成属性、方法与事件,如果需要,还可以运行属性页向
    导,让你的控件有属性页。
    但是,一个商业的控件,一定不能有任何Bug,这就要使你的程序数据随时保证有效。
    由此,属性不能用Public变量代替,因为在属性过程中你可以检则并设置数据的有效性

    当然,除了在属性过程中检查外,还可以在相应过程中再更改,比如:
    你可以对控件的大小这样处理:Private Sub UserControl_Resize()
    ' Check to see if the control is larger or smaller than the preset
    ' minimum or maximum size.
    ' If it is larger or smaller, set the size of the control.
    Select Case Height
    Case Is < 2400
    Height = 2400
    Case Is > 3600
    Height = 3600
    End SelectSelect Case Width
    Case Is < 2400
    Width = 2400
    Case Is > 3600
    Width = 3600
    End Select
    ' The label reports the height and width of the control in
    ' twips even if the container has a different scalemode.
    Label1.Caption = "Height: " & Height
    Label2.Caption = "Width: " & Width
    End Sub再有,好的控件有时同样需要有帮助,有时甚致要有What's this 的帮助!怎么加呢?你可以查MSDN的KB,我不再多讲了!同样,由于控件是由多个部件组成的,因此,你要对控件的大小以及Enabled属性一一设置。否则,你只用UserControl.Enabled=False,实际上你的控件仍是可用的!说起属性,还有两个问题:
    其一是缺省属性的问题。VB6的控件全部都有缺省属性,比如我们可以用label="Hello",实际调用的即是Caption这个缺省属性。
    那么,如何作缺省属性呢?
    你只要选中Get属性过程,然后点击过程属性菜单,再点Advanced按钮,在Procedure ID中选择Default,这样这一属性就是缺省属性了!另一个是:List属性如何做?(当然,你同样可以做成List方法,不过,确实有控件存在List属性)
    其实,类向导只生成单一参数的属性,平常我们都用不到多参属性,事实上多参数的属性是可以的!以下即是CLASS类中List属性的代码:Option Explicit
    Private mvarList() As VariantPrivate Sub Class_Initialize()
    ReDim Preserve mvarList(0)
    End SubPublic Property Let List(ByVal Index As Long, ByVal vData As Variant)
    If Index > UBound(mvarList) Then
    ReDim Preserve mvarList(Index)
    End If
    mvarList(Index) = vData
    End Property
    Public Property Get List(ByVal Index As Long) As Variant
    If Index > UBound(mvarList) Then
    Exit Property
    End If
    List = mvarList(Index)End Property实际上,List属性可以不只是一个下标!那么,所有下标都要放在前面,而Let中要传值的参数则要放到最后。
    那么在控件中如何去实现呢?你需要用一个变体的变量保存其属性。
    这一属性应当是不可见的私有属性。比如,vList,然后你调用vList=mvarList,属性就存了下来!
    因为还要读出来,所以前者一样要用变体。属性如何不可见?
    还是使用过程属性菜单,在其对话框中设置即可!好了,我们再谈窗体,我曾经在某网站提问,如果去掉标题栏中的最大化/还原按钮。然而,我得到的是以下答复:
    “Form.MaxButton=False 啊啊”
    回复人意思说,看你这样是可能太初级了!我想他一定是如此。否则不会有两个“啊”字。
    可是到最后实际还是没有人答出来。另一角度说,大都程序员考虑问题从没有向深处想。有更多的则是处于抄袭。当然,通常的代码都是可以抄的。实际上,编程时大多代码也是固定的的。所以首先就当会抄。但是,非常复杂的问题常需要有独创性。比如,找素数这个问题。算法与效率一定是因人而异的。因为其中的创造性太强了!
    换句话说,也只有创造性的东西才是最有价值的。我常常收到很多人要源代码的邮件!这些人有没有想想,你是程序员,还是程序工匠?我觉得,充其量只不过是一个熟练工罢了!而且不时还想抄别人的东西!就是抄,你也得看是否可抄。说白了,这些人是自己将自己的人格放低了!
    所以,编程、做人、做学问是一致的,一个人程序写得好不好,首先要看其为人。这里虽然讲的是开发控件。实际上,编任何程序都是如此。我们可以好好看看,OFFICE,这个最普及的软件,其中有多少独创?你为什么不发邮件向微软要源代码呢?
    反过来,如果你真有创造性,那你的工资自然就高了!那么,你能解决这个问题吗?
    如果你认真看懂了前面的,解决此问题我想你是有办法了:
    因为,我们可以完全去掉Form中的标题条,因为我们知道,标题条按钮是如何做出来的。由此,我们即可以按自己的要求做标题条。要去掉的按钮自然就不在了,而外观与原Form并元二样!
    现在有很多Skin控件,可是多数都没有加上标题条按钮,这也是因为,API函数太多了,另一方面也说明,没有人为此付出时间去真正解决过这类问题。