Wait after showing MDI child form - alternative to DoEvents - vb.net

A co-worker made some improvements to my app, but at the same time, he changed the whole app to use MDI child forms. So where I used to be able to use ShowDialog() to make the subroutine wait until the new form closed to continue, now I can't. I adapted some old VB6 code to try and replicate the same functionality, but it uses DoEvents() and I've been told to avoid that at all costs.
At this point I can't help but feel like there's just a fundamental flaw in my methodology here, and that there is probably a far simpler way to accomplish the same task.
Private Sub Label_EditNode_Click(sender As Object, e As EventArgs) Handles Label_EditNode.Click
Dim Frm As New frmVariableEditor With {
.Tag = "FrmVariableEditor",
.MdiParent = FrmMDIMain,
.Dock = DockStyle.Fill,
.Location = Me.Location,
.Size = Me.Size,
.myFieldName = "NodeClick",
.myResultText = txbNodeClick.Text
}
Frm.Show()
Call WaitOnFormUnload()
txbNodeClick.Text = Frm.myResultText
End Sub
Public Sub WaitOnFormUnload()
Dim bIsLoaded As Boolean = True
Dim FormName As String = Me.MdiParent.ActiveMdiChild.Name ' Form.ActiveForm.Name
Do While bIsLoaded
bIsLoaded = False
For Each f As Form In Application.OpenForms
If f.Name = FormName Then
bIsLoaded = True
Application.DoEvents()
Exit For ' breaks the for loop
End If
Next f
Loop
End Sub

Goes a something like this:
Private Sub Label_EditNode_Click(sender As Object, e As EventArgs) Handles Label_EditNode.Click
Dim Frm As New frmVariableEditor With {
.Tag = "FrmVariableEditor",
.MdiParent = FrmMDIMain,
.Dock = DockStyle.Fill,
.Location = Me.Location,
.Size = Me.Size,
.myFieldName = "NodeClick",
.myResultText = txbNodeClick.Text
}
AddHandler Frm.FormClosing, AddressOf RetrieveBlahData
Frm.Show()
End Sub
Private Sub RetrieveBlahData(sender as Object, e as FormClosingEventArgs)
txbNodeClick.Text = DirectCast(sender, frmVariableEditor).myResultText
End Sub
Probably doesn't get more minimal than that, except for maybe sharing a single data object:
Dim Frm As New frmVariableEditor With {
.Tag = "FrmVariableEditor",
.MdiParent = FrmMDIMain,
.Dock = DockStyle.Fill,
.Location = Me.Location,
.Size = Me.Size,
.myFieldName = "NodeClick",
.DataSetToBindTo = Me.DataSetWhatever
}
You'll have to re-code your form so that it takes this passed in dataset (or other data container) and gets its data from it (databinding) .. then as the editor form is changing the data, it's actually changing the original dataset in the main form too, because they're the same thing

Related

How to resize a chart before printing in vb.net

