Open 2 MDI Parent after opening the main menu form - vb.net

I have 3 forms
MDI parent for TCP client
MDI parent for serial
The main menu form
I want to set the main menu form as the startupform then I want the 2 MDI parent to be loaded on the background. I don't want to show them, but I want to load them so I can trigger the on_load event of those 2 mdi parent which is to create serial/client child and connect automatically.
I've tried, but it didn't work.
Private Sub frmMenu_Load(sender As Object, e As EventArgs) Handles MyBase.Load
frmTcpMDI.show
frmSerialMDI.show
End Sub
I even tried adding a timer then starting it upon the show event of my startup form, the tick event is to open my frmTcpMDI and frmSerialMDI, still, it is not working.

Okay basically, if I understand what you want, you need a way to load your forms but not display them.
You want to run some code when the Load event occurs. However, as stated here by Microsoft :
Occurs before the control becomes visible for the first time.
Which basically screws you up...
So there is a few workaround for that.
Option 1 : You decide to run your code in the Sub New()
If you put all the code you want to run in the Sub New() of your child forms, you don't need to call Form.Show(), you just need to create the forms, and your code is running. When you actually need to display the form you call the Show() method and it's done.
Option 2 : You can't run your code in the Sub New()
If, for some reason, you can't run your piece of code in the Sub New() method, you still can do it with the load event. Just hide the form after showing it... Looks silly but will work.
First notice, still from Microsoft :
The Load event occurs when the handle for the UserControl is created. In some circumstances, this can cause the Load event to occur more than one time. For example, the Load event occurs when the UserControl is loaded, and again if the handle is recreated.
Which mean you have to be carefull to run your code only once...
Then, from your parent :
Dim myNewForm = new frmTCPMdi()
myNewForm.Show()'will call the Load event
myNewForm.Hide()'will hide the form, so it is loaded but invisible...
Honnestly, I think Option 1 looks better, but sometimes and for some reason you can't always go the easy way...

Related

Keep track of Window being Last Focus

The VB.Net program I am creating dynamically created Panels within a TableLayoutPanel and adds form elements to them. I need to keep track of what the last of these Panels to have focus was, and am hitting a bit of a brick wall.
I have tried creating an event class for when the Panel has focus:
Private Sub Self_GotFocus(ByVal sender As Object, ByVal e As EventArgs) Handles Me.GotFocus
GlobalController.Focus_Target = Me.Name
End Sub
The classes for each Panel Inherit from Windows.Forms.FlowLayoutPanel, which I why I have the call being Me.GotFocus. Additionally, the GlobalController class is just a class meant to hold global variables for the program.
Now the issue I am having, is that this event only seems to trigger when I actually am deleting the panel. When the panel is created, if I click on it, or any of it's form elements, the event never gets triggered (I debugged the program with a breakpoint).
I can't exactly figure out why this only triggers when I go to delete the panel, and not at any other time. Is there another event I should be using instead of GotFocus?
Use .Enter event in your panel since GotFocus is related only to focused control (not it's parent), mostly when UICues is set.
See MSDN GotFocus

Sharing Controls from multiple forms/classes

I'm currently stuck in how to share controls between two forms.
This is what i want to do:
- I have several forms that have their own function.
- Now i want to bring them all to gather on one mainform.
Normally i do this by creating the following code:
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim f As New Form2
GroupBox1.Controls.Add(f.Get_Groupbox_controls)
End Sub
End Class
This add all the control containing in Form2.Groupbox1 and adds it to Form1.Groupbox1.
Normally this works just fine for me.
Where "Get_Groupbox_controls" is a function that returns Form2.Groupbox1
Or if this doesn't works i display the entire form2 over form1 with a transparancykey. (this isn't a need solution, you have to do a lot of location calculating, but it works)
However now i got a form that has a lot going on. For the mainform i only want to display one Container(groupbox) but when the user clicks "More setting.." then it has to show the entire form with all the control on it.
The problem is when i use the container.controls.add() function i get an exception "Invoke or BeginInvoke cannot be called on a control until the window handle has been created "
The Error is logical because the entire form isn't made yet. But in order for the form to work properly it has to update the "hidden" UI controls (labels/buttons/etc)
So the main question is, how can i "port" a selection of controls from Form1 to form2 and keep all the handlers etc.. on Form1
If you have two forms where you want to place identical looking/functioning GroupBox sections, you may want to consider creating a custom user control that contains the shared functionality and can be placed in each form. User controls can even be added to a form through the form designer in Visual Studio.

