Generate dialog result from a custom message box class - vb.net

I am developing a custom messagebox class like the following-
Public Class MyCustomMsgBox
Private MyForm As Form = New Form
Private lblHeadline As Label = New Label
Private lblMessageBody As Label = New Label
Private btnNo As Button = New Button
Private btnOk As Button = New Button
Private btnYes As Button = New Button
Public Sub New(ByVal Message As String)
With MyForm
.Width = 438
.Height = 214
.Controls.AddRange(New Control() {lblHeadline, lblMessageBody, btnNo, btnYes, btnOk})
End With
End Sub
Public Shared Function ShowErrorMsg(ByVal ErrorMessage As String) As Windows.Forms.DialogResult
Dim obj As MyCustomMsgBox = New MyCustomMsgBox(ErrorMessage)
obj.MyForm.ShowDialog()
End Sub
Public Shared function ShowSuccessMsg(ByVal SuccessMessage As String) As Windows.Forms.DialogResult
'some code
End Sub
Public Shared Function AskQuestions(ByVal Questions As String) As Windows.Forms.DialogResult
'some code
End Sub
Public Shared Function ShowExceptions(ByVal ExMessage As String) As Windows.Forms.DialogResult
'some code
End Sub
'Private Sub btnNo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNo.Click
' Windows.Forms.DialogResult.No()
'End Sub
End Class
Those functions are designed with related graphics, color, title and heading.
btnOk will return DialogResult.Ok, btnNo will return DialogResult.No and btnYes will return DialogResult.Yes
How do i return the dialog result with those functions?
How do i know that which button is pressed?
i dont know how to handle a button click event in a formless class.
Would you give me the idea?
Thank you in advance.
SKPaul

Start with the easy one. You will have to manually wire-up the events by using the AddHandler and RemoveHandler keywords this
AddHandler btnNo.Click, AddressOf btnNo_Click
btnNo is the button object. The ".Click" is the event you want captured. The AddressOf gets a pointer to the function (basically, it tells the compiler where the function is. Think of it as a different type of "handles".)
You'll have to remvoe the handler when your done, by doing this.
RemoveHandler btnNo.Click, AddressOf btnNo_Click
To set the Dialog Results, the form must be called via ShowDialog. You Simple set the DialogResults property of the form. I'd do it in the form.closing event.
me.DialogResult = Windows.Forms.DialogResult.OK

Me.DialogResult = Windows.Forms.DialogResult.Abort
Me.Close()
and it will return result Abort

Related

How to raise click event of a panel by clicking on its controls in Vb.net

I've a custom TableLayoutPanel:
Public Class CustomTLP
Inherits TableLayoutPanel
Private labelText As Label = New Label()
Public Sub New([variousParam])
[...]
labelText.Text = "Hello Dolly!"
Me.Controls.Add(labelText, 0, 0)
End Sub
End Class
And, in another class, I create a new CustomTLP and its mouse click handler
Dim w As CustomTLP = New CustomTLP (Me, dName)
aFlowLayout.Controls.Add(w)
AddHandler w.MouseClick, AddressOf Me.ABeautifulOperation
The problem is that when i click on the CustomTLP label, the handler doesn't detect the event.
The only solution that came to my mind is to set ABeautifulOperation as public and call it from a label-click handler, but I don't think is an elegant solution... Is there a way to raise the clickevent of the panel? Something like this ( in CustomTLP):
AddHandler labelText.Click, AddressOf labelClicked
[...]
Private Sub labelClicked(sender As Object, e As EventArgs)
' Raise Me.MouseClick
End Sub
As suggested by GSerg, just call the base OnClick() method when your Label is clicked:
Private Sub labelClicked(sender As Object, e As EventArgs)
Me.OnClick(e)
End Sub
Here's a VB version of the Custom Label that will ignore mouse events, thus allowing the parent control to handle them:
Public Class CustomLabel
Inherits Label
Protected Overrides Sub WndProc(ByRef m As Message)
Const WM_NCHITTEST As Integer = &H84
Const HTTRANSPARENT As Integer = (-1)
If m.Msg = WM_NCHITTEST Then
m.Result = New IntPtr(HTTRANSPARENT)
Else
MyBase.WndProc(m)
End If
End Sub
End Class

Accessing label on Passed Form

