Type Class_Virtual '虚拟控件，是直接画在窗口上的 ，所有私有属性记录，保存在主窗口中，
Protected : 
   m_IDC As Long     '控件IDC
   m_hWndParent As .hwnd  '父窗口，就是直接画在什么窗口上，
   Declare Function GetFP() As FormControlsPro_TYPE ptr '返回控件保存数据的指针（一般是类自己用）
   
Public : 
   Declare Constructor
   Declare Destructor
   Declare Property IDC() As Long             '返回/设置控件IDC，控件标识符，1个窗口里每个控件IDC都是唯一的，包括控件数组。（不可随意修改，系统自动处理）
   Declare Property IDC(NewIDC As Long)
   Declare Property hWndForm() As.hWnd         '返回/设置控件所在的窗口句柄，主要用于多开同一个窗口后，要使用控件前，必须先指定控件所在的窗口句柄，才能正常使用控件。
   Declare Property hWndForm(ByVal hWndParent As.hWnd) '获取控件所在的窗口句柄（父窗口）
   Declare Property ToolTip() As CWSTR              '返回/设置控件的一个提示，当鼠标光标悬停在控件时显示它。
   Declare Property ToolTip(ByVal sText As CWSTR)
   Declare Property ToolTipBalloon() As Boolean  '返回/设置控件是否一个气球样式显示工具提示。。{=.True.False}
   Declare Property ToolTipBalloon(bValue As Boolean)
   Declare Property Enabled() As Boolean                 '返回/设置控件是否允许操作。{=.True.False}
   Declare Property Enabled(ByVal bValue As Boolean)
   Declare Property Visible() As Boolean                 '显示或隐藏控件。{=.True.False}
   Declare Property Visible(ByVal bValue As Boolean)
   Declare Property Tag() As CWSTR                       '存储程序所需的附加数据。
   Declare Property Tag(ByVal sText As CWSTR)
   Declare Property Left() As Long                 '返回/设置相对于父窗口的 X（像素，注：虚拟控件自动感知DPI，应为100%DPI时的数值）
   Declare Property Left(ByVal nLeft As Long)
   Declare Property Top() As Long                  '返回/设置相对于父窗口的 Y（像素，注：虚拟控件自动感知DPI，应为100%DPI时的数值）
   Declare Property Top(ByVal nTop As Long)
   Declare Property Width() As Long                '返回/设置控件宽度（像素，注：虚拟控件自动感知DPI，应为100%DPI时的数值）
   Declare Property Width(ByVal nWidth As Long)
   Declare Property Height() As Long               '返回/设置控件高度（像素，注：虚拟控件自动感知DPI，应为100%DPI时的数值）
   Declare Property Height(ByVal nHeight As Long)
   Declare Function HitTest(ByRef xPos As Long, ByRef yPos As Long) As Boolean  ' 测试光标是不是在本虚拟控件上（xPos,yPos 为相对于主窗口），返回0 不在，非0 在，当控件不可见和不允许时，就返回0， 成功将修改 xPos,yPos 为相对于控件
   Declare Sub Move(ByVal nLeft As Long, ByVal nTop As Long, ByVal nWidth As Long = 0, ByVal nHeight As Long = 0) '设置窗口位置和大小，高度、宽度=0时不修改。注：虚拟控件自动感知DPI，应为100%DPI时的数值
   
End Type

'----------------------------------------------------------------------------------------------------------------------------------------------------------------
Constructor Class_Virtual
   '注意：由于窗口类是永久的，全局变量，因此这里从开软件到关软件只执行1次。
End Constructor

Destructor Class_Virtual
   '注意：由于窗口类是永久的，全局变量，因此为了可以完成特殊功能，Destructor 会重复执行
   '1，每次窗口销毁  就执行1次 Destructor  ，多次显示和关窗口就重复操作
   '2，退出软件  执行1次 Destructor 
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      If IsWindow(fp->ToolWnd) Then DestroyWindow fp->ToolWnd
   End If       
End Destructor
Function Class_Virtual.GetFP() As FormControlsPro_TYPE ptr '返回自己控件的指针
   Dim fp As FormControlsPro_TYPE ptr = GetPropW(m_hWndParent, "FCP_TYPE_PTR")
   While fp
      if fp->IDC = m_IDC Then Return fp      
      fp = fp->VrControls
   Wend

End Function
Function Class_Virtual.HitTest(ByRef xPos As Long, ByRef yPos As Long) As Boolean  '测试光标是不是在本虚拟控件上
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      if (fp->Style and &H1)=0 then Return 0  '当控件不可见和不允许时，就返回0
      if (fp->Style and &H2)=0 then Return 0
      Dim As Long x=AfxScaleX(fp->nLeft),y=AfxScaleY (fp->nTop),w=AfxScaleX(fp->nWidth),h=AfxScaleY(fp->nHeight)
      if xPos >= x AndAlso xPos <= x + w AndAlso yPos >= y AndAlso yPos <= y + h Then 
         xPos -= x
         yPos -= y 
         Return TRUE
      End If
   end if
