VS 2008 [RESOLVED] Windowless User Control-VBForums
Results 1 to 11 of 11

Thread: [RESOLVED] Windowless User Control

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Resolved [RESOLVED] Windowless User Control

    Hello all

    Doing a step back from c++ for a cool desktop app that will take over my current program browser app.

    I have a question regarding user controls.
    I have made a custom "key manager" class, which has global keydown, keyup, keypress events. It uses a thread in combination with a windows API to handle global key changes. This is the structure:
    Code:
    Public Class KeyManager
        Public Event KeyDown(ByRef s As KeyManager, ByVal key As Windows.Forms.Keys)
        Public Event KeyUp(ByRef s As KeyManager, ByVal key As Windows.Forms.Keys)
        Public Event KeyPress(ByRef s As KeyManager, ByVal key As Windows.Forms.Keys)
        Public ReadOnly Property GetKeyDown(ByVal key As Windows.Forms.Keys) As Boolean
        Public ReadOnly Property Control() As Boolean
        Public ReadOnly Property Shift() As Boolean
        Private c As Control
        Private sd As Integer = 0
        Private t As Threading.Thread
        Public Sub New(ByRef owner As Control, ByVal Checkdelay As Integer)
        Public Sub Dispose()
        Private Declare Function GetAsyncKeyState Lib "user32" (ByVal Key As Windows.Forms.Keys) As Boolean
        Private states(255) As Boolean
        Private special(2) As Boolean
        Private lastkeydown As Integer = -2
        Private Sub CheckLoop()
        Private Sub HandleKey(ByVal key As Windows.Forms.Keys)
        Private Delegate Sub dinvoke(ByVal type As KeyEvent, ByVal k As Windows.Forms.Keys)
        Private Sub invoke(ByVal type As KeyEvent, ByVal k As Windows.Forms.Keys)
        Private Enum KeyEvent
    End Class
    In the new sub the values are applied to c and sd and the thread (t) is started. Inside the checkloop it checks all 0 - 255 key chars and the 3 special key chars (alt, shift, control). These values are applied to the states(255) and special(2) arrays. if the value differs, it raises an event. This event is handled by a delegated sub so you won't get thread access errors in the receiving end.
    I can add the class as variable in my class, but I want to make it just like the timer, Errorprovider, Backgroundworker etc. standard windows usercontrols. In short, I want to have an user control that shows up in the bottom of the screen and which has no window.

    I guess I would have to inherit something, but it all causes crashes till now, as soon I drag/dropped the control into the field. (designer error)

    So, how can I make such an user control that has no window, just some events and properties?
    Last edited by bergerkiller; Jan 15th, 2011 at 03:22 PM.

  2. #2
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    96,578

    Re: Windowless User Control

    Those aren't "user controls". A user control is a class that inherits UserControl, which is specifically designed to be a container for multiple child controls, thereby allowing you design a control likea form, but use it like any other control.

    What you're talking about is a component. Strictly speaking, a component is any class that implements the System.ComponentModel.IComponent interface. You'd rarely do that directly though. In almost all cases, you would inherit the System.ComponentModel.Component class, which provides a basic concrete implementation the aforementioned interface. That's what the classes you mentioned do. Simply add the appropriate "Inherits" line to your class and it will become a component. As such, it can be designed and it can be added to another component in the designer.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    MSDN "How Do I?" Videos: VB | C#
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Windowless User Control

    Mmh I get the same error as when I implemented timer:
    Failed to create component 'keyclass'.
    Constructor on type 'Mini_Desktop.keyclass' not found.
    From c++ experience I would understand I would have to add a contructor/initialization to my class. Problem is that it is already there; the sub new.

    What do I have to add for constructor? (I'd expect I would also have to add a destructor)

    Thanks for your help.

    EDIT

    Never mind, my mistake. Forgot to remove the constructor arguments. Problem is that it had the control to use in as argument (invoking), how can I get the "parent" control of this component? The container class only gives me a set of child controls...and a null reference exception when I ask for the first control.

    How can I get the control/form this component is in?...preferably without setting a property since it would only make things more complicated for the end user.
    Last edited by bergerkiller; Jan 15th, 2011 at 04:41 PM.

  4. #4
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    96,578

    Re: Windowless User Control

    You need to provide a parameterless constructor. Obviously the designer can't pass those parameter values when creating an instance because it doesn't know what they are.

    I think you should do a bit of reading on components, because the fact that you are currently passing a parent control into the constructor indicates that you need to do a bit of redesign. Also, I think you misunderstand exactly what ByRef is for. You should ONLY be declaring parameters ByRef if:

    1. You are assigning a new value to the parameter itself inside the method and you want that change to affect the original variable.
    2. The parameter is a value type, you are setting a property of that parameter inside the method and you want that change to affect the original variable.

    You should never, EVER have a ByRef parameter in a constructor.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    MSDN "How Do I?" Videos: VB | C#
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  5. #5

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Windowless User Control

    Yeah I did some reading a;ready, and it seems I need to override the componentmodel.site property. I translated this from c#:
    Code:
    Imports System.ComponentModel
    
    '<<some more code here>>
    
        Public Overrides Property Site() As ISite
            Get
                Return MyBase.Site
            End Get
            Set(ByVal value As ISite)
                MyBase.Site = value
                If IsNothing(value) Then Return
                Dim host As Design.IDesignerHost = value.GetService(GetType(Design.IDesignerHost))
                If Not IsNothing(host) Then
                    Dim component As IComponent = host.RootComponent
                    If (TypeOf (component) Is ContainerControl) Then
                        c = CType(component, ContainerControl)
                    End If
                End If
            End Set
        End Property
    Problem is it doesn't return any control in the end (I changed the c value type to containercontrol). Any ideas?

    About the byref; I always thought classes were always send by reference. Till now when I send a class by value to a sub and change something of this value, the object passed into it changes. Ow well, wasn't intended to modify the value anyways. Just wanted to "speed up" the system.

  6. #6
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    96,578

    Re: Windowless User Control

    Exactly: classes are reference types so you are always passing a reference. When you pass a parameter by value you are making a copy of the contents of the original variable. If the original variable is a reference type then its contents is a reference. That means that passing a reference type by value passes a reference, while passing a reference type by reference passes a reference to a reference.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    MSDN "How Do I?" Videos: VB | C#
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  7. #7

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: Windowless User Control

    while passing a reference type by reference passes a reference to a reference.
    Hehe funny sentence, but I think I understand. It's like making a shortcut on your computer linking to another shortcut; pointless and as always the OS automatically changes it to the target of the first shortcut; like changing byref to byval. Thanks for the insight

    And I get the feeling the only way of getting the parent is by property or by using this ISite...which is doomed to fail. I'll just stick with the regular class.

    Thanks for your help

  8. #8
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    96,578

    Re: [RESOLVED] Windowless User Control

    No, not pointless. It has a very important point.

    If you pass a reference type ByVal then you are passing a copy of a reference. If you assign a new object to the parameter inside the method, the copy now refers to the new object but the original still refers to the original object.

    If you pass a a reference ByRef then you are passing a reference to a reference. If you assign a new object to the parameter inside the method, the copy and the original now refer to the new object.

    That's why I said:
    You should ONLY be declaring parameters ByRef if:

    1. You are assigning a new value to the parameter itself inside the method and you want that change to affect the original variable.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    MSDN "How Do I?" Videos: VB | C#
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  9. #9

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: [RESOLVED] Windowless User Control

    Ah you mean like this?
    Code:
    Public Sub ChangeClass(ByRef c as ACLASS)
         Dim d as ACLASS = c
         d.member = 2
         c = d
         'd is disposed
    End Sub
    After passing the class of type ACLASS with member value 10 the member value changes to 2 (or is even disposed), because both objects point to the same element on the stack?

    While the following sub using ByVal would not affect the sent class:
    Code:
    Public Sub ChangeClass(ByVal c as ACLASS)
         Dim d as ACLASS = c
         d.member = 2
         c = d
         'd is disposed
    End Sub
    Or am I still on the wrong track here? :P
    Last edited by bergerkiller; Jan 15th, 2011 at 07:21 PM.

  10. #10
    .NUT jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    96,578

    Re: [RESOLVED] Windowless User Control

    No not like that. In that code, 'c' is the parameter. Where are you assigning a new object to 'c' in that code? I'm not talking about setting a property of the object, as you can tell from point 2 in post #4, which does specifically relate to setting a property.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    MSDN "How Do I?" Videos: VB | C#
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  11. #11

    Thread Starter
    Fanatic Member
    Join Date
    Jul 2009
    Posts
    629

    Re: [RESOLVED] Windowless User Control

    Hehe saw that already, was too late with editing.
    Still can't really see what could possible happen in a constructor with a referenced class...it passes the class just fine. And of course, you only send something by reference if you want to change the value of it at some point in the routine. At what point after you did this ByRef does it go wrong with classes?
    - When you change a property in the referenced class
    - When you assign a new class to the referenced class
    - When you make a new class and you assign it to (make it equal to) the referenced class
    ...- When you set a property of the new cloned class
    - When you try to get a property from the referenced class
    - Something with the scope of the referenced class?

    Never had any problems with this, so am still interested in what *could* go wrong.

    EDIT

    Ow wait, actually I start to understand it a little.
    ByVal:
    You change the passed class directly, the class that was sent in (original) stays what it is. You change a class member, and it changes on the original also.
    ByRef:
    You change the passed class directly, the class that was sent in (original) changes to the new one. In case you used the parameter as if it was a "temporary object", the original gets messed up. You change a class member, and it changes on the original also.

    So the only difference with them is when you set the referenced class directly, which rarely happens.

    Conclusion: ByVal class has referenced members; ByRef class is itself referenced?
    Last edited by bergerkiller; Jan 15th, 2011 at 07:50 PM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.