I'm trying to add an activity logger into my application. I'm hoping to keep my code clean and so only want to state the current activity once in my code and then it displays it in lblStatus and updates the log file. I'm trying to do this like this:
I'm passing it like this on my normal form:
LogActivity.LogActivity(Me, "Checking program directories...")
And this is the sub that's doing the work.
Public Sub LogActivity(FormID As Form, ByVal ActivityDescription As String)
'Log Activity code is here
'Update Status Label on form
FormID.lblStatus = ActivityDescription
end sub
But Visual Studio doesn't understand the syntax, I can understand why but I'm not sure how to do this correctly.
'lblStatus' is not a member of 'Form'
However, all my forms will call this sub, so I really need my code to understand which form called the sub and to update the lbl on that form specifically.
I could just check the form's name like this:
If Form.Name = "Main_Loader" Then
Main_Loader.lblStatus = ActivityDescription
elseif Form.Name = "..." then
end if
But again that's not very clean and doesn't seem like the proper way... Could anyone advise?
Assuming the Label is called "lblStatus" on ALL of the Forms, you could simply use Controls.Find() like this:
Public Sub LogActivity(FormID As Form, ByVal ActivityDescription As String)
Dim matches() As Control = FormID.Controls.Find("lblStatus", True)
If matches.Length > 0 AndAlso TypeOf matches(0) Is Label Then
Dim lbl As Label = DirectCast(matches(0), Label)
lbl.Text = ActivityDescription
End If
End Sub
You could use a custom event. The form that needs the info reported back subscribes to the event that is on the form that has the LogActivity.
Public Class frmActivity 'name of class is an example
Private log As New LogClass
Public Event LogActivity(ActivityDescription As String, log As LogClass)
'somewhere in code raise this event and send to info to main form
Private Sub SomeEventSub()
RaiseEvent LogActivity("some status", log)
End Sub
'...
End Class
Public Class frmMain 'name of class is an example
Private Sub btnGetActivity() Handles btnGetActivity.Click
Dim frm As New frmActivity
Addhandler frm.LogActivity, AddressOf LogActivity
frm.Show()
End SUb
Private Sub LogActivity(ActivityDescription As String, log As LogClass)
lblStatus = ActivityDescription
'then use the log variable to store the log data
End Sub
'...
End Class

How to get values from a dialog form in VB.NET?

I have a "frmOptions" form with a textbox named "txtMyTextValue" and a button named "btnSave" to save and close the form when it's clicked,
then, I'm showing this dialog form "frmOptions" when a button "btnOptions" is clicked on the main form "frmMain", like this
Private Sub btnOptions_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOptions.Click
ShowOptionsForm()
End Sub
Private Sub ShowOptionsForm()
Dim options = New frmOptions
options.ShowDialog()
End Sub
How can I get in the main form "frmMain" the value inserted in the textbox "txtMyTextValue" when the "btnSave" is clicked?
You want to capture the information from the dialog only if the result is OK (user presses Save instead of Cancel or closes the dialog some other way), so do this:
Private Sub ShowOptionsForm()
Dim options = New frmOptions
' Did the user click Save?
If options.ShowDialog() = Windows.Forms.DialogResult.OK Then
' Yes, so grab the values you want from the dialog here
Dim textBoxValue As String = options.txtMyTextValue.Text
End If
End Sub
Now inside of your dialog form, you need to set the result Windows.Forms.DialogResult.OK when the user clicks the button that corresponds to the OK action of the dialog form, like this:
Public Class frmOptions
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
' Set the result to pass back to the form that called this dialog
Me.DialogResult = Windows.Forms.DialogResult.OK
End Sub
End Class
The simplest method is to add a public property to the frmOptions form that returns an internal string declared at the global level of the frmOptions
Dim strValue As String
Public Property MyStringValue() As String
Get
Return strValue
End Get
End Property
Then, when your user clicks the OK button to confirm its choices you copy the value of the textbox to the internal variable
Private Sub cmdOK_Click(sender As Object, e As System.EventArgs) Handles cmdOK.Click
strValue = txtMyTextValue.Text
End Sub
Finally in the frmMain you use code like this to retrieve the inserted value
Private Sub ShowOptionsForm()
Using options = New frmOptions()
if DialogResult.OK = options.ShowDialog() Then
Dim value = options.MyStringValue
End If
End Using
End Sub
I prefer to avoid direct access to the internal controls of the frmOptions, a property offer a indirection that could be used to better validate the inputs given by your user.
You can use Events to take care of this. With this approach the Settings Form does not have to be Modal and the user can click the Save Button at any time.
In frmOptions:
'You can expand the signature to take more than just a single String.
Friend Event SavedOptions(ByVal strData As String)
Private Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSave.Click
RaiseEvent SavedOptions(txtMyTextValue.Text)
End Sub
In frmMain:
Private Sub ShowOptionsForm()
Dim options = New frmOptions
AddHandler options.SavedOptions, AddressOf OnOptionsSave
options.ShowDialog()
End Sub
Private Sub OnOptionsSave(ByVal strData As String)
'Or whatever you want to do on frmMain with Options Data.
MsgBox(strData)
End Sub
You can access the value from the frmOptions instance. However, this breaks the law of demeter.
You should expose the value with a property within your class.
Public Class frmOptions
Public ReadOnly Property MyTextValue As String
Get
Return Me.txtMyTextValue.Text
End Get
End Property
End Class
Then you can access the value:
Private Sub ShowOptionsForm()
Dim options = New frmOptions
Dim frmOptionTextValue As String
Dim frmOptionsDiagResult As DialogResult
frmOptionsDiagResult = options.ShowDialog()
If frmOptionsDiagResult = Windows.Forms.DialogResult.OK Then
frmOptionTextValue = options.MyTextValue
Else
'...
End If
End Sub
Finally, if you are using a Dialog then make sure to set the Dialog Result for the button.

vb.net how do I make an application that only has a notifyicon and no windows form?