Access event in a user control created in code behind?

I'm trying to create a user control in my code behind, and then respond to events in that control. Presumably because the control doesn't exist at compile time, Visual Studio can't compile the handler subroutine I created to catch my control's event. Importantly, I want to decide the type of control at runtime (which is why I'm not just hard-coding it).
[before going on, the controls work correctly, including events and event handlers when used in the 'normal' way of creating the controls in XAML. I want to create the control instances in code behind so I can avoid duplicating pages that are 99% identical]
This 'works' (but doesn't give me the flexibility I need):
Public WithEvents AnswerPanel As MyControls.ScrollerControl
... (and the initialisation in the New() sub):
AnswerPanel = New MyControls.ScrollerControl
ItemStack3.Children.Add(AnswerPanel)
AddHandler AnswerPanel.GuessMade, AddressOf CheckAnswer
... (this is the handler sub responding to a custom event in the ScrollerControl)
Public Sub CheckAnswer(answer As String) Handles AnswerPanel.GuessMade
With the code above everything works as I expect: the control is created at runtime and its event is handled correctly.
What I want to achieve is to be able to choose a different user control when I initialise my control (e.g. ScrollerControl2, ScrollerControl3, etc.) I can create the controls this way by changing the first line to:
Public WithEvents AnswerPanel As UserControl
But once that change is made I can no longer reference the custom event in my handler as (presumably) the compiler sees it as a generic UserControl, which doesn't include my custom GuessMade event. The compiler errors on the event name and tells me it doesn't exist.
I'm sure I'm doing something wrong here. I think it's a theory/concept issue rather than my code.
Am I on the right track or going about this in the wrong way?
If I am reading this right, you have a user control that fires an event and you want the parent page to catch that even? If so, you need to raise the event, which will cause the event to bubble to the the parent. IE:
Partial Class user_controls_myControl
Inherits System.Web.UI.UserControl
Public Event DataChange As EventHandler
End Class
This creates a control with a public event called DataChange. Now, if you look at the code in the parent page that instantiates the user control, you will see that it has an event called "OnDataChange". Just like an onCLick event, you can assign this a method in the parent page. Now, you just need to raise the event in the user control. This can be added in some event in the control, like a button click or radio button change event:
RaiseEvent DataChange(Me, New EventArgs)
This takes two objects, the sender and event arguments. Typically I pass ME, which is the user control. This is great because you can use reflection to get all the controls public properties. You can also use this to cast objects to your control type. I rarely pass event arguments but you certainly could.
I answered a similar question here: Handling events of usercontrols within listview
If this is not what you had in mind, let me know
EDIT: To add a user control dynamically and attach the event:
First, in the page that will be using the control, you will need to add a place holder:
<asp:PlaceHolder ID="placeholder1" runat="server"></asp:PlaceHolder>
as well as a reference to the user control at the head of the page (depending on how the page is setup, you may not need this. If you get a page directive error, remove it):
<%# Reference="" Control="~/user_controls/myControl.ascx"%>
In the parent page, you can then create a user control and add it to the place holder. You must declare the user control with events like this:
Private WithEvents myNewControl As New user_controls_myControl
then, in some method you can add it to the page like this:
Dim getPh As New PlaceHolder
'create an instance of the user control
newMyControl = CType(LoadControl("~/user_controls/myControl.ascx"), user_controls_myControl)
'get a handle on the place holder
getPh = me.placeHolder1
'add the user control to the place holder
getPh.Controls.Add(newMyControl)
Then, make sure you have event method:
Protected Sub myEvent(ByVal sender As Object, ByVal e As EventArgs) Handles myNewControl.DataChange
End Sub
So, if you added the RaiseEvent to the user control like I suggested earlier, this should work for you.
I have an answer to this now. As I suspected I was sort of thinking about the problem from the wrong angle.
In a nutshell I was trying to raise an event from my user controls, but I needed to be raising the events in the base class and calling that from my user controls.
So my base class (which my user controls inherit from), now contains the following:
Public Event GuessMade(answer As String)
Protected Sub RaiseGuessEvent(answer As String)
RaiseEvent GuessMade(answer)
End Sub
Then, in my user control(s), when I need to raise the event, I simply call the RaiseGuessEvent sub like this:
Me.RaiseGuessEvent(CurrentValue)
And additionally, I had to remove the event from my subclasses/user controls, of course.

VB.NET: How can you activate the childform when only the control inside is clicked?

*edit: OK, so this is my real problem, below scenario happens only when the form is MDIChild.. thanks for anyone that could provide me with the code
I have a form with labels, panels, buttons etc. Where I'm having problem is, while form2 is my active window/form and I clicked on a control inside form1, the form1 does not activate itself. What I would like to happen is for form1 to activate even when it's not the form I clicked, only the control inside it (any control)..
I'm thinking that if I clicked a control on the form, there's an event fired on the form. If I could only know of that certain event, that would help - maybe (coz I could just add Me.activate on that event if it exists). I've tried searching for series of events when a control (ex. label) is clicked but to no avail. I hope that someone could help me with this one.
Thanks in advance.
*edit
i will just try to make my question more understandable..
How can I activate the form when only the control is clicked (say, label or textbox)? My forms does not activate or focused when I click inside it except the form itself..
I can do this on one control..
Private Sub Label1_Click - Handles Label1.Click
Me.Activate()
End Sub
But what if I have 20 controls (labels, buttons, textbox, combobox, etc)? See? =)
EDIT: this answer does not apply to MDI applications.
I think what you really want to know is which one of your forms is currently the foreground window (if any). The first thing you need to understand is that a form instance lives inside a window, but the window's behavior is controlled somewhere higher up. Similar to how a form instance is identified by a variable pointing to the instance, a window can be identified by what's known as a window handle.
Knowing this, the proper way to find out whether a form is the "active" form is to:
find out the window handles of the windows containing our instances of Form1 and Form2
find out the window handle of the foreground window (which can be any window)
compare the value found in step 2 to all of the values found in step 1
Perhaps you'd then like to fire an event if the foreground window changes, but I'll leave the actual implementation up to you. There are probably several ways to perform step 1 and 2, but I can't give any solutions off the top of my head. Hopefuly I've put you back on the right track.
EDIT
Alternatively, you can use the form's Containsfocus property. If its value is True, you can safely assume that your form is the foreground window. I didn't find out about this property until after I wrote my own implementation, which I'll show you anyway:
One module containing only a windows API call
Friend Module NativeMethods
Friend Declare Function GetForegroundWindow Lib "user32.dll" () As IntPtr
End Module
Calling this method will return the window handle of the foreground window (if any).
One module containing the extension method for the Form class
Imports System.Runtime.CompilerServices
Public Module FormExtensions
<Extension>
Public Function IsForeground(f As Form) As Boolean
Return (f.Handle = NativeMethods.GetForegroundWindow)
End Function
End Module
Calling this method returns whether the specified form f has the same window handle as the foreground window.
Usage example
You could use a Timer that periodically checks whether a form is the foreground window.
Public Class Form1
Private WithEvents timer As New Timer With {.Enabled = True}
Private Sub timer_Tick(sender As Object, e As EventArgs) Handles timer.Tick
If Me.IsForeground() Then
Console.WriteLine("this instance of Form1 is the foreground window")
End If
End Sub
End Class
Like I said before, you can use Me.ContainsFocus instead of my extension method and it will work just fine.
In non-MDI forms, the form is automatically activated when you click any control inside it.

vb.net activated fires multiple times

I want to update a database based on the form that is currently activated. I had originally decided to use the GotFocus event. However I now understand that will not work as the form has controls on it. So I then thought I wouls use the activated event. This works but seems to fire multiple times. I put in the following code:
Private Sub frmNewTicket_Activated(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Activated
MsgBox("Form Activated")
End Sub
I select the form and make it activated and the message box appears about 15 times.
Why does it do this? How should I handle this. I only want my code to execute once when the form is activated.
NOTE: There are several forms that the users will be changing between, incuding forms from other applications.
Each time you click OK on the messagebox, the form regains the focus and is activated again.
Put a static Boolean value in your frmNewTicket_Activated like someone has posted here:
Static HasRan As Boolean=False
If Not HasRan Then
HasRan=True
'put code here
End If
It sounds like you are wanting to do something everytime your form gets activated. The Form Activated event will work fine as long as what you are doing doesn't pull focus from the Form which will then trigger another Activation event when the Form gets focus again. Try using something other than a MessageBox for testing like Beep or changing the Form's Color