End Function
Property Class_Virtual.hWndForm() As .hWnd         '返回/设置控件所在的窗口句柄
      Return m_hWndParent
End Property
Property Class_Virtual.hWndForm(ByVal hWndParent As .hWnd)
   m_hWndParent = hWndParent
End Property
Property Class_Virtual.IDC() As Long    '返回/设置控件IDC，控件标识符，
      Return m_IDC
End Property
Property Class_Virtual.IDC(NewIDC As Long)
   m_IDC = NewIDC
End Property
Property Class_Virtual.ToolTip() As CWSTR
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      Return fp->ToolTip 
   End If
End Property
Property Class_Virtual.ToolTip(ByVal sText As CWSTR)
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      fp->ToolTip = sText
      If IsWindow(fp->ToolWnd) Then DestroyWindow fp->ToolWnd
      if Len( **fp->ToolTip) then
         fp->ToolWnd = FF_AddTooltip(m_hWndParent, fp->ToolTip, fp->ToolTipBalloon,fp->nLeft ,fp->nTop ,fp->nWidth ,fp->nHeight )
      End If
   End If
End Property
Property Class_Virtual.ToolTipBalloon() As Boolean  '返回/设置控件是否一个气球样式显示工具提示。。{=.True.False}
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then   
      Return fp->ToolTipBalloon  
   End If
End Property
Property Class_Virtual.ToolTipBalloon(bValue As Boolean)  
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      fp->ToolTipBalloon = bValue
      If fp->ToolWnd Then DestroyWindow fp->ToolWnd
      if Len( **fp->ToolTip ) then 
        fp->ToolWnd = FF_AddTooltip(m_hWndParent, fp->ToolTip, fp->ToolTipBalloon,fp->nLeft ,fp->nTop ,fp->nWidth ,fp->nHeight )
      End If
   end if
End Property
Property Class_Virtual.Enabled() As Boolean
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then  ' 虚拟控件通用样式 样式结构：&H01020304  04 选项 &H1=允许 &H2=显示
      Return (fp->Style and &H1 )<>0
   End If
End Property
Property Class_Virtual.Enabled(ByVal bValue As Boolean)
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      If bValue Then fp->Style Or= &H1 Else fp->Style And= Not &H1 
      AfxRedrawWindow m_hWndParent
   End If
End Property
Property Class_Virtual.Visible() As Boolean
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      Return (fp->Style and &H2 )<>0 
   End If
End Property
Property Class_Virtual.Visible(ByVal bValue As Boolean)
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      If bValue Then fp->Style Or= &H2 Else fp->Style And= Not &H2
      AfxRedrawWindow m_hWndParent
   End If
End Property
Property Class_Virtual.Tag() As CWSTR 
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      Return fp->Tag
   End If
End Property
Property Class_Virtual.Tag(ByVal sText As CWSTR )
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      fp->Tag = sText
   End If
End Property
Property Class_Virtual.Left() As Long    
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      Return fp->nLeft
   End If
End Property
Property Class_Virtual.Left(ByVal nLeft As Long)
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      fp->nLeft = nLeft
      AfxRedrawWindow m_hWndParent
   End If
End Property
Property Class_Virtual.Top() As Long    
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      Return fp->nTop
   End If
End Property
Property Class_Virtual.Top(ByVal nTop As Long)
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      fp->nTop = nTop
      AfxRedrawWindow m_hWndParent
   End If
End Property
Property Class_Virtual.Width() As Long    
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      Return fp->nWidth
   End If
End Property
Property Class_Virtual.Width(ByVal nWidth As Long)
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      fp->nWidth = nWidth
      AfxRedrawWindow m_hWndParent
   End If
End Property
Property Class_Virtual.Height() As Long    
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      Return fp->nHeight
   End If
End Property
Property Class_Virtual.Height(ByVal nHeight As Long)
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      fp->nHeight = nHeight
     AfxRedrawWindow m_hWndParent
   End If
End Property
Sub Class_Virtual.Move(ByVal nLeft As Long, ByVal nTop As Long, ByVal nWidth As Long = 0, ByVal nHeight As Long = 0)
   Dim fp As FormControlsPro_TYPE ptr = GetFP()
   if fp then
      fp->nTop = nTop
      fp->nLeft = nLeft
      if nWidth <> 0 then fp->nWidth = nWidth
      if nHeight <> 0 then fp->nHeight = nHeight
      AfxRedrawWindow m_hWndParent
   End If
End Sub