I would like to print a chart in my vb.net application but when I print it, it's very small and I can't find how to resize it.
For now, I'm using this code: (Found here : Some msdn printing subject)
Private Sub BT_Print_Click(sender As Object, e As EventArgs) Handles BT_Print.Click
Dim pdS As New PrintDocument()
AddHandler pdS.PrintPage, AddressOf pds_PrintPage
pdS.DefaultPageSettings.Landscape = True
Dim PrintDialog1 As New PrintPreviewDialog
PrintDialog1.Document = pdS
If (PrintDialog1.ShowDialog = DialogResult.OK) Then
Chart_Requis.Printing.PrintDocument.DefaultPageSettings.Landscape = True
pdS.Print()
End If
End Sub
Private Sub pds_PrintPage(sender As Object, ev As PrintPageEventArgs)
Dim chartPosition As New Rectangle(1, 1, ev.MarginBounds.Width, ev.MarginBounds.Height)
Chart_Requis.Printing.PrintPaint(ev.Graphics, chartPosition)
End Sub
After all my attempt I just reached to move margins... which is good but I still cannot read my chart correctly...
Do someone had the same issue and found a solution ?
----------------------------------------EDIT-------------------------------------
As I explain it the comment of your answer, I now can change chart's position and size but blank squares appears and I don't know why !
By image you have posted seems your issue is ChartArea not Chart Control.
You need to increase Area of your Chart Area.
In the example below (which can help you in that) I have used two parameters scaleX and scaleY .
You can work on those two to find the right size becomes on print.
Note that.: As Chart Area in the example I’ve used the first of your Chart Control, but, you can use another calling it by name. Hope is what you needs.
Private Sub BT_Print_Click(sender As Object, e As EventArgs) Handles BT_Print.Click
Using pdS As New PrintDocument()
Dim scaleX As Single = 1.5
Dim scaleY As Single = 1.2
With pdS.DefaultPageSettings
.Landscape = True
.Margins = New Margins(10, 10, 10, 10)
End With
Chart_Requis.Printing.PrintDocument = pdS
AddHandler pdS.PrintPage, Sub(obj As Object, ev As PrintPageEventArgs)
Using ev.Graphics
With Chart_Requis.ChartAreas.FirstOrDefault
Dim initialP As DataVisualization.Charting.ElementPosition = .Position
Dim newP As Rectangle = New Rectangle With {
.X = CInt(initialP.X),
.Y = CInt(initialP.Y),
.Width = CInt(initialP.Width * scaleX),
.Height = CInt(initialP.Height * scaleY)
}
.Position.FromRectangleF(newP)
Chart_Requis.Printing.PrintPaint(ev.Graphics, ev.MarginBounds)
.Position = initialP
End With
End Using
End Sub
Using PrintDialog1 As New PrintPreviewDialog With {
.Document = pdS
}
If (PrintDialog1.ShowDialog = DialogResult.OK) Then
pdS.Print()
End If
End Using
End Using
End Sub
Ok, I finally found something which worked for me here and I adapt it to my case : Another Stackoverflow subject
I let you see the final chart here :
I add a dialogbox to choose the printer and adapt a bit the original code as you can see here :
Private Sub BT_Print_Click(sender As Object, e As EventArgs) Handles BT_Print.Click
Print_Preview()
End Sub
Public Sub Print_Preview()
Dim Print_Doc As PrintDocument
Print_Doc = Chart_Requis.Printing.PrintDocument
AddHandler Print_Doc.PrintPage, New PrintPageEventHandler(AddressOf Print_Page)
'SHEET PARAMETERS
Print_Doc.DefaultPageSettings.Landscape = True
Print_Doc.DefaultPageSettings.Margins = New Printing.Margins(0, 1, 1, 1)
Print_Doc.DefaultPageSettings.Color = True
'CHOOSING PRINTER AND OTHER PARAMETERS
Dim Print_dlg As New PrintDialog
Print_dlg.Document = Print_Doc
Dim result As DialogResult = Print_dlg.ShowDialog()
'IF DIALOGBOX OK THEN CONTINUE OTHERWISE NO
If (result = DialogResult.OK) Then
'PUT MARKERS TO THE RIGHT SIZE
For i = 0 To Chart_Requis.Series.Count - 1
Chart_Requis.Series(i).MarkerSize = 1
Next
'CHECKING BEFORE PRINTING
Chart_Requis.Printing.PrintPreview()
End If
End Sub
Private Sub Print_Page(ByVal sender As Object, ByVal ev As PrintPageEventArgs)
'DEFINI LA POSITION ET LA TAILLE DU GRAPHIQUE
Dim chartPosition As New Rectangle(-70, -50, 2500, 2300)
Chart_Requis.Printing.PrintPaint(ev.Graphics, chartPosition)
End Sub
Hope it will help someone in the same trouble than me today...

VB.Net: DataGridView seems as if it is piercing the form

I'm having a graphical issue with a DataGridView.
As you can see the form looks like pierced from the DataGridView control.
The code of the DataGridView instantiation is this:
Private Sub pageAlarms_Load(sender As Object, e As EventArgs) Handles Me.Load
Me.Width = MainForm.Width
Me.Height = MainForm.Height
Me.Dock = DockStyle.Fill
dgvActiveAlarms = New DataGridView()
almBasePanel.Controls.Add(dgvActiveAlarms)
With dgvActiveAlarms
.Dock = DockStyle.Fill
.Name = "activeAlarmsTable"
.AutoSizeRowsMode =
DataGridViewAutoSizeRowsMode.DisplayedCellsExceptHeaders
.ColumnHeadersBorderStyle = DataGridViewHeaderBorderStyle.Single
.CellBorderStyle = DataGridViewCellBorderStyle.Single
.GridColor = Color.Black
.RowHeadersVisible = False
.ColumnCount = 5
End With
End Sub
I tried also to create the control from the designer, but with same result.
The page which contains the almBasePanel is a user control, instantiated in the main form load.
I could not find a topic with similar issue so I decided to submit this question, forgive me if I posted for a redundant argument.
Thank you,
Giuse

