• 0

[VB.NET] Starting with a form and without


Question

Suppose I have Form1 and there's only 1 button in there (Button1) and I start my application through a Public Sub Main() in Module 1. Then, in Module 1 I have the fomr variable declared this way: Dim frmMain as New Form1; and inside the Sub Main() I have: Application.Run(frmMain). If I have the frmMain inside the Run(), the form will show, if I don't, no form will be shown. And no matter if I have something inside Run() or not, the code will notcontinue after that point unless some function is called from some button, menu or something... I mean:

Public Sub Main()
    Application.Run(frmMain)
    Debug.WriteLine("Test") ' This line won't be processed...
End Sub

Also, on the Module 1 I have some function like:

Public Sub Function1()
End Sub

It doesn't matter what's inside, it's just a function I need to use.

I need to call this function when I click the Button1; no problem with that, it's easy. Now... My application can be accessed with 1 parameter or not and this is my problem. Not reading parameters, cause for that I use the following code:

For Each Argument As String In CmdArguments
            If (Argument = "/monitor") Then
                MonSwitch = True
                Exit For
            End If
        Next

(also in Module1 declarations I have: Dim MonSwitch as Boolean)

I only need this (/monitor) parameter, so, if the application is executed normally, without any parameters, I want it to run as usual and show Form1 but if the parameter is found (MonSwitch = True) I want the application to run normally but without showing the form and after all that, I want to call Function1.

I can't find a way to make it work...

The contentes of my Function1 are:

Public Sub Function1()
        ' Make MainForm as invisible
        frmMain.ShowInTaskbar = False
        frmMain.Hide()

        ' Put icon in the notification area?
        If (frmMain.CheckIcon.Checked = True) Then
            frmMain.NotifyIcon.Visible = True
        End If
    End Sub

Because this code will be called at start (if /monitor is in the parameters) or when I press button1. As you can see, I have a NotifyIcon wich has visible property set to false in the design view and I set it to False when I press Button1 or I start the app with /monitor, wich means I don't want to show Form, I just want the app to rest on the notification area monitoring some files (that's what I want to do).

Basically, I want the app to start hidden and start monitor some files if the parameter /monitor is there, if it's not, show Form1 with all the settings about what to monitor and Button1 is to save the settings and start monitor.

Any help? Can't make all this mess work...

19 answers to this question

Recommended Posts

  • 0

I think you're making this way harder than it needs to be. What I would do is overload the constructor for your frmMain. Have the new New take a boolean as an argument. Store the argument in a private member variable of your form. Handle the Load event for the form and put the code from Function1 in it, except enclose it in an If statement that test the value of the member variable.

Module mainMod
    Public Sub Main(ByVal args() As String)
        Dim MonSwitch As Boolean = False
        For Each s As String In args
            If s = "/monitor" Then
                MonSwitch = True
                Exit For
            End If
        Next

        Application.Run(New frmMain(MonSwitch))

    End Sub

End Module

