Subclassed Textbox OnLeave Overrides

M

Martin

Hi all,

I'm trying to make a subclass of the Textbox. One of the things I did there
is the following:

Protected Overrides Sub OnLeave(ByVal e As System.EventArgs)
If Me.DataType = 1 Or Me.DataType = 2 Then
If IsNumeric(Me.Text) Then
Me.TextAlign = HorizontalAlignment.Right
End If
End If
MyBase.OnLeave(e)
End Sub

For the sake of clarity I removed all the code that doesn't pertain to this
problem.
The offending code is the setting of the TextAlign property. This causes the
focus to go back to the instance. In other words: When I try to tab to the
next control on the form, the OnEnter event occurs again, and this control
keeps the focus. When I take the setting of the TextAlign property out, the
focus changes normally.

Any ideas on how to prevent the focus shifting back when setting this
property?

Tia,
Martin
 
C

CMM

Try overriding OnLostFocus instead. That should work.

The reason this happens is because I think the control is recreated with a
new handle when you do this... and I guess that throws a kink into "tab out"
process. Changing the textalign property *after* the control has already
lost focus should work.
 
M

Martin

Hi CMM,

Thanks for your reply. Coming from VB6 I tried the onlostfocus first. But if
I do it there, I get a Windows Exception (Could not create Handle or
something).

That is the reason why I moved the code here. Maybe I need an event that
happens a bit earlier.

Martin
 
M

Martin

By the way, I do also other stuff in the OnLeave event, such as:

If Me.DataType = 2 Then
Me.Text = Format(Val(Me.Text), "N")
End If

And for some reason that does not give me any trouble. Don't TextAlign and
Text use the same handle? Or does it have something to do with the fact that
maybe one of the events is a Textbox event, and the other a Textboxbase
event?
 
M

Martin

By the way, you were right on the money with your suspicion that it had to
do with the handle. When I change the code like this:

If Me.IsHandleCreated Then
Me.TextAlign = HorizontalAlignment.Right
End If

I don't have a problem anymore. Of course the TextAlign doesn't work anymore
either...

Martin
 
C

CMM

At what point does that exception get thrown? I don't get that error. Try
handling the LostFocus event instead of overriding OnLoadFocus. That works
here.
 
M

Martin

Hi CMM,

Followed your advice and used the lostfocus event itself. That worked!
Thanks a lot!

Being a newbie in .Net it still puzzles me somewhat... I read a few
publications on overriding events, from SYBEX and from Microsoft itself. And
they seem to contradict eachother.

What I did is this (this worked):

Private Sub Entrybox_LostFocus(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.LostFocus

If Me.DataType = 1 Or Me.DataType = 2 Then
If IsNumeric(Me.Text) Then
Me.TextAlign = HorizontalAlignment.Right
If Me.DataType = 2 Then
Me.Text = Format(Val(Me.Text), "N")
End If
End If
End If

End Sub

The thing I don't understand is the bit "Handles Me.LostFocus". According to
a Microsoft publication this shouldn't be there, because it would trigger
the LostFocus event twice.

<QUOTE>
Protected Overrides Sub Button1_Click(ByVal sender As System.Object, _
ByVal e as System.EventArgs)
Static Counter as Integer = 0
Counter += 1
MessageBox.Show (" This inherited button has been clicked " & _
Counter.ToString() & " times.")
End Sub

The Handles clause is no longer associated with the method. This is not an
oversight, but rather an important part of how events are handled in the
..NET Framework. The event handler is already associated with the event in
the base class, and this association is passed on to the inheriting class.
</QUOTE>

However when I try to do the same with the "EntryBox_LostFocus" event, I get
error messages from the IDE: "Sub 'EntryBox_LostFocus' cannot be declared
'overrides' because it does not override a sub in the base class.

A perfectly understandable message, because the baseclass may know
'LostFocus' but definitely not 'EntryBox_LostFocus'. But without the
"handles" clause how would 'EntryBox_LostFocus' get triggered? The Microsoft
example doesn't seem to make a whole lot of sense.

The Sybex book follows your recommendation, except that they use the 'Enter'
and 'Leave' events.

So, is the Microsoft example wrong? Or am I missing something?

Martin
 
C

CMM

The confusion I think lies in the difference between "Event LostFocus" and
"Sub OnLostFocus." OnLostFocus is the procedure in the base class that
eventually ends up calling RaiseEvent LostFocus... consider it an Event
Thrower. You can override this procedure and actually prevent the base class
from throwing an event simply by neglecting to call "MyBase.OnLostFocus."

Since OnLostFocus is not an "event" you don't do "Handles" on it... but
rather you override it.

More Info:
In VB.Classic, if you were creating a class that threw events, it might be
common for you to call RaiseEvent all over the place in your code (If
SomeError Then RaiseEvent MyEvent). Although you can still do this in .NET,
the "design practice" is to wrap up RaiseEvent in an overridable procedure.
Then you would raise the event by calling the procedure (If SomeError Then
OnMyEvent) rather than raising the event directly. This allows someone who
wants to inherit from your class to override the event if they wanted to.
 
M

Martin

Thanks a lot, I appreciate your help.

CMM said:
The confusion I think lies in the difference between "Event LostFocus" and
"Sub OnLostFocus." OnLostFocus is the procedure in the base class that
eventually ends up calling RaiseEvent LostFocus... consider it an Event
Thrower. You can override this procedure and actually prevent the base
class from throwing an event simply by neglecting to call
"MyBase.OnLostFocus."

Since OnLostFocus is not an "event" you don't do "Handles" on it... but
rather you override it.

More Info:
In VB.Classic, if you were creating a class that threw events, it might be
common for you to call RaiseEvent all over the place in your code (If
SomeError Then RaiseEvent MyEvent). Although you can still do this in
.NET, the "design practice" is to wrap up RaiseEvent in an overridable
procedure. Then you would raise the event by calling the procedure (If
SomeError Then OnMyEvent) rather than raising the event directly. This
allows someone who wants to inherit from your class to override the event
if they wanted to.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top