Windows Forms Modal Form Closes instantly when Base form is not Active

I have a Winforms Application which should notify the user when something in a database changes. For that i use Sql-Dependencys, which works fine.
When the Dependency fires i am able to show a form with some Buttons so the user can decide what he wants to do.
After one Button i want to show a Dialog, but the first Dialog always gets closed instantly.
The only fix i found until now is restoring the base form and activating it, but that is not the solution i am looking for.
For the code i am doing the Following:
This Method gets called when something changes in the Database
Private Sub NutzerBenachrichtigen(Aenderung As Aenderung)
If InvokeRequired Then
Me.BeginInvoke(New MethodInvoker(Sub()
ErzeugeBenachrichtigung(Aenderung)
End Sub))
Else
ErzeugeBenachrichtigung(Aenderung)
End If
End Sub
This Method Displays the first form (HeadsUp is taken from this here :https://github.com/glm9637/MaterialWinforms/blob/master/MaterialWinforms/Controls/HeadsUp.cs)
Private Sub ErzeugeBenachrichtigung(ByVal Aenderung As Aenderung)
If Aenderung.istAktuellerBenutzer Then
Dim objHeadsUp As New HeadsUp()
objHeadsUp.Titel = "Neue Aenderung"
If Aenderung.EventTyp.ToLower = "alter" Then
objHeadsUp.Text = String.Format("Du hast etwas an {0} {1} {2} geändert. {3}Willst du etwas dazu schreiben?", _
If(Aenderung.BetroffenesObjekt.EntitaetTyp.Name = New EntitaetTyp.Trigger().Name, "dem", "der"), _
Aenderung.BetroffenesObjekt.EntitaetTyp.Name, Aenderung.BetroffenesObjekt.Name, vbNewLine)
Else
objHeadsUp.Text = String.Format("Du hast {0} {1} {2} erstellt. {3}Willst du etwas dazu schreiben?", _
If(Aenderung.BetroffenesObjekt.EntitaetTyp.Name = New EntitaetTyp.Trigger().Name, "den", "die"), _
Aenderung.BetroffenesObjekt.EntitaetTyp.Name, Aenderung.BetroffenesObjekt.Name, vbNewLine)
End If
objHeadsUp.Tag = Aenderung.BetroffenesObjekt
Dim objButtonSchliessen = New MaterialFlatButton
objButtonSchliessen.Tag = objHeadsUp
objButtonSchliessen.Text = "Schliessen"
AddHandler objButtonSchliessen.Click, AddressOf SchliesseHeadsUp
objHeadsUp.Buttons.Add(objButtonSchliessen)
Dim objButtonHistorie = New MaterialFlatButton
objButtonHistorie.Tag = objHeadsUp
objButtonHistorie.Text = "Historieneintrag"
AddHandler objButtonHistorie.Click, AddressOf HistorienEintragHinzufuegen
objHeadsUp.Buttons.Add(objButtonSchliessen)
Dim objButtonDokumentation = New MaterialFlatButton
objButtonDokumentation.Tag = objHeadsUp
objButtonDokumentation.Text = "Dokumentation"
AddHandler objButtonDokumentation.Click, AddressOf DokumentationBearbeiten
objHeadsUp.Buttons.Add(objButtonSchliessen)
objHeadsUp.Buttons.Add(objButtonHistorie)
objHeadsUp.Buttons.Add(objButtonDokumentation)
objHeadsUp.Show()
ElseIf Aenderung.EventTyp = "CLOSE_MESSAGE" Then
Dim objHeadsUp As New HeadsUp()
objHeadsUp.Titel = "Achtung"
objHeadsUp.Text = "Die Anwendung muss für eine Aktualisierung geschlossen werden."
Dim objButtonSchliessen = New MaterialFlatButton
objButtonSchliessen.Tag = objHeadsUp
objButtonSchliessen.Text = "Anwendung Schliessen"
AddHandler objButtonSchliessen.Click, AddressOf AnwendungSchliessen
objHeadsUp.Buttons.Add(objButtonSchliessen)
objHeadsUp.Show()
Else
If mtc_UebersichtTabControl.SelectedTab.Text = "Aenderung" Then
mAenderungenUebersicht.Aktualisieren()
End If
End If
End Sub
Finally when the "Historieneintrag" Button is pressed this Method gets called:
Private Sub HistorienEintragHinzufuegen(sender As Object, e As EventArgs)
Dim blnNachDialogVerstecken As Boolean = False
Dim objFlatButton As MaterialFlatButton = sender
Dim HeadsUp As HeadsUp = objFlatButton.Tag
Dim Objekt As Entitaet = HeadsUp.Tag
Dim objOldLocation As System.Drawing.Point = Location
HeadsUp.Close()
Dim objDialogContent As New HistorienEintrag()
''Hacky: Ansonsten wird der Dialog sofort geschlossen
If WindowState = FormWindowState.Minimized Or Not Visible Then
Location = New System.Drawing.Point(-Width * 2, -Height - 2)
Me.Show()
blnNachDialogVerstecken = True
End If
Activate()
If MaterialDialog.Show("Neuer Historien Eintrag", objDialogContent, MaterialWinforms.Controls.MaterialDialog.Buttons.OKCancel, MaterialDialog.Icon.Info) = DialogResult.OK Then
Objekt.HistorieSpeichern(objDialogContent.Ergebniss)
End If
If blnNachDialogVerstecken Then
Me.Hide()
Location = objOldLocation
End If
End Sub
In here the first modal Form, so a MessageBox.Show("") or any other form closes Instantly if i don't do the show and activate part.
What am i doing wrong here?
Project > (Project) Properties > Application > Shutdown mode
change from when startup form closes to when last form closes

Winforms custom loading screen text not loading

I'm using VB.NET winforms and have a particular form that take a while to load up so I've decided to implement a loading screen to make it feel a bit less freezey. Here is the code I'm using in my freezey form load.
Private Sub HanleyView_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim loaderForm As New Loader
loaderForm.Show()
AllOpenOrdersList.FullRowSelect = True
NeedsAttentionList.FullRowSelect = True
StockManagementList.FullRowSelect = True
Dim lowStockCount = HelperMethods.ReviewLowStock()
ReviewLowStockButton.Text = "Review Low Stock (" & lowStockCount & ")"
RefreshAllOpenOrdersList()
RefreshNeedsAttentionList()
RefreshStockManagementList()
loaderForm.Close()
End Sub
So I start by showing the loading form and finish by closing it.
The good new is that the loading form appears, but the bad news is the "LOADING..." text which is a label on my loading form doesn't show, I just get a white patch there instead. I've tried two approaches, the above and calling Loader.Show and Loader.Close. I've also tried setting loaderForm.Label1.Text = "LOADING..." but this didn't make any difference. Each time the form loads (and the title loads which says "Loading please wait") but not the label on the form itself.
I've now also tried:
Dim loaderForm As New Loader
Dim lbl As New Label
loaderForm.Controls.Add(lbl)
lbl.Text = "LOADING..."
lbl.Location = New System.Drawing.Point(42, 21)
loaderForm.Show()
AllOpenOrdersList.FullRowSelect = True
NeedsAttentionList.FullRowSelect = True
StockManagementList.FullRowSelect = True
Dim lowStockCount = HelperMethods.ReviewLowStock()
ReviewLowStockButton.Text = "Review Low Stock (" & lowStockCount & ")"
RefreshAllOpenOrdersList()
RefreshNeedsAttentionList()
RefreshStockManagementList()
loaderForm.Close()
But this hasn't worked either.
EDIT: I've tried Varocarbas' code but was still unsuccessful. The form loads but the text remains a white patch
Dim loaderForm As Form = New Form
With loaderForm
.Height = 200
.Width = 300
.Location = New System.Drawing.Point(12, 12)
End With
Dim label1 As Label = New Label
loaderForm.Controls.Add(label1)
With label1
.Text = "LOADING..."
.Location = New System.Drawing.Point(12, 45)
End With
loaderForm.Show()
EDIT 2: For clarity, here is my code now it is working using Franck suggestion
Private Sub HanleyView_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim loaderForm As New Loader
loaderForm.Show()
Application.DoEvents()
AllOpenOrdersList.FullRowSelect = True
NeedsAttentionList.FullRowSelect = True
StockManagementList.FullRowSelect = True
Dim lowStockCount = HelperMethods.ReviewLowStock()
ReviewLowStockButton.Text = "Review Low Stock (" & lowStockCount & ")"
RefreshAllOpenOrdersList()
RefreshNeedsAttentionList()
RefreshStockManagementList()
loaderForm.Close()
End Sub
I have kept my original code and simply added Application.DoEvents() below loaderform.Show and it works properly now.
Also the below screenshot is what I mean by using the designer (and not doing it programmtically):
Multithreading!
Create and run the loaderForm on a separate thread. But then you need to be careful about cross-thread operations, so have a self-invoking method on your loaderForm, such as:
Public Sub ParseStatus(msg as String)
If Me.InvokeRequired Then Me.Invoke(New Action(Of String)(AddressOf Me.ParseStatus), msg) Else Me.Label1.Text = msg
End Sub
Also in your loaderForm you want something like:
Public Sub Finish()
Me.DialogResult = Windows.Forms.DialogResult.OK
Me.Close()
End Sub
Then in the Load procedure of your form:
Private Sub HanleyView_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim loaderForm As New Loader
Dim loaderThread As New Threading.Thread(New Threading.ThreadStart(AddressOf loaderForm.ShowDialog))
loaderThread.Start()
loaderForm.ParseStatus("Loading ...")
AllOpenOrdersList.FullRowSelect = True
NeedsAttentionList.FullRowSelect = True
StockManagementList.FullRowSelect = True
Dim lowStockCount = HelperMethods.ReviewLowStock()
ReviewLowStockButton.Text = "Review Low Stock (" & lowStockCount & ")"
LoaderForm.ParseStatus("Refreshing open orders ...")
RefreshAllOpenOrdersList()
loaderForm.ParseStatus("Refreshing needs attentions?") ' etc
RefreshNeedsAttentionList()
RefreshStockManagementList()
loaderForm.Finish()
End Sub
But Visual Studio has a neat thing called SplashScreen in its project templates for VB.NET. I'd use that one, if you aren't already…
Edit: I corrected the syntax errors in the code.

Passing arguments from a dynamic control to AddHandler in VB.NET

I'm trying to figure out how to pass information from one form to another using an AddHandler that I create in a dynamic control.
I have a loop something like
Dim I As Integer
For I = 0 To 10
Dim gbNew As New GroupBox()
Dim pbNew As New PictureBox()
Dim llbNew As New Label()
Dim tlbNew As New Label()
Dim olbNew As New Label()
Dim slbNew As New Label()
Dim wlbNew As New Label()
UserName = dt.Rows(I)("UserName").ToString()
Status = dt.Rows(I)("LastJobType").ToString()
JobType = dt.Rows(I)("LastJobType").ToString()
LLocation = dt.Rows(I)("LastLocation").ToString()
TimeIn = dt.Rows(I)("LogInTime")
TimeOut = dt.Rows(I)("LogOutTime")
FlowLayoutPanel1.Controls.Add(gbNew)
gbNew.Controls.Add(llbNew)
llbNew.Visible = True
llbNew.Text = LLocation
llbNew.Font = New Font(llbNew.Font.FontFamily, 6.5)
llbNew.Location = New System.Drawing.Point(3, 25)
llbNew.BorderStyle = BorderStyle.None
llbNew.TextAlign = ContentAlignment.MiddleLeft
llbNew.Size = New Size(80, 15)
gbNew.Size = New System.Drawing.Size(270, 80)
'gbNew.BackColor = System.Drawing.Color.Silver
gbNew.Visible = True
gbNew.Text = UserName & " " & I + 1
AddHandler gbNew.Click, AddressOf ShowForm
Next
The eventhandler fires off a sub ShowForm:
Private Sub ShowForm()
Details.Show()
End Sub
This in turn pops up a form, but I can't figure out how to pass a few needed bits of information from the dynamic generated control to a static control outside the loop.
I was using a static control in a form:
label1.text = "something"
And I opened the new form, and I could read that into the new form using something like
dim info as string = form1.label.text. But since it is dynamic, I don't have a label1.text. Instead, I have a llbNew.Text which seems to be something I can't call from form2 :(
How can I pass information from form1's dynamic control to form2?
Please keep this to VB.NET, not C#, as I barely understand VB.NET let alone trying to brain convert from C# which I have zero knowledge of.
Here's a direction you could take. I hope it is clear:
For I = 0 To 10
(...)
gbNew.Text = UserName & " " & I + 1
gbNew.Tag = dt.Rows(I) ' Any information that you need here
AddHandler gbNew.Click, AddressOf ShowForm '(No changes here)
Next
' Use the appropriate Event Handler signature # the handler Sub
Private Sub ShowForm(sender as Object, e as EventArgs)
Dim groupBoxClicked as GroupBox = TryCast(sender, GroupBox)
If groupBoxClicked IsNot Nothing
Dim detailsForm as New Details()
detailsForm.ParentInformation = groupBoxClicked.Tag
detailsForm.ShowDialog()
End If
End Sub
(...)
Public Class Details ' Your Details Form
Public Property ParentInformation as DataRow
End Class