Dynamically adding an ActiveX control to VB.Net form does nothing - vb.net

In VB.Net, I'm trying to add a QuickTime ActiveX control to a Form when the user clicks a button.
My code is below. For testing I've got a design-time ActiveX control, "designed_control", which works fine, but I'm trying to place "dynamically_created_control" onto the form.
Public Class Form1
Private moviePath As String = "\\localhost\D$\Temp\Test.mov"
Friend WithEvents dynamically_created_control As AxQTOControlLib.AxQTControl = Nothing
Private Sub buttonLoadMovieIntoExisting_Click(sender As Object, e As EventArgs) Handles buttonLoadMovieIntoExisting.Click
' load movie into control created in designer, works fine:
MessageBox.Show(moviePath)
With designed_control
.URL = moviePath
MessageBox.Show("URL:" + .URL)
End With
End Sub
Private Sub buttonCreateNewControl_Click(sender As Object, e As EventArgs) Handles buttonCreateNewControl.Click
' create a new ActiveX control when button is clicked:
dynamically_created_control = New AxQTOControlLib.AxQTControl
CType(dynamically_created_control, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(Form1))
With dynamically_created_control
.CreateControl()
.Enabled = True
.Location = New System.Drawing.Point(160, 160)
.Name = "new_control"
.OcxState = CType(resources.GetObject("designed_control.OcxState"), System.Windows.Forms.AxHost.State)
.Size = New System.Drawing.Size(480, 270)
.TabIndex = 0
Me.Controls.Add(Me.dynamically_created_control)
.Visible = True
.URL = moviePath
End With
CType(dynamically_created_control, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(True)
With dynamically_created_control
MessageBox.Show("URL:" + vbCrLf + .URL)
.Movie.Play()
End With
End Sub
End Class
This doesn't work; when I click 'buttonCreateNewControl', it will pop up the 'URL:' messagebox with the correct URL, showing that the properties of dynamically_created_control are being set and the object is not nothing. However the rectangular shape of the control I'd expect doesn't appear on the form. As soon as I call the .Play() method of the control, it raises an exception because .Movie is nothing, when it shouldn't be.
Can anyone spot why the dynamically-generated ActiveX control simply doesn't appear (but without throwing errors), when the designer-based version is absolutely fine?
Incidentally, I'm aware of the security issues around QuickTime, which is why I'm now trying to code something which can optionally use QuickTime if the user decides to.
Thanks

I believe you may need to update buttonCreateNewControl_Click to use
.OcxState = CType(resources.GetObject("dynamically_created_control.OcxState"), System.Windows.Forms.AxHost.State)
Hope this helps.

I have spotted the error in my code.
The .createControl() method was attempting to create an external QuickTime window. That control works for something like VLC Player, but QuickTime doesn't support it, so nothing was happening.
As soon as I commented out createControl(), the behaviour became what I was expecting.
The .createControl() was a leftover from code I found online, I assumed it was essential for initiating the ActiveX control but it isn't.

Related

Parent form sometimes does not close (Only in Windows 10)

My main form is frmInvoice. This sub is located inside frmInvoice.
This is one of the Subs that sometimes causes frmDark to not close. frmLookup does not display when this happens. frmDark just stays there covering frmInvoice. It's like it doesn't reach the call to frm.ShowDialog(frmDark), cause when I press the lookup key, it displays the frmLookup, but upon closing frmLookup, frmDark is still there.
No exception is being raised.
Note that this only happens in Windows 10. In Windows 8/7, this never happened. What am I missing?
This happens at different times. Sometimes I could press the lookup key for 20 times and it will display fine. Sometimes, after 1 press of the lookup key and this happens.
Private Sub ItemLookup()
Try
Using frmDark As New Form
With frmDark
.ShowInTaskbar = False
.Icon = Me.Icon
.FormBorderStyle = Windows.Forms.FormBorderStyle.None
.BackColor = Color.Black
.Opacity = 0.95
.WindowState = FormWindowState.Maximized
.Show(Me)
Using frm As New frmLookup
With frm
.Icon = Me.Icon
.ShowDialog(frmDark)
frmDark.Close()
If .DialogResult = Windows.Forms.DialogResult.OK Then
' Do stuff here
End If
End With
End Using
End With
End Using
Catch ex As Exception
ErrMsg(ex)
End Try
End Sub
UPDATE: I'm using .Net Framework 4.8
Thanks
I would suggest rearranging the code like so:
Dim lookupResult As DialogResult
Using frmDark As New Form With {.ShowInTaskbar = False,
.Icon = Me.Icon,
...}
frmDark.Show(Me)
Using frm As New frmLookup With {.Icon = Me.Icon}
lookupResult = frm.ShowDialog(frmDark)
End Using
End Using
If lookupResult = DialogResult.OK Then
'...
End If
Because that code exits the Using block that created frmDark, there should be no way that it can't close.
Also, instead of using a vanilla Form and configuring it on demand, I would suggest that you create a dedicated form type to use as the overlay in that scenario. You can then get rid of all the property assignments.
Having a dedicated overlay form would also allow you to reconfigure things significantly and, in my opinion, better. The overlay form could have a property of type Form. You main form could then create a frmLookup instance and assign it to that property, than call ShowDialog on the overlay form. In the Shown event handler of the overlay form, it could then call ShowDialog on the form in that property. When that call returns, it could assign the result to its own DialogResult property and close itself. The main form would then just get the result from calling ShowDialog on the overlay. That might look like this:
Public Class OverlayForm
Public Property DialogueForm As Form
Private Sub OverlayForm_Shown(sender As Object, e As EventArgs) Handles Me.Shown
DialogResult = DialogueForm.ShowDialog()
End Sub
End Class
and this:
Public Class MainForm
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Using dialogue As New DialogueForm,
overlay As New OverlayForm With {.DialogueForm = dialogue}
If overlay.ShowDialog() = DialogResult.OK Then
MessageBox.Show("OK")
End If
End Using
End Sub
End Class

How to load a form on the basis of previous execution?

I have made a form in Vb.net in which the user can do several changes. I want the changes which the user makes should remain each time it is executed.
For Example, I have applied some effects on font while execution -
Private Sub Checkbox1_CheckedChanged ()
If CheckBox1.Checked = True then
Label1.Font = New Drawing Style ("Comic Sans Ms", 16, FontStyle.Bold)
End If
End Sub
The changes which the user makes should be visible next time the program is executed.
Is it possible?
Thanks in Advance!
You have a couple of options, The one that I would use if you are just going to have a few settings is the built in User Settings, you can create a setting in your Project Propertys. This is an example of your Font.
You would then use it like this.
Private Sub Checkbox1_CheckedChanged() Handles CheckBox1.CheckedChanged
If CheckBox1.Checked = True Then
Label1.Font = New Font("Comic Sans Ms", 16, FontStyle.Bold)
My.Settings.MyNewFont = Label1.Font
My.Settings.Save()
End If
End Sub
Public Sub New()
' This call is required by the designer.
InitializeComponent()
If Not IsNothing(My.Settings.MyNewFont) Then Label1.Font = My.Settings.MyNewFont
End Sub
Yes you can use external Css file for this purpose
1st you create a external Css file of your project and specify some default style
Like your Css file
.Fstyle {
font-family: Comic Sans Ms;
}
And your aspx
<asp:label id="lblname" runat="server" class="Fstyle">
2nd you can re-write to this file by the changes which the user makes
save the changes to the variables and override this file by using IO function of vb.net it remains the changes permanent.
Marks answer is how i would do it Except if you wish to store changes for a number of different controls you might be best to loop through them and check the settings on form closing and store them in a System.Collections.Specialized.StringCollection in My.Settings then you can loop through this collection on Form Load and set the settings as they should be.
Let me know if you want an example and i can provide it.
Example:
Note: I have always found when adding a System.Collections.Specialized.StringCollection you need to add an empty string manually (you can then delete it) to force it to create the .xml (probably a more technical solution to this but it works for me)
I created one called FormLoadData
To identify which controls to store data for I prefixed their names with "UC_", if it is all the controls on the form or all in a groupbox etc then you can skip this check.
then add the following form closing sub:
Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
'clear collection
My.Settings.FormLoadData.Clear()
'loop through each control on the form
For Each Con As Control In Me.Controls
'run check to see if it is a control to store changes for
If Con.Name.Substring(0, 3) = "UC_" Then
'load any settings you wish to store in the collection starting with the control ID
My.Settings.FormLoadData.Add(Con.Name & "," & Con.Font.ToString)
End If
Next
End Sub
and the following under New:
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
'loop through controls
For Each Con As Control In Me.Controls
'loop through settings to compare
For Each item In My.Settings.FormLoadData
'check stored name against control name
If Con.Name = item.Split(",").ElementAt(0) Then
'update settings
Con.Font = New Font(item.Split(",").ElementAt(1), Con.Font.Size)
MsgBox(item)
Exit For
End If
Next item
Next Con
End Sub
There is certainly a better way of doing this rather then the loop through the collection created but unless you are storing the data for thousands of controls this will work OK.
My browser is playing up so i cannot check what this looks like but hopefully it is clear!

Dynamically create and remove a control from a form, many times

The below subroutine, when called using a mouse click, successfully creates and then removes a control. but it doesn't create it a second time. I'm assuming it is because the label is not longer dimensioned as public. ie Dim lblDebug1 As New Label is at the top variable section of the form.
However when I put Dim lblDebug1 As New Label in the subroutine the dispose request doesn't work. Is there someway that I can keep creating and disposing a control?
In the below sub, booleanDebug is used to switch back and forth between creating it and disposing it. Thanks in advance.
Dim lblDebug1 As New Label
booleanDebug = Not booleanDebug
If booleanDebug Then
Me.Controls.Add(lblDebug1)
lblDebug1.BackColor = Color.BlueViolet
Else
lblDebug1.Dispose()
End If
Ensure the label has a global context. Within the form that owns it and that you have all the appropriate size and coordinates information and visibility set.
Here is some sample code that worked for me. First just create a new windows form then add a button control in the middle of the form then use the following code.
Public Class Main
Private labelDemo As Windows.Forms.Label
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.SuspendLayout()
If labelDemo Is Nothing Then
labelDemo = New Windows.Forms.Label
labelDemo.Name = "label"
labelDemo.Text = "You Click the Button"
labelDemo.AutoSize = True
labelDemo.Left = 0
labelDemo.Top = 0
labelDemo.BackColor = Drawing.Color.Violet
Me.Controls.Add(labelDemo)
Else
Me.Controls.Remove(labelDemo)
labelDemo = Nothing
End If
Me.ResumeLayout()
End Sub
End Class
Once you've Disposed a control, you can't use it any more. You have two choices here:
Choice 1: Just Remove the control from the form rather than disposing it:
'Top of the file
Dim lblDebug1 As New Label
'Button click
booleanDebug = Not booleanDebug
If booleanDebug Then
lblDebug1.BackColor = Color.BlueViolet
Me.Controls.Add(lblDebug1)
Else
Me.Controls.Remove(lblDebug1)
End If
Choice 2: Create a new control object each time
'Top of the file
Dim lblDebug1 As Label
' ^ No "New".
'We just want an object reference we can share at this point, no need for an instance yet
'Button click
booleanDebug = Not booleanDebug
If booleanDebug Then
lblDebug1 = New Label()
lblDebug1.BackColor = Color.BlueViolet
Me.Controls.Add(lblDebug1)
Else
lblDebug1.Dispose()
End If

Access properties of controls on a programatically created user control VB .NET

After taking a few years off from programming, I decided to start learning vb.net. I have created a user control that contains a picture box. I added some custom properties to the picture box that will hold general string data from a database.
My problem is that the user control is programatically created during run time, and during this time a DoubleClick event handler is added for the picture box that is within the user control.
I need to be able to set the custom properties for the picture box during the creation of the user control, so that when the control (picture box) is double clicked I can read these values but am unsure on how to access them.
The picture box is the entire size of the user control, or I would just add the custom properties right to the user control and add the DoubleClick event handler to that. However, double clicking needs to be done on the picture box since it takes up the entire user control, unless anyone has an idea to trigger the DoubleClick event of the user control when the picture box is double clicked.
Here is a bit of code I am using to add the user control to the form programatically -
hb_item = New PictureLoader
With hb_item
.Name = "item_" & i
.Left = itemLeft
.Top = itemTop
.SetImageSizeMode = ImageLayout.Stretch
.SetLoadingImageSizeMode = ImageLayout.Stretch
.Size = New Size(100, 126)
.SetImage = BlobToImage(sql_reader("ThumbImage"))
.Visible = True
.SetHighlight(True)
.SetHighlightColor = Color.GreenYellow
.TextColor = Color.White
.CircleColor = Color.GreenYellow
'--- THIS UPDATES ONE OF THE CUSTOM PROPERTIES FOR THE PICTURE BOX
'--- CONTAINED WITHIN THE USER CONTROL
.SetID = "test"
AddHandler .picMainClick, AddressOf frmHome.HBItem_Click
AddHandler .picMainDoubleClick, AddressOf frmHome.HBItem_DoubleClick
End With
Here is the event handler code I am trying to access the picture box's custom properties from
Public Sub HBItem_DoubleClick(ByVal sender As System.Object, ByVal e As EventArgs) Handles MyBase.DoubleClick
With sender
'--- THIS IS WHERE I WANT TO READ THE DATA IN THE CUSTOM PROPERTIES
'--- OF THE PICTURE BOX... SOMETHING SIMILAR TO THE FOLLOWING -
' Database_ID is one of the custom properties of the sender (picMain
' control on the user control)
MessageBox.Show(.Database_ID)
End With
End Sub
EDIT: Got it all worked out, thanks for everything. All that was needed was casting the sender to the actual picture box like stated, I was just looking way to deeply into things. A simple one line of code is all that was needed in the event handler -
Dim pb As xPictureBox = CType(sender, xPictureBox)
Then all the custom properties could be accessed using pb.property_here.
sender is of type System.Object - you need to cast (convert) sender to the type it actually is (in your case, your custom user control), i.e.:
Dim myControl As MyCustomControl = CType(sender, MyCustomControl)
With myControl
MessageBox.Show(.Database_ID)
End With

VB.NET - cannot get Video Preview to work

Overflow. I have an application which is supposed to convert a video via DirectShowSource.
I have a checkbox which enables a button called "btnviewcrop" which shows a new form called crp.vb for cropping/shearing pixels off the video.
Now, I have a Panel1 that I want to set as the owner (the video drawing surface) but when I set it to open, the application crashes (Error: Object reference not set to an instance of an object.) and I do not understand how to fix it.
Here is my button code:
Imports Microsoft.DirectX.AudioVideoPlayback
Private Sub btnviewcrop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnviewcrop.Click
Me.ShowInTaskbar = False
Me.Enabled = False
crp.Show()
Dim cropperv As Video
cropperv.Owner = crp.preview 'VS2010 reports that cropperv has been used before being assigned a value'
cropperv.FromFile(labinputfile.Text, True)
cropperv.Play()
End Sub
I don't think you ever assign anything to cropperv. Did you mean
Dim cropperv As New DirectX.AudioVideoPlayback
Good point, and if I do this:
Dim cropperv As New Video(labinputfile.Text, True)
cropperv.Owner = crp.preview
cropperv.Play()
Then all works out fine besides the resizing needs done.
I appreciate the help, Matti.