I want to make an application that only has a notifyicon and doesn't have any visible window form when it starts up. I see some example sort of like what I want to do for c#, but I don't see how to do this in vb.net project.
A form is not strictly necessary. You can instantiate a NotifyIcon and use that without creating a form:
Public Class AppContext
Inherits ApplicationContext
Private notifyIcon As NotifyIcon
Private appActive As Boolean
Public Sub New()
AddHandler Application.ApplicationExit, AddressOf OnApplicationExit
notifyIcon = New NotifyIcon()
notifyIcon.Icon = My.Resources.ActiveIcon
notifyIcon.Text = "The app is active."
AddHandler notifyIcon.MouseClick, AddressOf OnIconMouseClick
appActive = True
notifyIcon.Visible = True
End Sub
Private Sub OnApplicationExit(ByVal sender As Object, ByVal e As EventArgs)
If notifyIcon IsNot Nothing Then
notifyIcon.Dispose()
End If
End Sub
Private Sub OnIconMouseClick(ByVal sender As Object, ByVal e As MouseEventArgs)
If e.Button = MouseButtons.Left Then
appActive = Not appActive
notifyIcon.Icon = If(appActive, My.Resources.ActiveIcon, My.Resources.InactiveIcon)
notifyIcon.Text = If(appActive, "The app is active.", "The app is not active.")
Else
If MsgBox("Do you want to Exit?", MsgBoxStyle.YesNo) = MsgBoxResult.Yes Then
notifyIcon.Visible = False
ExitThread()
End If
End If
End Sub
End Class
And then start your app from a Sub Main:
Public Module EntryPoint
Public Sub Main()
Dim ctx As New AppContext()
Application.Run(ctx)
End Sub
End Module
Just put the form transparent and resize it to 1x1..
And add a notifyicon..
And on the Form Load Event do this:
NotifyIcon.Visible = True
Then make what ever you want..
You can create a context menu strip (A Menu when you right click on it )
PS: If you do it, You need to go on the NotifyIcon properties and set the Context Menu Strip to that you created..
Hope it helped you..

How do I get events to execute on the "main thread"

I have 2 classes, one is frmMain a windows form and the other is a class in vb.NET 2003.
frmMain contains a start button which executes the monitor function in the other class. My question is, I am manually adding the event handlers -- when the events are executed how do I get them to excute on the "main thread". Because when the tooltip balloon pops up at the tray icon it displays a second tray icon instead of popping up at the existing tray icon. I can confirm that this is because the events are firing on new threads because if I try to display a balloon tooltip from frmMain it will display on the existing tray icon.
Here is a part of the second class (not the entire thing):
Friend Class monitorFolders
Private _watchFolder As System.IO.FileSystemWatcher = New System.IO.FileSystemWatcher
Private _eType As evtType
Private Enum evtType
changed
created
deleted
renamed
End Enum
Friend Sub monitor(ByVal path As String)
_watchFolder.Path = path
'Add a list of Filter to specify
_watchFolder.NotifyFilter = IO.NotifyFilters.DirectoryName
_watchFolder.NotifyFilter = _watchFolder.NotifyFilter Or IO.NotifyFilters.FileName
_watchFolder.NotifyFilter = _watchFolder.NotifyFilter Or IO.NotifyFilters.Attributes
'Add event handlers for each type of event that can occur
AddHandler _watchFolder.Changed, AddressOf change
AddHandler _watchFolder.Created, AddressOf change
AddHandler _watchFolder.Deleted, AddressOf change
AddHandler _watchFolder.Renamed, AddressOf Rename
'Start watching for events
_watchFolder.EnableRaisingEvents = True
End Sub
Private Sub change(ByVal source As Object, ByVal e As System.IO.FileSystemEventArgs)
If e.ChangeType = IO.WatcherChangeTypes.Changed Then
_eType = evtType.changed
notification()
End If
If e.ChangeType = IO.WatcherChangeTypes.Created Then
_eType = evtType.created
notification()
End If
If e.ChangeType = IO.WatcherChangeTypes.Deleted Then
_eType = evtType.deleted
notification()
End If
End Sub
Private Sub notification()
_mainForm.NotifyIcon1.ShowBalloonTip(500, "Folder Monitor", "A file has been " + [Enum].GetName(GetType(evtType), _eType), ToolTipIcon.Info)
End Sub
End Class
You need to use Control.Invoke, this will not run the delegate (event) on the UI thread, but when the event fires, you can use Control.Invoke to execute a piece of code on the UI thread, in your case this code will be a function that shows the tool tip.
Thanks, I figured it out by doing the following in frmMain and in the other class calling a new method in frmMain called dispalyToolTip.
In FrmMain here is what I did:
added a delegate
Private Delegate Sub displayTooltipDelegate(ByVal tooltipText As String)
Added the new method, which I am calling from the other class
Friend Sub displayTooltip(ByVal tooltipText As String)
If Me.InvokeRequired Then
Dim delegate1 As New displayTooltipDelegate(AddressOf displayTooltip)
Me.Invoke(delegate1, tooltipText)
Else
NotifyIcon1.ShowBalloonTip(500, "Folder Monitor", tooltipText, ToolTipIcon.Info)
End If
End Sub