AddinBox(Title_Logo)


Breakthrough in
        the Pseudo-Control-Array

                                                                          (Jpn. 1st Edition : 17 May 2004 )
                                                                          (Jpn. Last Edition : 11 Oct. 2016 )
                                                                          (Eng. 1st Translation: 24 Jul. 2014 )
                                                                          (Eng. Last Translation: 1 Sep. 2020 )

This document is translated from the document which I released in
Japanese in 2004 about the event handling of the Pseudo-Control-Array
of Excel-VBA.
      [ http://addinbox.sakura.ne.jp/Breakthrough_P-Ctrl_Arrays.htm  ( Jpn. )]
      [ Old Site : http://www.h3.dion.ne.jp/~sakatsu/ ]

It begins with the Basics & the Problems of Pseudo-Control-Array and
explains the Problems & the Solution in a process reaching the technique
of the event handling at the same level as VisualBasic
.

    Everybody seems to call it "Control-Array" about VBA as far as I read the
    forum of the English zone. In Japan, we often call it "Pseudo-Control-Array".
    ( It is not a function implemented as a system like VB.  In a meaning of the
    alternative technique and not to be true Control-Array, we touch "Pseudo-"
    and call it with "Pseudo-Control-Array". )


So, in a meaning to leave the limitation of VBA and to realize the event
handling at the same level as VB, the title of the document of Japanese
becomes "Breakthrough in Pseudo". The opening sentence of the Japanese
document begins in this way.
          What is Pseudo?
                It is Pseudo-Control-Array.
          Then what is Pseudo-Control-Array?
                O.K. then, let's begin with the explanation of Pseudo-Control-Array.    ....

    ---- Contents  of  Breakthrough in the Pseudo-Control-Array (Jpn.)  ----
    Chap. 1: VB(Visual Basic) vs VBA(Visual Basic for Application)
    Chap. 2: Use of the Controls collection
    Chap. 3: Use of the Collection object
    Chap. 4: What is the Class module?
    Chap. 5: Use of the Class module
    Chap. 6: Problems to remain with the Pseudo-Control-Array
    Chap. 7: Operate the objects and the properties etc. in the UserForm module
                  from the Class module
    Chap. 8: At first we take a step forward from the Pseudo-Control-Array
    Chap. 9: Problems of the Pseudo-Control-Array becoming a hindrance
    Chap. 10: Breakthrough in the Pseudo-Control-Array
    Chap. 11: Sample macro

The volume of all the Japanese documents is about 5 times of this page.
This document translated Chap. 10 and Chap. 11 into English mainly.
The flow of following conversation is the contents from Chap. 1 to Chap. 9.

Furthermore ....
the class module of VBA cannot implement Enter and Exit events, but it
is enabled by API (ConnectToConnectionPoint).


      ( Because I who am poor at English am translating into English while using translation software,  
        there may be an odd expression. The mistranslation revises it sequentially. )

---- Contents  ( History of clsBpca ) ----
1. Question about the event handling of plural controls
2. Key point of Breakthrough in the Pseudo-Control-Array (Bpca)
3. Flow of the event handling of Bpca
4. Sample (Click event of CommandButton)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5. General-purpose class module (clsBpca  Ver 4.0) and use example
    5-1. Using Exit event, if it is not a numeric, warning indication (TextBox)
          & Using Enter / Exit event, ActiveControl indication
            ( The use of the Enter / Exit event is possible since clsBpca (Ver2.0) ).
    5-2. Using Change event, highlight the color of the button (OptionButton)
    5-3. Using Change event, if it is not a numeric, warning indication (TextBox)
    5-4. Using KeyDown event, if it is not an alphanumeric character, warning indication (TextBox)
    5-5. Using Click event, Calculator
    5-6. Using MouseMove & Click event, Color palette form
    5-7. Using MouseMove & Click event, Calendar form
    5-8. Use example to the dynamic creation control
    5-9. Use example to controls on a worksheet
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6. Implementation of the event handling by API (ConnectToConnectionPoint)
        The class module of VBA cannot implement Enter and Exit events,
        but it is enabled by API ( ConnectToConnectionPoint ).

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
7. ToggleLabel-Button class ( clsBpcaTglLbl  Ver 4.1 )
      Flag type button only with good points of Toggle, Option and CheckBox.   Figure 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
8. Focus class ( clsBpcaFocus Ver 1.5 )
      The class which detects focus movement (change of ActiveControl) without using Enter/Exit event.



[ Link to here ]

----  The question about the event handling of plural controls.  ----

I will express the contents of Chap. 1 to Chap. 9 by a simple conversation.

[ Y ] : You  ( you who read this )
[ K ] : K.Tsunoda  ( it's me )

Y : How does the event handling do it in Control-Array in VBA ?
K : In the first place, the Control-Array function same as VB is not implemented in VBA.
    Therefore, the event handling such as VB is not usable in VBA, too.

Y : Is there the alternative technique for Control-Array of VB in VBA ?
K : You can operate plural controls as follows using Controls-Collection-Object.
          Me.Controls ( "TextBox" & Idx ) .Value = "1234"
    And, you can define the event of plural controls by one event procedure using a class module.
    In this case, all the processing to perform by an event will define it in a class module.
    ( Pseudo-Control-Array )

Y : Then can we not describe an event handling on UserForm module?
    Is there the alternative technique for an event handling on UserForm?

K : You can define the Custom Event by using "Event declaration" and "RaiseEvent method"
    in the Class module.
    The class module takes charge of only the detection of the event of the control. When the
    class module detects an event, the class module fires a custom event to UserForm. So you
    become able to describe an event handling in custom event procedure in UserForm.

Y : When is it that "RaiseEvent method" was implemented ?
K : It is implemented in Excel2000.  The release of Excel2000 is June, 1999.

Y : From such past ?@Because this year is 2014, 15 years ago!
    Why does everybody not use it?@Will we be usable ?

K : Yes, you are usable it from past.

Y : Then can we handle the custom event of Control-Array, if we use the class module ?
K : No, you cannot do it.

Y : Why ?@You said that we could define the custom event using the class module !
K : Yes, you can define the custom event. But you cannot do it in Array.

Y : What do you mean ?
K : There is not any problem with defining the class object as an Array.
    Of course there is not any problem with "Event declaration" and "RaiseEvent method" in
    the class module either.

Y : Though nothing has any problem, why can we not do it ?
K : It does not have any problem to fire the custom event (Class module).
    However, the side to receive of the custom event has a problem (UserForm module).

Y : What do you mean ?
K : The definition of the object variable with "WithEvents" is necessary to receive an event.

Y : Yes, I know it.
K : Because it is a story of Control-Array, does the object variable define it in Array ?

Y : Yes, it is so.
K : A definition of Array cannot describe "WithEvents" keyword.
        -- Help : WithEvents --
        You can declare as many individual variables as you like using WithEvents,
        but you can't create arrays with WithEvents.

Y : Oh my God !
K : Do you understand it ?

Y : I can't help it, I give it up.
K : Do you give it up ?
    I released the document (Breakthrough in the Pseudo-Control Array : Japanese) in 2004.
    Thereafter, the technique to realize Control-Array including an Event Handling is becoming
    popular in Japan since 2004.  ( History by Internet Archive's Wayback Machine. -- Capture -- ).
    [ History of clsBpca ]

Y : Is there it ?   What kind of technique is it ?
K : Then let's begin explanation from now on.


[ Link to here ]

---  Key point of Breakthrough in the Pseudo-Control-Array ( Bpca )  ---

In VBA (Excel2000 and later), RaiseEvent method to fire a custom event is usable.

You can receive a custom event fired by RaiseEvent method by a class object variable
with "WithEvents".

Accordingly, Control-Array seems to be able to be realized, if you define the object of the
custom event class in an array variable.

However, it is impossible.

The reason why Control-Array is impossible in VBA is not to be able to describe
"WithEvents keyword" by array declaration.
        -- Help : WithEvents --
        You can declare as many individual variables as you like using WithEvents,
        but you can't create arrays with WithEvents.



This document explains on a technique to realize Control-Array in VBA avoiding the
limit  mentioned above.



At first I will list problems becoming a hindrance.

a) In the Class firing a custom event, , the Definition of "Event statement" and the
    Practice of "RaiseEvent statement" does not have any problem at all.

b) Because "WithEvents" keyword  is not described to the Array declaration of the
    class object in UserForm receiving the custom event, a custom event is not usable.

Conversely, if a class object definition does not have the array declaration on the
UserForm side, there is no problem.

But in this situation it contradicts it because it does not become the Control-Array
if you do not declare it as an array.


The key point of "Breakthrough in the Pseudo-Control-Array" is to divide the function
of the class into Fire-Events and Make-Array.



[ Link to here ]

---  Flow of the event handling of Bpca  ---

Because I prepare for an illustration, please understand the following explanation
while watching an illustration together.  ( Illustration of clsBpca Concept )


1. Applies the Class module by 2 steps ( clsBpca and clsBpcaCh ).

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2. 1st-Step class module "clsBpca" ( Parent class, It is only one. )

  2-1. It is the class to use for a definition of the control array in UserForm.
        But the variable to declare in this class does not define it with Array.

        Because it is not array, you can describe "WithEvents" keyword.
        In other words, you can receive a custom event from the class of this variable.

  2-2. The controls to make array on UserForm enroll in the collection in the 1st-Step
        class. ("Add" method of clsBpca)

  2-3. According to the number of controls registered with the collection, you create
        the 2nd-Step class object as the Dynamic Array in the 1st-Step class.

  2-4. You assign a control in the collection to an element of this array of the class
        object one by one.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3. 2nd-Step class module "clsBpcaCh" ( Child class; It is one per one control object. )

  3-1. This class object is created as a Dynamic array in the 1st-Step class.

  3-2. In the 2nd-Step class object (individual elements of the dynamic array), one control
        is assigned to each.

  3-3. The variable that control is assigned to here is not array.
        (The 2nd-Step class object is array, but the control variable in the individual array
         element is not array.)

  3-4. Because a control variable is not array, the variable can describe "WithEvents".

  3-5. In this way, in individual elements of the array of the 2nd-Step class, you can
        receive an event of the control in UserForm.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
4. Fire Custom Event ( Flow of the event handling )

  4-1. An event of the control on UserForm fire by Macro-processing or the Operation
        of the person.

  4-2. You can receive an event of the control by a variable with "WithEvents" of the
        individual elements of the 2nd-Step class.

  4-3. For the notice of the event to the 1st-Step class, you call the method of the 1st-Step
        class from the 2nd-Step class. (In the individual elements of the 2nd-Step class, you
        keep the reference of the 1st-Step class object as the parent object.)

  4-4. You carry out "RaiseEvent" in the method of the 1st-Step class and fire the custom
        event.

  4-5. By a class obect variable (clsBpca) with "WithEvents" in UserForm, you receive the
        custom event of the 1st-Step class.


Then, with the click event of the CommandButton as an example, I will make a class
module by this technique.


[ Link to here ]

---  Sample (Click event of CommandButton)  ---

The sample macro which does "the indication of the weekday name" and "the change
of the button color" by the click of the weekday button (Sunday to Saturday).



I put off the presentation of the macro code of the class module.
At first, please watch the macro code of the UserForm module which is the use side.

===== UserForm module =========================

  Private WithEvents WeekBtn As clsBpcaCmd


  Private Sub UserForm_Initialize()
      Set WeekBtn = New clsBpcaCmd  ' Create Instance
      With WeekBtn
          .Add cmdSun    ' Register control in a class
          .Add cmdMon
          .Add cmdTue
          .Add cmdWed
          .Add cmdThu
          .Add cmdFri
          .Add cmdSat
          .Rgst          ' Create Child-class(clsBpcaCmdCh)
      End With
  End Sub


  Private Sub UserForm_Terminate()
      WeekBtn.Clear    ' Clean up and Release
      Set WeekBtn = Nothing
  End Sub


  Private Sub WeekBtn_Click(ByVal Index As Integer)
  Dim vntWeekName As Variant
  Dim i As Integer
    vntWeekName = Array("", "Sun", "Mon", "Tue", _
                            "Wed", "Thu", "Fri", "Sat")

    If (WeekBtn.Item(Index).BackColor = vbButtonFace) Then
      For i = 1 To 7
        If (i = Index) Then
          WeekBtn.Item(i).BackColor = &HCCFFFF  'Light Yellow
        Else
          WeekBtn.Item(i).BackColor = vbButtonFace
        End If
      Next i
    Else
      WeekBtn.Item(Index).BackColor = vbButtonFace
    End If

    MsgBox "[" & vntWeekName(Index) & _
            "] button is clicked (" & Index & ")"
  End Sub
 

It become the event coding at the same level as VB.
It is only the difference that Item property is sandwiched in between.
      VB :    cmdWeek(Index).BackColor
      Bpca : WeekBtn.Item(Index).BackColor


In addition, if you define the Item property as "Default Property" in a class module,
you can omit a description of "Item". Then, it is the completely same as VB.

In the general-purpose class module (clsBpca), I define the Item property as
"Default Property".

  ----  You can do it with the style that omitted "Item" (default property) as follows.  ----

    If (WeekBtn(Index).BackColor = vbButtonFace) Then
      For i = 1 To 7
        If (i = Index) Then
          WeekBtn(i).BackColor = &HCCFFFF   'Light Yellow
        Else
          WeekBtn(i).BackColor = vbButtonFace
        End If
      Next i
    Else
      WeekBtn(Index).BackColor = vbButtonFace
  End If


  ----  Method to define "Default Property"  ----

  You add the following the red-bold-faced part on the export file of the class module
  and take in a module by import again.
  ( The red-bold-faced part is invisible on the code window. )

  [ Export file  :  clsBpcaCmd.cls ]
  '---( Item property )---------------------------------------------
  Public Property Get Item(ByVal Index As Integer) As MSForms.CommandButton
  Attribute Item.VB_UserMemId = 0
  If ( blnRgst = True ) And _
      (Index > 0) And ( Index <= colCtrl.Count ) Then



Then we will watch the macro code of the class module.
Please watch while comparing it with a Illustration.

==== clsBpcaCmd module(1st-step class module) ====

  '------[ Event definition (Raise to the User-side) ]--------------
  Public Event Click (ByVal Index As Integer)

  '------[ Control-Array definition ]--------------------------
  'Child-class of clsBpcaCmd (Dynamic array)
  Private clsCtrlCh() As clsBpcaCmdCh
  'The storage of the controls on UserForm
  Private colCtrl As Collection 
  'Rgst method practice Flag : Done(True) , Not(False)
  Private blnRgst As Boolean    


  Private Sub Class_Initialize()
      Set colCtrl = New Collection     ' Create Instance
  End Sub


  Private Sub Class_Terminate()
      If (blnRgst = True) Or (Not (colCtrl Is Nothing)) Then
          Me.Clear
      End If
  End Sub


  '---( Add method )------------------------------------
  Public Sub Add(ByVal NewCtrl As MSForms.CommandButton)
      colCtrl.Add NewCtrl
  End Sub


  '---( Rgst method )------------------------------------
  Public Sub Rgst()
  Dim i As Integer
      If (blnRgst = True) Then
          'Done
      ElseIf (colCtrl.Count = 0) Then
          blnRgst = False
      Else
          ReDim clsCtrlCh(1 To colCtrl.Count)
          For i = 1 To colCtrl.Count
              ' Create Instance
              Set clsCtrlCh(i) = New clsBpcaCmdCh 
              With clsCtrlCh(i)
                  .Item = colCtrl(i)
                  .Index = i
                  .Parent = Me
              End With
          Next i
          blnRgst = True
      End If
  End Sub


  '---( Clear method )-------------------------
  Public Sub Clear()
  Dim i As Integer
      If (blnRgst = True) Then
          For i = 1 To colCtrl.Count
              clsCtrlCh(i).Clear
          Next i
      End If
      Set colCtrl = Nothing
      Erase clsCtrlCh
      blnRgst = False
  End Sub


  '---( Count property--------------------------------------
  Public Property Get Count() As Integer
      Count = colCtrl.Count
  End Property


  '---( Item property )---------------------------------------
  Public Property Get Item(ByVal Index As Integer) _
                  As MSForms.CommandButton
      If (blnRgst = True) And _
          (Index > 0) And (Index <= colCtrl.Count) Then
          Set Item = colCtrl(Index)
      Else
          Set Item = Nothing
      End If
  End Property


  '===========================================================
  '===== Method to be called from clsBpcaCmdCh =========
  '===========================================================

  Friend Sub RaiseClick(ByVal Index As Integer)
      RaiseEvent  Click(Index)
  End Sub
 

==== clsBpcaCmdCh module (2nd-step class module) ====

  Private WithEvents MyCtrl As MSForms.CommandButton
  Private MyIndex As Integer        'Index number of the control
  Private MyParent As clsBpcaCmd   'Referrence to the parent class
  Private blnParent As Boolean      '[Parent] register flag


  '---( Clear method )------------------------------------------
  Public Sub Clear()
      Set MyCtrl = Nothing
      Set MyParent = Nothing
      blnParent = False
      MyIndex = 0
  End Sub


  '---( Item property )-----------------------------------------
  Public Property Let Item(NewCtrl As MSForms.CommandButton)
      Set MyCtrl = NewCtrl
  End Property


  '---( Index property )----------------------------------------
  Public Property Let Index(NewIndex As Integer)
      MyIndex = NewIndex
  End Property


  '---( Parent property )---------------------------------------
  Public Property Let Parent(NewParent As clsBpcaCmd)
      blnParent = True
      Set MyParent = NewParent
  End Property


  '=============================================================
  '===== Receive an event of registered control ================
  '=============================================================
  'Receive an event of the control and notify the parent-class.

  Private Sub MyCtrl_Click()
      If (blnParent = True) Then
          MyParent.RaiseClick  MyIndex
      End If
  End Sub
 



This clsBpcaCmd and clsBpcaCmdCh class is a general-purpose class about the
click event of the CommandButton
.


(a) Not only Weekday-Button, you can use it for the array of other CommandButtons.

(b) On one UserFom, you can make the plural array of CommandButtons.
     You should only prepare plural class object definitions as follows.

        Private WithEvents CmdGrp1 As clsBpcaCmd
        Private WithEvents CmdGrp2 As clsBpcaCmd
                            :
                            :

(c) The number of CommandButtons which a class object can store away does not have
     the limit. The correction of the macro code of the class module cannot be necessary
     about the thing. You only merely repeat "Add method".

        With CmdGrp1
            .Add  CommandButton1
            .Add  CommandButton2
                            :
                            :

(d) About the CommandButton to create dynamically , you can handle a click event
    with this class.


However, it is inconvenient to be usable only by the Click event of CommandButton.
Because there are other controls such as TextBox, too, and there are other events
such as Change, too; ...

Therefore, I prepared General-purpose class (clsBpca  Ver 4.0) which supported
controls such as CommandButton,TextBox etc. and events such as Click,Change etc. .
In Ver2.0, a problem becomes available for Enter event etc. submitting in follows.

Please use it.



In fact, the following problem remains one more last.
      In the class module of VBA,
      we cannot define Enter, Exit, BeforeUpdate and AfterUpdate events.

These events are often used in error check and ActiveControl indication, etc.
I am disappointed at that I cannot use these events with Control-Array that
became available with much effort.

I explain why you cannot use the events of Enter etc. in a class module.

    (a) In the case of UserForm module ....
        For control placed in UserForm or control object (with WithEvents) defined
        in MsForms.TextBox etc., we can generate various event procedure from the
        list of Declarations of the module window top right corner. Naturally Enter
        event etc. are included in that, too.


    (b) In the case of Class module ....
        For control object (with WithEvents) defined in MsForms.TextBox etc., Enter
        event etc. are not included in the list of Declarations.


    (c) In the first place, the definitions of Enter,Exit,BeforeUpdate,AfterUpdate are not
        implemented in MsForms.TextBox etc. (You can confirm this by Object-Browser.)

    (d) The definitions of Enter, Exit, BeforeUpdate, AfterUpdate are implemented by
        MsForms.Control. (You can confirm this by Object-Browser, too.)

    (e) In the UserForm module, VBA links MsForms.Control to MsForms.TextBox etc..
        Because of support of VBA, we can build event procedures including Enter etc.
        for control of MsForms.Text etc. in UserForm module.

    (f) Class module does not have such a support.
        Therefore we cannot build events of Enter etc. from control of MsForms.Text etc.
        in class module.

In a class module, I will prepare an object (with WithEvents) defined in MsForms.Control.
Then I can generate a template of the event procedure of Enter from a list of Declalations.



Then, if you copy a control object from MsForms.TextBox to MsForms.Control, will
a problem be solved it?

Unfortunately then it is not solved.
    MsForms.Control from MsForms.TextBox cannot copy it.

The following copy becomes the error.
      Dim Ctrl1 As MsForms.TextBox
      Dim Ctrl2 As MsForms.Control
      Set Ctrl2 = Ctrl1      ' Error



For such a reason, Enter etc. are not available in the class module.


In addition, in General-purpose class (clsBpca Ver 2.0), a class module
is able to build events of Enter/Exit/BeforeUpdate/AfterUpdate by a
different method.


Please see below for the explanation of General-purpose class.




[ Link to here ]

General-purpose class module (clsBpca  Ver 4.0)
                              and Usage example.


    (Note)
      Because Enter / Exit events implement it by Windows-API, you cannot use Ver4.0 in Mac PC.
      In the case of Mac PC, please use Ver1.4 where Enter / Exit events are not implemented.

Event programming same as VisualBasic is enabled in VBA ,
only if you import clsBpca class module in your workbook as the Black-Box.
What you should do is ...
      At first, prepare for a variable of Control-Array (clsBpca object).
      Next, carry out "Rgst" method after repeating "Add" method.
      After that ... , describe event procedure commonly.
Only this.  ( Please check it in Sample Macro )

clsBpca supports the following controls and events, and it works in x64.
    -- Controls --
      Label , TextBox , CommandButton , OptionButton
      CheckBox , ComboBox , SpinButton , ToggleButton
          Among standard controls, ListBox/Frame/TabStrip/ MultiPage/ScrollBar is excluded
          from supported controls. It is the reason that is not placed much so that these controls
          becomes Control-Array.

    -- Events --
      Enter , Exit , BeforeUpdate , AfterUpdate
      Change , Click , DblClick , KeyDown , KeyPress , KeyUp
      MouseMove , MouseDown , MouseUp
      SpinDown , SpinUp , DropButtonClick
      FakeExit

          FakeExit event was added in Ver3.0 ( 11 Oct. 2016 ).
          (Note: Ver3.1 (updated by malfunction , 13 Oct. 2016 )
          In the case of the focus movement to get away from Frame / MultiPage, Exit event of the source
          control does not fire (it fire later). FakeExit event to become the substitute was added.
          ( See below for further details. )

          The use of the Enter / Exit / BeforeUpdate / AfterUpdate event is possible
          since clsBpca in Ver2.0 ( 11 Aug. 2014 ).

          In the class module of VBA, it cannot usually receive events of Enter , Exit , BeforeUpdate
          and AfterUpdate of the MsForms-Controls. It become able to receive the events by using API
          (ConnectToConnectionPoint).
          ( See below for further details. )


    Downloading and the help document of clsBpca are follows.

        [ clsBpca : Download & Help document ]    ( 1 Sep. 2020  Ver 4.0 release )



----- 5.  Use Examples of clsBpca -----
    5-1. Using Exit event, if it is not a numeric, warning indication (TextBox)
                & Using Enter / Exit event, ActiveControl indication
    5-2. Using Change event, highlight the color of the button (OptionButton)
    5-3. Using Change event, if it is not a numeric, warning indication (TextBox)
    5-4. Using KeyDown event, if it is not an alphanumeric character, warning indication (TextBox)
    5-5. Using Click event, Calculator
    5-6. Using MouseMove & Click event, Color palette form
    5-7. Using MouseMove & Click event, Calendar form
    5-8. Use example to the dynamic creation control
    5-9. Use example to controls on a worksheet


[ Link to here ]
1. Using Exit event, if it is not a numeric, warning indication (TextBox)
    & Using Enter / Exit event, ActiveControl indication

    The use of the Enter / Exit event is possible since clsBpca (Ver2.0).
    Enter / Exit event is defined by the name of OnEnter / OnExit in clsBpca.
    (Note) Because Enter / Exit events implement it by Windows-API, you cannot use it in Mac PC.

    About a method to implement Enter / Exit event in a class module.


  Video capture
  ( Bpca_EnterExitEvent.mp4  570KB )


  Private WithEvents NumBox As clsBpca

  Private Sub UserForm_Initialize()
      Set NumBox = New clsBpca    ' Create Instance
      With NumBox
          .Add txtNum1
          .Add txtNum2
          .Add txtNum3
          .Add txtNum4
          .Rgst  BPCA_EnterExit
      End With
  End Sub

  Private Sub UserForm_Terminate()
      NumBox.Clear
      Set NumBox = Nothing
  End Sub

  Private Sub NumBox_OnEnter(ByVal Index As Integer)
      NumBox.ItmTxt(Index).BackColor = &HFFFFE0    'LightCyan
  End Sub

  Private Sub NumBox_OnExit(ByVal Index As Integer, _
                        ByVal Cancel As MSForms.ReturnBoolean)
      If (NumBox.ItmTxt(Index).Value = "") Then
          'Empty is OK
      ElseIf IsNumeric(NumBox.ItmTxt(Index).Value) Then
          'Numeric is OK
      Else
          'Not Numeric is Error
          NumBox.ItmTxt(Index).BackColor = &HCCCCFF    'Light Red
          Beep
          Cancel = True
          Exit Sub
      End If

      NumBox.ItmTxt(Index).BackColor = vbWindowBackground
  End Sub



[ Link to here ]
2. Using Change event, highlight the color of the button (OptionButton)



  Private WithEvents OptBtn As clsBpca

  Private Sub UserForm_Initialize()
    Set OptBtn = New clsBpca    ' Create Instance
    With OptBtn
      .Add OptionButton1
      .Add OptionButton2
      .Add OptionButton3
      .Add OptionButton4
      .Add OptionButton5
      .Rgst BPCA_Change
    End With
  End Sub

  Private Sub UserForm_Terminate()
    OptBtn.Clear
    Set OptBtn = Nothing
  End Sub

  Private Sub OptBtn_Change(ByVal Index As Integer)
    With OptBtn.ItmOpt(Index)
      If (.Value = True) Then
        .BackColor = &HCCCCFF      'Light Red
      Else
        .BackColor = Me.BackColor
      End If
    End With
  End Sub

  Private Sub cmdOptReset_Click()
  Dim i As Integer
    For i = 1 To 5
      With OptBtn.ItmOpt (i)
        If (.Value = True) Then
          'I leave the change of the color to
          'the Change event mentioned above
          .Value = False
        End If
      End With
    Next i
  End Sub



[ Link to here ]
3. Using Change event, if it is not a numeric, warning indication (TextBox)



  Private WithEvents NumBox As clsBpca

  Private Sub UserForm_Initialize()
    Set NumBox = New clsBpca    ' Create Instance
    With NumBox
      .Add txtNum1
      .Add txtNum2
      .Add txtNum3
      .Rgst BPCA_Change
    End With
  End Sub

  Private Sub UserForm_Terminate()
    NumBox.Clear
    Set NumBox = Nothing
  End Sub

  Private Sub NumBox_Change(ByVal Index As Integer)
    With NumBox.ItmTxt(Index)
      If IsNumeric(.Value) Then
        .BackColor = vbWindowBackground
      Else
        .BackColor = &HCCCCFF    'Light Red
      End If
    End With
  End Sub



[ Link to here ]
4. Using KeyDown event, if it is not an alphanumeric character, warning indication (TextBox)



  Private WithEvents AlfaNumBox As clsBpca

  Private Sub UserForm_Initialize()
    Set AlfaNumBox = New clsBpca    ' Create Instance
    With AlfaNumBox
      .Add txtAN1
      .Add txtAN2
      .Add txtAN3
      .Rgst BPCA_KeyDown
    End With
  End Sub

  Private Sub UserForm_Terminate()
    AlfaNumBox.Clear
    Set AlfaNumBox = Nothing
  End Sub

  Private Sub AlfaNumBox_KeyDown _
        (ByVal Index As Integer, _
        ByVal KeyCode As MSForms.ReturnInteger, _
        ByVal Shift As Integer)
  Dim i As Integer
  Dim blnERR As Boolean
    With AlfaNumBox.ItmTxt(Index)
      Select Case KeyCode
        Case vbKeyTab, vbKeyReturn, vbKeyUp, vbKeyDown
          'Type an input end key
          blnERR = False
          For i = 1 To Len(.Value)
            Select Case Mid(.Value, i, 1)
              Case "0" To "9"
              Case "A" To "Z"
              Case "a" To "z"
              Case Else
                blnERR = True
            End Select
          Next i
          If (blnERR = False) Then
            .BackColor = vbWindowBackground
          Else
            .BackColor = &HCCCCFF    'Light Red
          End If
        Case Else
          'Inputting now
      End Select
    End With
  End Sub



[ Link to here ]
5. Using Click event, Calculator



  Private WithEvents CalcNum As clsBpca
  Private WithEvents CalcOpr As clsBpca
  Private intOperate As Integer  'Operator of Calculator

  Private Sub UserForm_Initialize()
  Dim i As Integer
    txtCalcResult.Value = ""
    txtCalcBuff.Value = ""
    intOperate = 0

    Set CalcNum = New clsBpca    'Create Instance
    With CalcNum
      For i = 1 To 9
        .Add Me.Controls("cmdCalc" & i)
      Next i
      .Add cmdCalc0      '[10]
      .Add cmdCalcSign    '[11]
      .Add cmdCalcPoint  '[12]
      .Rgst BPCA_Click
    End With

    Set CalcOpr = New clsBpca    'Create Instance
    With CalcOpr
      .Add cmdCalcClear    '[1]
      .Add cmdCalcMulti    '[2]
      .Add cmdCalcDivide  '[3]
      .Add cmdCalcPlus    '[4]
      .Add cmdCalcMinus    '[5]
      .Add cmdCalcEQ      '[6]
      .Rgst BPCA_Click
    End With
  End Sub

  Private Sub UserForm_Terminate()
    CalcNum.Clear
    CalcOpr.Clear
    Set CalcNum = Nothing
    Set CalcOpr = Nothing
  End Sub

  Private Sub CalcNum_Click(ByVal Index As Integer)
  Dim strWK As String
    If (intOperate = 6) And (Index <> 11) Then
      strWK = ""
      intOperate = 0
    Else
      strWK = txtCalcResult.Value
    End If

    Select Case Index
      Case 1 To 9
        Select Case strWK
          Case "0"
            strWK = Index    'Omit 0 of the top
          Case "-0"
            strWK = "-" & Index    'Omit 0 of the top
          Case Else
            strWK = strWK & Index
        End Select
      Case 10
        Select Case strWK
          Case "0", "-0", "-"
            'Let it ride
          Case Else
            strWK = strWK & "0"
        End Select
      Case 11  'Sign (Plus <--> Minus)
        If (Left(strWK, 1) = "-") Then
          strWK = Mid(strWK, 2)
        Else
          strWK = "-" & strWK
        End If
      Case 12  'Decimal point
        If (InStr(strWK, ".") = 0) Then
          strWK = strWK & "."
        End If
    End Select
    txtCalcResult.Value = strWK
  End Sub

  Private Sub CalcOpr_Click(ByVal Index As Integer)
  Dim i As Integer
    Select Case Index
      '[AC: All Clear]
      Case 1
        txtCalcResult.Value = ""
        txtCalcBuff.Value = ""
        intOperate = 0
        For i = 2 To 5
          CalcOpr.ItmCmd(i).BackColor = vbButtonFace
        Next i
      '[*][/][+][-]
      Case 2 To 5
        If (intOperate >= 2) And (intOperate <= 5) Then
          Call Calc_Sub
        End If
        intOperate = Index
        txtCalcBuff.Value = txtCalcResult.Value
        txtCalcResult.Value = ""
        For i = 2 To 5
          With CalcOpr.ItmCmd(i)
            If (i = Index) Then
              .BackColor = &HC0FFFF  'Light Yellow
            Else
              .BackColor = vbButtonFace
            End If
          End With
        Next i
      '[=]
      Case 6
        Call Calc_Sub
        intOperate = 6
        For i = 2 To 5
          CalcOpr.ItmCmd(i).BackColor = vbButtonFace
        Next i
    End Select
  End Sub

  Private Sub Calc_Sub()
  Dim dblNum1 As Double
  Dim dblNum2 As Double
    dblNum1 = Val(txtCalcBuff.Value)
    dblNum2 = Val(txtCalcResult.Value)
    Select Case intOperate
      Case 2
        txtCalcResult.Value = CStr(dblNum1 * dblNum2)
      Case 3
        If (dblNum2 <> 0) Then
          txtCalcResult.Value = CStr(dblNum1 / dblNum2)
        Else
          txtCalcResult.Value = "0"
        End If
      Case 4
        txtCalcResult.Value = CStr(dblNum1 + dblNum2)
      Case 5
        txtCalcResult.Value = CStr(dblNum1 - dblNum2)
    End Select
    txtCalcBuff.Value = ""
  End Sub



[ Link to here ]
6. Using MouseMove & Click event, Color palette form ( Layout before Excel2003 )



  ' Placement of the color index (Layout before Excel2003)
  ' A control name (lblPalette99) is acquired so
  ' that it is placed follows.
  '
  ' [01] [53] [52] [51] [49] [11] [55] [56]
  ' [09] [46] [12] [10] [14] [05] [47] [16]
  ' [03] [45] [43] [50] [42] [41] [13] [48]
  ' [07] [44] [06] [04] [08] [33] [54] [15]
  ' [38] [40] [36] [35] [34] [37] [39] [02]
  ' ---------------------------------------
  ' [17] [18] [19] [20] [21] [22] [23] [24]
  ' [25] [26] [27] [28] [29] [30] [31] [32]


  Private WithEvents Palette As clsBpca

  Private Sub UserForm_Initialize()
  Dim i As Integer
    lblPaletteRGB.Caption = ""
    Set Palette = New clsBpca    'Create Instance
    With Palette
      For i = 1 To 56
        .Add Me.Controls("lblPalette" & i)
      Next i
      .Add lblPaletteFrame    '(57)
      .Rgst BPCA_MouseMove + BPCA_Click
    End With
    For i = 1 To 56
      With Palette.ItmLbl(i)
        .BackColor = ThisWorkbook.Colors(i)
        .ControlTipText = _
            "(" & Format(i, "00") & ") x" & _
            Right("000000" & Hex(ThisWorkbook.Colors(i)), 6)
      End With
    Next i
  End Sub

  Private Sub UserForm_Terminate()
    Palette.Clear
    Set Palette = Nothing
  End Sub

  Private Sub Palette_Click(ByVal Index As Integer)
    If (Index <= 56) Then
      lblPaletteRGB.BackColor = Palette.ItmLbl(Index).BackColor
    End If
  End Sub

  Private Sub Palette_MouseMove _
          (ByVal Index As Integer, _
          ByVal Button As Integer, _
          ByVal Shift As Integer, _
          ByVal X As Single, ByVal Y As Single)
  Dim i As Integer
    Select Case Index
      Case 1 To 56
        'When mouse cursor overlaps with a palette,
        'only the palette makes a convex.

        For i = 1 To 56
          With Palette.ItmLbl(i)
            If (i = Index) Then
              If (.SpecialEffect = fmSpecialEffectEtched) Then
                .SpecialEffect = fmSpecialEffectRaised
              End If
            Else
              If (.SpecialEffect = fmSpecialEffectRaised) Then
                .SpecialEffect = fmSpecialEffectEtched
              End If
            End If
          End With
        Next i
      Case Else
        'If mouse cursor deviates from the palette,
        'it goes all back up in a flat.
        '[ lblPaletteFrame(57) ]

        For i = 1 To 56
          With Palette.ItmLbl(i)
            If (.SpecialEffect = fmSpecialEffectRaised) Then
              .SpecialEffect = fmSpecialEffectEtched
            End If
          End With
        Next i
    End Select
  End Sub



[ Link to here ]
7. Using MouseMove & Click event, Calendar form

  Video capture
  ( Bpca_CalendarForm.mp4 0.4MB )


  Private WithEvents CalBtn As clsBpca
  Private dtmBaseDate As Date
  Private dtmFirstDate As Date
  Private dtmLastDate As Date

  Private Sub UserForm_Initialize()
  Dim i As Integer
    Set CalBtn = New clsBpca    ' Create Instance
    With CalBtn
      For i = 1 To 37
        .Add Me.Controls("lblDay" & i)
      Next i
      .Rgst BPCA_Click + BPCA_MouseMove
    End With
    dtmFirstDate = DateSerial(Year(Date), Month(Date), 1)
    Call CalendarMake
  End Sub

  Private Sub UserForm_MouseMove( _
            ByVal Button As Integer, ByVal Shift As Integer, _
            ByVal X As Single, ByVal Y As Single)
    'All highlights are turned off by handing Zero
    Call CalMousePoint(0)
  End Sub

  Private Sub UserForm_Terminate()
    CalBtn.Clear
    Set CalBtn = Nothing
  End Sub

  Private Sub CalBtn_Click(ByVal Index As Integer)
    MsgBox "Click Date = " & _
        Format(dtmBaseDate + Index - 1, "d mmm. yyyy")
  End Sub

  Private Sub CalBtn_MouseMove( _
            ByVal Index As Integer, _
            ByVal Button As Integer, ByVal Shift As Integer, _
            ByVal X As Single, ByVal Y As Single)
    'Highlight the button of the mouse position
    Call CalMousePoint(Index)
  End Sub

  Private Sub spnMonth_SpinDown()
    dtmFirstDate = DateSerial(Year(dtmFirstDate), _
                                      Month(dtmFirstDate) - 1, 1)
    Call CalendarMake
  End Sub

  Private Sub spnMonth_SpinUp()
    dtmFirstDate = DateSerial(Year(dtmFirstDate), _
                                      Month(dtmFirstDate) + 1, 1)
    Call CalendarMake
  End Sub

  Private Sub CalendarMake()
  Dim dtmWK As Date
  Dim i As Integer
    dtmLastDate = DateSerial(Year(dtmFirstDate), _
                                    Month(dtmFirstDate) + 1, 0)
    dtmBaseDate = dtmFirstDate - Weekday(dtmFirstDate) + 1

    lblMonth.Caption = Format(dtmFirstDate, "mmm. yyyy")
    For i = 1 To 37
      dtmWK = dtmBaseDate + i - 1
      With CalBtn.ItmLbl(i)
        If (dtmWK >= dtmFirstDate) And (dtmWK <= dtmLastDate) Then
          .Caption = Day(dtmWK)
          .Visible = True
          If (dtmWK = Date) Then
            .ControlTipText = "Today"
            .Font.Underline = True
          Else
            .ControlTipText = ""
            .Font.Underline = False
          End If
        Else
          .Visible = False
        End If
      End With
    Next i
  End Sub

  '---- Highlight the button of the mouse position ----
  Private Sub CalMousePoint(ByVal Index As Integer)
  Dim i As Integer
    For i = 1 To 37
      With CalBtn.ItmLbl(i)
        If (i = Index) Then
          If (.BackColor = Me.BackColor) Then
            .BackColor = &HFFFFC0    'Thin light blue
          End If
        Else
          If (.BackColor <> Me.BackColor) Then
            .BackColor = Me.BackColor
          End If
        End If
      End With
    Next i
  End Sub


 You can make a general-purpose Calendar Tool
       from the UserForm (frmCalendarTool) mentioned above.


  Please perform import of the calendar form (frmCalendarTool)  in your
  workbook from [ Bpca_Class_V30E.zip > Export_V30E > frmCalendarTool.frm ].


  When you clicked Day-button or Close-button, frmCalendarTool closes UserForm
  in Hide unlike frmBpca3. In this way, the caller macro can receive a result (Serial
  value or -1). (see below)
  If you make the following CalendarForm function, you can perform the input of the
  date with the popup calendar.
 
 === frmCalendarTool module ===
   'Serial_Number(Date clicked) or [-1](Cancel)
   Public ReturnValue As Date
   Private WithEvents CalBtn As clsBpca
       :
       :
 
   Private Sub UserForm_QueryClose _
             (Cancel As Integer, CloseMode As Integer)
     If (CloseMode = vbFormControlMenu) Then
       Cancel = True
       ReturnValue = -1    'Cancel
       Me.Hide
     End If
   End Sub
 
   Private Sub CalBtn_Click(ByVal Index As Integer)
     ReturnValue = dtmBaseDate + Index - 1
     Me.Hide
   End Sub
 
 
 === Standard module ===
   Public Function CalendarForm() As Date
     frmCalendarTool.Show
     CalendarForm = frmCalendarTool.ReturnValue
     Unload frmCalendarTool
   End Function

 === Any UserForm ===
   Private Sub TextBox1_DblClick _
         (ByVal Cancel As MSForms.ReturnBoolean)
   Dim DateWk As Date
     DateWk = CalendarForm
     If (DateWk = -1) Then
       'Cancel
     Else
       TextBox1.Value = Format(DateWk, "yyyy/m/d")
     End If
     Cancel = True
   End Sub
 
   Private Sub TextBox2_DblClick _
         (ByVal Cancel As MSForms.ReturnBoolean)
   Dim DateWk As Date
     DateWk = CalendarForm
     If (DateWk = -1) Then
       'Cancel
     Else
       TextBox2.Value = Format(DateWk, "yyyy/m/d")
     End If
     Cancel = True
   End Sub



The macro of the calendar form becomes the Map selection form
if you change the placement of Label controls.
The figure below is Japanese map form (selection of the prefecture).
This sample is not included in the distribution file.
 
  Video capture
  ( Bpca_JapanMapForm.mp4  0.9MB )


[ Link to here ]
8. Use example to dynamic creation control    ( 3 Nov. 2016 added )

It create 2-5 lines of control sets dynamically.
(the 1st line has been made at the time of a design)
You delete the added controls and can go back up in initial state.
[ Bpca_DynamicCreate_Eng.xls ]



 'It store a Control-Name not an Object in colAddCtrl (in consideration of Remove).
 Private colAddCtrl As Collection

 Private WithEvents AddChkEnable As clsBpca
 Private WithEvents AddTxtName As clsBpca
 Private WithEvents AddTxtAddr As clsBpca
 '---------------------------------------------------------
 Private Sub Bpca_Clear()
    AddChkEnable.Clear
    AddTxtName.Clear
    AddTxtAddr.Clear

    Set AddChkEnable = Nothing
    Set AddTxtName = Nothing
    Set AddTxtAddr = Nothing
 End Sub
 '---------------------------------------------------------
 Private Sub Bpca_Registration()
 Dim vntArray As Variant
 Dim j As Integer

    Set AddChkEnable = New clsBpca
    Set AddTxtName = New clsBpca
    Set AddTxtAddr = New clsBpca

    For j = 1 To colAddCtrl.Count
        vntArray = colAddCtrl(j)
        AddChkEnable.Add Me.Controls(vntArray(1))  'chkEnable
        AddTxtName.Add Me.Controls(vntArray(2))    'txtName
        AddTxtAddr.Add Me.Controls(vntArray(3))    'txtAddr
    Next j

    AddChkEnable.Rgst BPCA_Change + BPCA_EnterExit
    AddTxtName.Rgst BPCA_Change + BPCA_EnterExit
    AddTxtAddr.Rgst BPCA_Change + BPCA_EnterExit
 End Sub
 '---------------------------------------------------------
 Private Sub DisplayListBox(ByVal Arg As String)
    With ListBox1
        .AddItem Arg
        .ListIndex = .ListCount - 1
    End With
 End Sub
 '---------------------------------------------------------
 Private Sub UserForm_Initialize()
    'For 1st lines(lblNo1 & chkEnable1 & txtName1 & txtAddr1)
    'which are prepared by a design.

    Set colAddCtrl = New Collection
    colAddCtrl.Add Array("lblNo1", "chkEnable1", "txtName1", "txtAddr1")

    Call Bpca_Registration

    txtName1.SetFocus
 End Sub
 '---------------------------------------------------------
 Private Sub UserForm_Terminate()
    Set colAddCtrl = Nothing
    Call Bpca_Clear
 End Sub
 '---------------------------------------------------------
 Private Sub cmdAddLine_Click()
 Dim ctlLbl As MSForms.Label
 Dim ctlChk As MSForms.CheckBox
 Dim ctlTxtName As MSForms.TextBox
 Dim ctlTxtAddr As MSForms.TextBox
 Dim vntArray As Variant
 Dim j As Integer

    If (colAddCtrl.Count = 5) Then  ' Max 5 line
        Beep
        Exit Sub
    End If

    j = colAddCtrl.Count + 1

    Set ctlLbl = Me.Controls.Add("Forms.Label.1")
    With ctlLbl
        .Name = "lblNo" & j
        .Top = 56 + 30 * (j - 1)
        .Left = 12
        .Height = 12
        .Width = 24
        .Caption = "( " & j & " )"
    End With

    Set ctlChk = Me.Controls.Add("Forms.CheckBox.1")
    With ctlChk
        .Name = "chkEnable" & j
        .Top = 54 + 30 * (j - 1)
        .Left = 45
        .Height = 20
        .Width = 20
        .Caption = ""
        .Value = True
    End With

    Set ctlTxtName = Me.Controls.Add("Forms.TextBox.1")
    With ctlTxtName
        .Name = "txtName" & j
        .Top = 54 + 30 * (j - 1)
        .Left = 72
        .Height = 18
        .Width = 54
        .Enabled = True
        .Value = ""
    End With

    Set ctlTxtAddr = Me.Controls.Add("Forms.TextBox.1")
    With ctlTxtAddr
        .Name = "txtAddr" & j
        .Top = 54 + 30 * (j - 1)
        .Left = 135
        .Height = 18
        .Width = 54
        .Enabled = True
        .Value = ""
    End With

    colAddCtrl.Add Array(ctlLbl.Name, ctlChk.Name, ctlTxtName.Name, ctlTxtAddr.Name)

    'Reset for created controls (chkEnableX & txtNameX & txtAddrX)
    Call Bpca_Clear
    Call Bpca_Registration

    ctlTxtName.SetFocus
 End Sub
 '---------------------------------------------------------
 Private Sub cmdEraseLine_Click()
 Dim vntArray As Variant
 Dim j As Integer

    If (colAddCtrl.Count = 1) Then
        Beep
        Exit Sub
    End If

    'In the case of deletion, please carry it out in order of
    '[Bpca_Clear > Control-Remove > Bpca_Registration].


    Call Bpca_Clear

    For j = colAddCtrl.Count To 2 Step -1
        vntArray = colAddCtrl(j)
        Me.Controls.Remove vntArray(0)      'lblNo
        Me.Controls.Remove vntArray(1)      'chkEnable
        Me.Controls.Remove vntArray(2)      'txtName
        Me.Controls.Remove vntArray(3)      'txtAddr
    Next j

    chkEnable1.Value = True
    With txtName1
        .Enabled = True
        .Value = ""
    End With
    With txtAddr1
        .Enabled = True
        .Value = ""
    End With

    Set colAddCtrl = Nothing
    Set colAddCtrl = New Collection
    colAddCtrl.Add Array("lblNo1", "chkEnable1", "txtName1", "txtAddr1")

    Call Bpca_Registration

    Call DisplayListBox("---------- Erase (2)-(5) lines ----------")
    txtName1.SetFocus
 End Sub
 '---------------------------------------------------------
 Private Sub AddChkEnable_OnEnter(ByVal Index As Integer)
    With AddChkEnable.Item(Index)
        .BackColor = &HFFFFE0    'LightCyan
        Call DisplayListBox(.Name & " : Enter Value=" & .Value)
    End With
 End Sub

 Private Sub AddChkEnable_Change(ByVal Index As Integer)
    With AddChkEnable.Item(Index)
        Call DisplayListBox(.Name & " : Change Value=" & .Value)
    End With

    'The Index number of TextBox becomes same as CheckBox of the same line.
    AddTxtName.Item(Index).Enabled = AddChkEnable.Item(Index).Value
    AddTxtAddr.Item(Index).Enabled = AddChkEnable.Item(Index).Value
 End Sub

 Private Sub AddChkEnable_OnExit(ByVal Index As Integer, _
                             ByVal Cancel As MSForms.ReturnBoolean)
    With AddChkEnable.Item(Index)
        .BackColor = vbButtonFace
        Call DisplayListBox(.Name & " : Exit Value=" & .Value)
    End With
 End Sub
 '---------------------------------------------------------
 Private Sub AddTxtName_OnEnter(ByVal Index As Integer)
    With AddTxtName.Item(Index)
        .BackColor = &HFFFFE0    'LightCyan
        Call DisplayListBox(.Name & " : Enter Value=" & .Value)
    End With
 End Sub

 Private Sub AddTxtName_Change(ByVal Index As Integer)
    With AddTxtName.Item(Index)
        Call DisplayListBox(.Name & " : Change Value=" & .Value)
    End With
 End Sub

 Private Sub AddTxtName_OnExit(ByVal Index As Integer, _
                             ByVal Cancel As MSForms.ReturnBoolean)
    With AddTxtName.Item(Index)
        .BackColor = vbWindowBackground
        Call DisplayListBox(.Name & " : Exit Value=" & .Value)
    End With
 End Sub
 '---------------------------------------------------------
 Private Sub AddTxtAddr_OnEnter(ByVal Index As Integer)
    With AddTxtAddr.Item(Index)
        .BackColor = &HFFFFE0    'LightCyan
        Call DisplayListBox(.Name & " : Enter Value=" & .Value)
    End With
 End Sub

 Private Sub AddTxtAddr_Change(ByVal Index As Integer)
    With AddTxtAddr.Item(Index)
        Call DisplayListBox(.Name & " : Change Value=" & .Value)
    End With
 End Sub

 Private Sub AddTxtAddr_OnExit(ByVal Index As Integer, _
                             ByVal Cancel As MSForms.ReturnBoolean)
    With AddTxtAddr.Item(Index)
        .BackColor = vbWindowBackground
        Call DisplayListBox(.Name & " : Exit Value=" & .Value)
    End With
 End Sub




[ Link to here ]
9. Use example to controls on a worksheet    ( 1 Sep. 2020 added )

    Video capture ( Bpca_SheetControlEvent_Eng.mp4   231KB )



 '----- clsBpca : Example of using controls on a worksheet -----

 Private WithEvents Bpca_ShCmd As clsBpca

 'Use a label control (lblFrame) instead of a frame.
 'The processing of lblFrame may be described in the Sheet1 module,
 'but in order to complete it in Thisworkbook module,
 'clsBpca is applied by lblFrame alone.

 Private WithEvents Bpca_ShLbl As clsBpca

 '-----------------------------------------------------------------
 Private Sub Workbook_Open()
     Set Bpca_ShCmd = New clsBpca    ' Create instance
     Set Bpca_ShLbl = New clsBpca

     ' [ <Worksheet name> .OLEObjects( <Control Name> ).Object ]
     With Worksheets("Main")
         Bpca_ShCmd.Add .OLEObjects("CommandButton5").Object
         Bpca_ShCmd.Add .OLEObjects("CommandButton6").Object
         Bpca_ShCmd.Add .OLEObjects("CommandButton7").Object
         Bpca_ShCmd.Add .OLEObjects("CommandButton8").Object
         Bpca_ShCmd.Rgst BPCA_Click + BPCA_MouseMove

         Bpca_ShLbl.Add .OLEObjects("lblFrame").Object
         Bpca_ShLbl.Rgst BPCA_MouseMove
     End With
 End Sub

 '-----------------------------------------------------------------
 Private Sub Workbook_BeforeClose(Cancel As Boolean)
     'Be sure to write [On Error Resume Next] in case the object variables
     '(Bpca_ShCmd, Bpca_ShLbl) have been initialized (resulting in a runtime error)
     'due to a VBA project reset.

     On Error Resume Next
     Bpca_ShCmd.Clear
     Bpca_ShLbl.Clear
     Set Bpca_ShCmd = Nothing
     Set Bpca_ShLbl = Nothing
 End Sub

 '-----------------------------------------------------------------
 Private Sub Bpca_ShCmd_Click(ByVal Index As Integer)
     MsgBox "[ clsBpca ] Example of using controls on a worksheet" & vbCrLf & vbCrLf & _
             Bpca_ShCmd.ItmCmd(Index).Caption & " was pressed.", vbInformation

     Bpca_ShCmd.ItmCmd(Index).BackColor = &H80FFFF    'Light Yellow
 End Sub

 '-----------------------------------------------------------------
 Private Sub Bpca_ShCmd_MouseMove(ByVal Index As Integer, ByVal Button As Integer, _
                     ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
 Dim i As Integer

     For i = 1 To Bpca_ShCmd.Count
         With Bpca_ShCmd.ItmCmd(i)
             If (i = Index) Then
                 If (.BackColor = &H80FFFF) Then
                     .BackColor = &HC0C0FF    'Light Red
                 End If
             Else
                 If (.BackColor <> &H80FFFF) Then
                     .BackColor = &H80FFFF    'Light Yellow
                 End If
             End If
         End With
     Next i
 End Sub

 '-----------------------------------------------------------------
 'Use label control (lblFrame) instead of frame
 'to detect mouse release from all command buttons.

 Private Sub Bpca_ShLbl_MouseMove(ByVal Index As Integer, ByVal Button As Integer, _
                     ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
 Dim i As Integer

     For i = 1 To Bpca_ShCmd.Count
         With Bpca_ShCmd.ItmCmd(i)
             If (.BackColor <> &H80FFFF) Then
                 .BackColor = &H80FFFF    'Light Yellow
             End If
         End With
     Next i
 End Sub






[ AddinBox Home (Japanese) ]  [ English Home ]  AddinBox_Banner


AddinBox ( K.Tsunoda in Japan ) CopyRight(C) 2014 Allrights Reserved.