Keep track of Window being Last Focus - vb.net

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

Related

Nothing works anymore after building project in vb.net

I was going to build my project when i noticed i didn't put an icon,
and since i couldn't access the icon value of the original form because i used a theme i C+X the container and access it from the grey form, change it, C+V the container, built the project.
Nothing changed, all the name of the buttons and stuff are the same, but i feel like nothing is connected to the code anymore, i don't know what happened, i just recently got re-interested into coding, and i have no idea what to do, i tried some things but nothing worked, so here i am, desperate (i spent 3 days on this, i'm REALLY starting from bottom)
link to the project: http://www.mediafire.com/file/2zrbe32lzpx2qhz/SchedulerProjectVBNET.rar
Thanks in advance
It sounds like you have lost all the Handles clauses off your event handlers. As an example, if you add a Button to your form and double-click it, you will get a Click event handler like this:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Note the Handles clause at the end, which is what connects the code to the event of the control. If you cut that Button from your form to the Clipboard then it no longer exists as part of the form, so that Handles clause will be automatically removed. If you paste the Button back onto the form, the Handles clause is not restored, so the method no longer handles the event.
If that's what has happened - which you can easily check just by looking at the code - then you need to restore all those Handles clauses. You can do that manually, i.e. write them all yourself in the code window, or you can have the designer regenerate them for you. To do the latter, select a control in the designer, open the Properties window, click the Events button, select the desired event and then select the appropriate method from the drop-down list.
Note that you can also double-click an event there to generate a new event handler, which can be useful for handling events other than the default event. You can generate a handler for the default event simply by double-clicking the control.

vb.net using SetParent API over IsMDIContainer?

I'm working with a set of custom controls (including a custom form), I have repainted the custom form to give it a metro style look and basically recreated the title bar of the form. Setting this form to be an MDI container causes the whole form to be repainted grey regardless of anything dictated in the OnPaint handler for the form.
I want to create a multi form application where all of the forms that are not the main form, appear inside the main form (the idea of MDI windows). I have also seen a SetParent API that achieves a similar effect without modifying its visuals, however, I have used this before to tie a cmd window to a form and it is not always reliable.
Would it be more efficient to use the MDI feature inside Winforms (if so, how do i overcome the complete recolour issue) or dump MDI and use the SetParent API to modify the child windows' parent?
EDIT: I have decided to go for using the SetParent API, it works everytime as opposed to my previous experiences with the console window. However, I need to create the window before I can set the parent and sometimes the user can see the screen flash briefly before it gets 'hooked' inside my main form. Is there a way to 'hook' it without it being visible to the user?
With MDI Parent Form if your issue is the background, then this is all you have to do, Set the IsMDIContainer property of the form to true, and then loop through each control on MDI Form to let them know this is the MDI Background, you can put this code in the form loading event,
Private Sub FormMDI_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each ctl As Control In Me.Controls
If TypeOf ctl Is MdiClient Then
ctl.BackColor = Me.BackColor
End If
Next ctl
End Sub
It might appear gray when program is not running, but it will show your desired background once the program runs

Where should controller-like code be written in my vb.net app?

I am refactoring an existing project that is one large file. All form controls live in a single form, and all event handlers live in the form's code behind.
I am refactoring out a piece of the UI into a User Control. One piece of this UI is an 'Add Contract' button. This goes to my data layer, adds a row to a DataTable, and various grids in other parts of form are updated with the new row.
My question is, where should I put the event handler for the button click in the User Control?
I could leave the event handler code in the parent form, and use AddHandler in the User Control to reference the parent form's sub
I could write all the event handler code in the User Control. In this case, I'd need to access the parent form to get a reference to the data layer.
I come from a web background where I'm used to the 'controller' handling this sort of thing. I suppose my parent form is turning into a kind of controller - but is this a good practice? Should I have a separate class that coordinates user interactions with my model layer, or, once I separate out all the UI into separate user controls, will the main form be a good place for this sort of thing?
Your user control should raise events that the form hosting the user control will handle. If the user control has a reference to the form, then the user control is not reusable in any other context; in other words, the user control is tightly coupled to that one form and form X would break if it tried to use the user control.
Note: If your form is the only thing that will use the user control, then there is not much re-usability value in making it a user control at all. Kind of similar to it is not much use to make an interface if there is only one implementation of said interface. That said from an organization standpoint, user controls can be used to clean up a crowded form. It also has the benefit of allowing for the dynamic loading of content in user controls.
There is nothing wrong with your parent form becoming the controller.
Here is a quick example (in this case the clicking of the button in the user control) of how you can raise events from your user control and subscribe to the event in the form:
Public Class UserControlClass
' Define event that will be raised by user control to anyone interested in handling the event
Public Event UC_Button1Click()
' Mechanism to allow event to be raised by user control
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
RaiseEvent UC_Button1Click()
End Sub
End Class
Now in your form class, you need to add a handler for the event raised by the user control, like this:
AddHandler userControl1.UC_Button1Click, AddressOf Button1_Click
Finally, you would create the method that is referenced in the AddressOf syntax, like this:
Public Sub Button1_Click(ByVal sender As Object, ByVal args As EventArgs)
' Do something here
End Sub

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.