' frmMain
    Private isMon As Boolean
    Public Sub New(ByVal isMon As Boolean)
        MyBase.New()

        InitializeComponent()
        Me.isMon = isMon
    End Sub

    Private Sub FormLoad(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        If isMon = True Then
            ' Make MainForm as invisible
            Me.ShowInTaskbar = False
            Me.Hide()

            ' Put icon in the notification area?
            If (Me.CheckIcon.Checked = True) Then
                Me.NotifyIcon1.Visible = True
            End If
        End If
    End Sub

  • 0

I have done the way you said but now I couldn't yet test it and now I have another problem...

The thing is that now I can't have Dim frmMain As New Form1 in the module declarations, and if I don't have that, how do I hacces the form properties and the form controls properties in some other module functions?

For instance, I have the following function in the module to load some settings from an ini file and set them in Form1:

Public Sub LoadSettings()
        Dim CheckStartup As Integer, CheckIcon As Integer
        Dim FileMon As String, FileRep As String

        ' Get settings from ini file
        FileMon = INISettings.GetString("Files", "FileMonitor", "")
        FileRep = INISettings.GetString("Files", "FileReplacement", "")
        CheckStartup = INISettings.GetInteger("Options", "Startup", 0)
        CheckIcon = INISettings.GetInteger("Options", "ShowIcon", 0)

        ' Set settings in MainForm
        frmMain.CheckStartup.CheckState = CheckStartup
        frmMain.CheckIcon.CheckState = CheckIcon
        frmMain.FileMon.Text = FileMon
        frmMain.FileRep.Text = FileRep
    End Sub

this is now longer working with your code...

And, is this possible? (the code you gave me):

Private Sub FormLoad(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
       If isMon = True Then
           ' Make MainForm as invisible
           Me.ShowInTaskbar = False
           Me.Hide()

           ' Put icon in the notification area?
           If (Me.CheckIcon.Checked = True) Then
               Me.NotifyIcon1.Visible = True
           End If
       End If
   End Sub

Make it like this and then create a startmonitor() function:

Private Sub FormLoad(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
       If isMon = True Then
           StartMonitor()
       End If
   End Sub

Can't I do it like that?

  • 0

1. Just dimension it in the module. Instantiate it in the Application.Run(). Not very good design though. Globals are not considered good code. Just because you can, doesn't mean you should.

2. You could stick the LoadSettings call in the constructor(after the InitializeComponent), or the Load handler. If you don't have a global(bad anyway) of frmMain, then just pass it as a parameter to LoadSettings, and any other sub/function that needs to read its properties, modifying the signature.

' old signature: public sub LoadSignature()
' new
public sub LoadSignature(frmMain frm) ' assuming frmMain is a class
    ' this is a preferred method anyhow. globals are bad.
end sub

3. Yes, you can put whatever you want in the Load event handler.

  • 0

:s

this is getting very confusing for me... I did not understand your last post and I still can't understand how could I access Form1 properties and controls and such in any module functions. And I also have something like this on sub main (wich is in module1):

frmMain.Text = AppName + " v" + AppVer

frmMain.NotifyIcon.Text = AppName + " v" + AppVer

How could I even pass a parameter in sub new()?? and passing parametr for any other function, did not work. I guess i'll have to deleted the module and code everything in the form...

  • 0

Sorry if I'm confusing you. I think you're missing some fundamental skills that would greatly help you.

I'm simply saying avoid global variables at all costs. It's not that hard to do.

Obviously, I don't have all your code, but here is a module that would do what you want it to without a global.

Module mainMod
    Public Sub Main(ByVal args() As String)

        ' get args first
        Dim MonSwitch As Boolean = False
        For Each s As String In args
            If s = "/monitor" Then
                MonSwitch = True
                Exit For
            End If
        Next

        ' instantiate the frm, passing the MonSwitch as a parameter
        Dim frm As frmMain = New frmMain(MonSwitch)
        frm.Name = Application.ProductName + " v." + Application.ProductVersion
        frm.NotifyIcon.Text = Application.ProductName + " v." + Application.ProductVersion

        ' run it
        Application.Run(frm)
    End Sub

    Public Sub LoadSettings(ByRef frm As frmMain)
        Dim CheckStartup As Integer, CheckIcon As Integer
        Dim FileMon As String, FileRep As String

        ' Get settings from ini file
        FileMon = INISettings.GetString("Files", "FileMonitor", "")
        FileRep = INISettings.GetString("Files", "FileReplacement", "")
        CheckStartup = INISettings.GetInteger("Options", "Startup", 0)
        CheckIcon = INISettings.GetInteger("Options", "ShowIcon", 0)

        ' Set settings in MainForm
        frm.CheckStartup.CheckState = CheckStartup
        frm.CheckIcon.CheckState = CheckIcon
        frm.FileMon.Text = FileMon
        frm.FileRep.Text = FileRep
    End Sub

    Public Sub StartMonitor(ByRef frm As frmMain)
        frm.ShowInTaskbar = False
        frm.Hide()

        ' Put icon in the notifications area?
        ' If (frm.CheckIcon.Checked = True) Then
        frm.NotifyIcon.Visible = True
        ' you could shorten this to just frm.NotifyIcon.Visible = frm.CheckedIcon.Checked
    End Sub
End Module

Here's the my form that calls this stuff in form load. I'm passing a variable to the constructor, and I'm passing a reference to the form itself. Again, I don't have everything you do, but it should illustrate to you what I'm talking about.

Imports System.Runtime.InteropServices
Public Class frmMain
    Inherits System.Windows.Forms.Form

    Private mIsMonitor As Boolean

    ' this is an overloaded constructor
    ' the default constructor is still there in the generated code region
    Public Sub New(ByVal isMonitor As Boolean)
        MyBase.New()
        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call
        mIsMonitor = isMonitor
    End Sub

    Public Sub FormLoad(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
        ' do all form initialization
        LoadSettings(Me)
        If mIsMonitor = True Then
            StartMonitor(Me)
        End If
    End Sub

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call
        mIsMonitor = False
    End Sub


    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents NotifyIcon As System.Windows.Forms.NotifyIcon
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.components = New System.ComponentModel.Container
        Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(frmMain))
        Me.NotifyIcon = New System.Windows.Forms.NotifyIcon(Me.components)
        '
        'NotifyIcon
        '
        Me.NotifyIcon.Icon = CType(resources.GetObject("NotifyIcon.Icon"), System.Drawing.Icon)
        Me.NotifyIcon.Text = "NotifyIcon"
        Me.NotifyIcon.Visible = True
        '
        'frmMain
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(292, 273)
        Me.Name = "frmMain"
        Me.Text = "Main Form"

    End Sub

#End Region


End Class

  • 0

woooww... thanks a lot, I'll try it later as I can't do it right now but I just have 2 questions.

In here:

Module mainMod

Public Sub Main(ByVal args() As String)

where do this args come from? why are there? in my first example (where I wrote how would I get the /monitor parameter) I used a global variable like: Dim CmdArguments As String() = Environment.GetCommandLineArgs()

In your second [ code ] tag after "#Region " Windows Form Designer generated code ""... is there something I need to check or it was some mistake?

thanks once again.

  • 0

From MSDN:

  Quote
Main can also take a String array as an argument. Each string in the array contains one of the command-line arguments used to invoke your program. You can take different actions depending on their values.

It works the same as Environment.GetCommandLineArgs().

The second code tag is an entire form. I just cut and paste the whole thing. You can see that there is another New() sub there without the argument, which has mIsMonitor default to false. So, if you just instantiate the form with empty parens(e.g. frm = new frmMain() ), it'll load normally.

  • 0

Now I have another problem and I think this is easy to fix (at least for you) i'm going to create a new thread for that and hope you still read this :p

this is the following code I have to watch some folder's activity:

Dim Watchfolder As New FileSystemWatcher
        Dim FilePath As String = frmMain.FileMon.Text

        Watchfolder.Path = FilePath.Substring(0, frmMain.FileMon.Text.LastIndexOf("\"))
        Watchfolder.NotifyFilter = Watchfolder.NotifyFilter Or IO.NotifyFilters.Attributes

        AddHandler Watchfolder.Changed, AddressOf DoReplace
        AddHandler Watchfolder.Deleted, AddressOf DoReplace

        Watchfolder.EnableRaisingEvents = True

and then this:

Private Sub DoReplace(ByVal source As Object, ByVal e As FileSystemEventArgs)
    End Sub

Inside DoReplace, I need to get access to some textboxes text in the form and the whole code I just posted is in the module. How can I do it? If I try to add 1 more parameter to DoReplace, I just can't make it work in the line: AddHandler Watchfolder.Deleted, AddressOf DoReplace.

  • 0

Hmm... If you want data from your form, then your form should handle the Changed and Deleted events of the FileSystemWatch, IMO.

This is a design issue for sure. I don't know what else depends on your FileSystemWatch, so I can't give you a definitive answer.

  • 0
  weenur said:
Hmm... If you want data from your form, then your form should handle the Changed and Deleted events of the FileSystemWatch, IMO.

how do I do that?

basically, the filesystemwatcher code is inside the Startmonitor(). what else you need to know so I can try to help me?

  • 0
  Nazgulled said:
can't you (or anybody else) help em anymore? I really wanted to finish this and i'm almost there, just waiting for that part... I could make some gloabls but I didn't want to... I wanted to keep the DoReplace in the module too.

585292678[/snapback]

Is the FileSystemWatch declared(Dim) as a global or inside the StartMonitor?

  • 0
  Nazgulled said:
inside startmonitor() but I'll change it if necessary...

585293383[/snapback]

Yeah, make it public or friend in your module, outside any subs or functions. Then it's as simple as using the AddHandler in your form, like you did in your StartMonitor, in the constructor or the Load event. Just put the handling method in the form so it can access the form's members.

  • 0

the handling method can't be inside the form, it must be inside the startmonitor() wich is in the module, it must be there, because this function (startmonitor()) can be called in the load event with all that code we've been through the previous posts or can be called pressing a butotn and I don't want to have the same code duplicated...

  • 0
  Nazgulled said:
the handling method can't be inside the form, it must be inside the startmonitor() wich is in the module, it must be there, because this function (startmonitor()) can be called in the load event with all that code we've been through the previous posts or can be called pressing a butotn and I don't want to have the same code duplicated...

585293804[/snapback]

Then make a sub/function that takes a string or strings as parameters and have it called from the handler inside the form.

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • How did they source that "small seed of randomness" I wonder.
    • Malwarebytes 5.3.6.205 by Razvan Serea Malwarebytes is a high performance anti-malware application that thoroughly removes even the most advanced malware and spyware. Malwarebytes version 5.xx brings comprehensive protection against today’s threat landscape so that you can finally replace your traditional antivirus. You can finally replace your traditional antivirus, thanks to a innovative and layered approach to prevent malware infections using a healthy combination of proactive and signature-less technologies. While signatures are still effective against threats like potentially unwanted programs, the majority of malware detection events already come from signature-less technologies like Malwarebytes Anti-Exploit and Malwarebytes Anti-Ransomware; that trend will only continue to grow. For many of you, this is something you already know, since over 50% of the users already run Malwarebytes as their sole security software, without any third-party antivirus. What's new in Malwarebytes 5.xx: Unified user experience - For the first time, Malwarebytes now provides a consistent experience across all of our desktop and mobile products courtesy of an all new and reimagined user experience powered by a faster and more responsive UI all managed through an intuitive dashboard. Modern security and privacy integrations - Antivirus and ultra-fast VPN come together seamlessly in one easy-to-use solution. Whether you’re looking for a next-gen VPN to secure your online activity, or harnessing the power of Browser Guard to block ad trackers and scam sites, taking charge of your privacy is simple. Trusted Advisor - Empowers you with real-time insights, easy-to-read protection score and expert guidance that puts you in control over your security and privacy. Malwarebytes 5.3.6.205 changelog: Improved the onboarding experience with minor usability enhancements. Updated My subscription page design for better clarity. Added text explaining Scan notifications settings in Notifications page. Updated firewall filtering profile colors in Windows Firewall Control feature for Windows 11 users. Fixed minor UI issues with Windows Firewall Control feature for Windows 11 users. Fixed various localization and usability glitches. Download: Malwarebytes 5.3.6.205 | 403.0 MB (Free, paid upgrade available) Links: Malwarebytes Website | Screenshot Get alerted to all of our Software updates on Twitter at @NeowinSoftware
    • https://shop.royalmail.com/special-stamp-issues/monty-python
    • Microsoft disables a key graphics feature in Edge by Paul Hill Microsoft has released its new security baseline for its Edge browser version 139, it includes the addition of one setting and the removal of one other. For those that are unaware, these security baselines allow admins to set an organization’s Edge browser settings to the default that Microsoft recommends at any one time. You can download the new package from the Security Compliance Toolkit. With this update, the company is enforcing the default to disable the EnableUnsafeSwiftShader policy. This will help to mitigate potential risks as malicious web content could exploit vulnerabilities in the renderer. SwiftShader is a software-based renderer that serves as a fallback for WebGL in environments without GPU acceleration, such as virtual machines. With Microsoft’s disabling of it, it seems as though this compatibility tool is now seen as a liability. The disabled SwiftShader was the most relevant in virtual machines which are widely used in enterprises, so this change poses the risk of causing a bit of disruption. While the move is a good one for security, those who it affects may want to deviate away from Microsoft’s security baselines. The security baseline announcement also mentions a new Edge for Business security connectors feature which is designed to integrate the browser with security software for DLP and authentication. Microsoft said that these connectors can close critical gaps in enterprise security. You can learn more on the feature’s landing page. Microsoft doesn’t seem to have made the change to SwiftShader due to existing vulnerabilities, instead the move seems to be a proactive security improvement. If you rely on it with your virtual machines, feel free to deviate away from Microsoft’s security baseline, but understand you’re no longer following the company’s security advice.
  • Recent Achievements

    • One Month Later
      chiptuning earned a badge
      One Month Later
    • Week One Done
      harveycoleman123 earned a badge
      Week One Done
    • First Post
      EzraNougat earned a badge
      First Post
    • One Month Later
      westDvina earned a badge
      One Month Later
    • Community Regular
      Bern@rd went up a rank
      Community Regular
  • Popular Contributors

    1. 1
      +primortal
      667
    2. 2
      +FloatingFatMan
      196
    3. 3
      ATLien_0
      154
    4. 4
      Xenon
      132
    5. 5
      wakjak
      102
  • Tell a friend

    Love Neowin? Tell a friend!