Preserve swf transparency on forms vb - vb.net

Is there any way to include a .swf on my form and also preserve its original transparency? That is, so you can see any controls 'behind it' (obviously in the transparent areas). It's looking unlikely as I understand vb can't control the flash activex control (and hence the control's rendered background?) but wondering whether there's any workarounds?
relevant code thusfar:
Dim flash1 As New AxShockwaveFlash
.....
flash1.Location = New System.Drawing.Point(300, 23)
Me.Controls.Add(flash1)
flash1.Movie = "C:\Users\Steve\Scripts\Projects\CPWizBiz\Assets\Test SWFs\Artwork4.swf"
flash1.Size = New System.Drawing.Size(192, 400)
flash1.Play()

In the absence of any other solutions, here's what I did:
Basically, I just created a new form with a transparetn background. You then overlay this onto your main form (you can link any forms to move and resize with each other etc). Then you set the flash background to match the form transparency key and you're done. Brief, illustrative code:
Public Sub MarqueeFlash_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.TransparencyKey = Color.FromArgb(1, 4, 3)
Me.BackColor = Color.FromArgb(1, 4, 3)
dim FlashCtrl as As New AxShockwaveFlash
Controls.Add(FlashCtrl)
With FlashCtrl
.BGColor = Me.BackColor.R.ToString("X2") & Me.BackColor.G.ToString("X2") & Me.BackColor.B.ToString("X2")
.Movie = IndexedDR(0).Item("File")
.Location = New Point(10,10)
End With
FlashCtrl.Play()
FlashCtrl.Size = New Size(400,300)
end sub

Related

FlowLayoutPanel not showing more than one Control after it's cleared

My program automates a process on a website using selenium, HTTP requests, and an HTML parser known as HtmlAgilityPack.
There are parts of this process that require user input that can not be automatically filled out by hard-coded values. Allowing the user control over the website to fill in these inputs would be a mistake. It would be difficult to know when they are done inputting it and they would likely touch something they shouldn't which would cause errors when control of the website is handed back over to the program.
Instead, I download the page source of the website using selenium and parse the inputs out of the HTML with HtmlAgilityPack. Then controls matching those inputs are dynamically generated and added to a FlowLayoutPanel. The FlowLayoutPanel works correctly the first time. It displays all added controls. When the user is done they click on a button and the process continues.
Sometimes the process encounters errors that cause it to loop back to where the user needs to enter input again. The exact code that worked before is then run in the same subroutine again. It all runs without error and as expected. I have manually checked at runtime that the controls are added to the FlowLayoutPanel, that they have a size bigger than 0, 0, and that they are a visible color. Yet only one control ever shows up in the FlowLayoutPanel no matter how many should be visible.
The FlowLayoutPanel has it's AutoScroll property set to true and it has adequate space to add more controls. As I said this works fine the first time around just not the second. I've been stuck on this for a while and would appreciate some help. The code is going to be posted below for you to look at.
The code I am going to post has several FlowLayoutPanels. One that is on the Form permanently that was created in the designer and the others are generated dynamically to group up the controls.
The issue is with the permanent one. It shows one control as I said. This control is the first dynamically generated flow layout panel and all of it's children. It doesn't display any of the other FlowLayoutPanel controls that are added to it. Just whichever one is added first.
For those of you wondering about the line FLPOutOfStock.ImprovedClear() in the code bellow, The .Improved clear is an extension method I wrote. When Clearing the FlowLayoutPanel with the normal method, .Clear(), the controls get removed but they don't get disposed of. My method disposes of all the controls in the panel and then calls the Clear() method on the panel.
I realize that the Clear() method isn't necessary after they've been disposed of it's just a backup since nothing ever seems to work. I wanted to make sure the panel was fully reset.
Here is the code:
Private Sub UIOutOfStockState_Load()
Try
cmdOutOfStockDeleteAll.Enabled = False
cmdOutOfStockContinue.Enabled = False
FLPOutOfStock.ImprovedClear() 'The flowlayoutpanel that does not display all controls
With New WebDriverWait(ChromeDriver, TimeSpan.FromSeconds(20)).Until(Function(driver) CBool((CType(driver, IJavaScriptExecutor)).ExecuteScript("return jQuery.active == 0")))
End With
LBLOutOfStockErrors.Text = "Notice. The following items are out of stock. Please see below for product-specific availability dates. If you have any questions, please contact Customer Service at (800) 843-2020. All direct to patient orders will ship complete. The entire order will ship when out-of-stock product becomes available."
Dim OutOfStockDoc As New HtmlAgilityPack.HtmlDocument
OutOfStockDoc.LoadHtml(ChromeDriver.PageSource)
Dim OutOfStockProductNodes As HtmlAgilityPack.HtmlNodeCollection = OutOfStockDoc.DocumentNode.SelectNodes("//div[contains(#id,'id_detail_item_')]")
FLPOutOfStock.SuspendLayout()
If OutOfStockProductNodes IsNot Nothing Then
For Each OutOfStockProductNode As HtmlAgilityPack.HtmlNode In OutOfStockProductNodes
Dim FLPOutOfStockProduct As New FlowLayoutPanel
FLPOutOfStockProduct.SuspendLayout()
FLPOutOfStockProduct.FlowDirection = FlowDirection.LeftToRight
FLPOutOfStockProduct.AutoSize = False
FLPOutOfStockProduct.Size = New Size(420, 160)
FLPOutOfStock.Controls.Add(FLPOutOfStockProduct)
Dim WBProductText As New WebBrowser
WBProductText.Size = New Size(400, 120)
WBProductText.AllowNavigation = False
WBProductText.AllowWebBrowserDrop = False
WBProductText.IsWebBrowserContextMenuEnabled = False
WBProductText.ScriptErrorsSuppressed = True
WBProductText.ScrollBarsEnabled = True
WBProductText.Margin = New Padding(0, 0, 0, 0)
WBProductText.Padding = New Padding(0, 0, 0, 0)
WBProductText.Navigate("about:blank")
Dim ProductTextHtmlDoc As New HtmlAgilityPack.HtmlDocument
ProductTextHtmlDoc.LoadHtml(OutOfStockProductNode.OuterHtml)
ProductTextHtmlDoc.DocumentNode.SelectSingleNode("/descendant::a[#id='patient-outOfStock-delete-item']").Remove()
WBProductText.DocumentText = ProductTextHtmlDoc.DocumentNode.OuterHtml
FLPOutOfStockProduct.Controls.Add(WBProductText)
FLPOutOfStockProduct.SetFlowBreak(WBProductText, True)
Dim SpaceReducer0 As New Panel
SpaceReducer0.Size = New Size(0, 0)
FLPOutOfStockProduct.Controls.Add(SpaceReducer0)
Dim cmdProductDeleteButton As New Button
cmdProductDeleteButton.Text = "Delete"
cmdProductDeleteButton.BackColor = Color.White
cmdProductDeleteButton.ForeColor = Color.Black
cmdProductDeleteButton.Margin = New Padding(0, 0, 0, 0)
cmdProductDeleteButton.Padding = New Padding(0, 0, 0, 0)
cmdProductDeleteButton.Size = New Size(400, 20)
Dim OnClickAttributeValueWithQuoteEscaping As String = OutOfStockProductNode.SelectSingleNode("/descendant::a[#id='patient-outOfStock-delete-item']").GetAttributeValue("onclick", "")
cmdProductDeleteButton.Tag = "//a[#id='patient-outOfStock-delete-item' and (#onclick=""" & OnClickAttributeValueWithQuoteEscaping & """)]"
AddHandler cmdProductDeleteButton.Click, AddressOf cmdProductDeleteButton_Click
FLPOutOfStockProduct.Controls.Add(cmdProductDeleteButton)
FLPOutOfStockProduct.SetFlowBreak(cmdProductDeleteButton, True)
Dim SpaceReducer1 As New Panel
SpaceReducer1.Size = New Size(0, 0)
FLPOutOfStockProduct.Controls.Add(SpaceReducer1)
FLPOutOfStockProduct.ResumeLayout()
Next
FLPOutOfStock.ResumeLayout()
FLPOutOfStock.Refresh()
End If
cmdOutOfStockDeleteAll.Enabled = True
cmdOutOfStockContinue.Enabled = True
Catch Ex As Exception
cmdOutOfStockDeleteAll.Enabled = True
cmdOutOfStockContinue.Enabled = True
End Try
End Sub
So I’ve been asked to show what is in the improved clear method. Here it is:
<Extension()>
Public Function ImprovedClear(ByRef Control as Control)
For Each controlchild as control in control.controls
Control.Dispose()
Next
Control.Controls.Clear()
Return Nothing
End Function

VB.NET ClientSize

I have one form and I want it to be fullscreen, but taskbar should be still visible. And I want it to have one Panel on it, whose borders are 10px away from form borders
I tried hundreds of combinations, and I simply can't achieve this.
here's my code
Public Class Form1
Sub New()
InitializeComponent()
WindowState = FormWindowState.Maximized
Size = New Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height)
Dim p1 As New Panel()
p1.Location = New Point(10, 10)
p1.Size = New Size(ClientSize.Width - 20, ClientSize.Height - 20)
p1.BackColor = Color.Blue
Controls.Add(p1)
End Sub
End Class
what I want: http://i.imgur.com/4BxoBeh.png
what I get: http://i.imgur.com/QynIdaU.png
I would take an entirely different approach where there is no need to calculate anything:
WindowState = FormWindowState.Maximized
Size = New Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height)
Padding = New Padding(10)
Dim p1 As New Panel()
p1.Location = New Point(0, 0)
p1.Dock = DockStyle.Fill
p1.BackColor = Color.Blue
Controls.Add(p1)
Your calculation is correct for a form that takes entire screen but is not maximized, which you can see by unmaximizing it as soon as it appears. The reason is that you are observing the form sizes from the constructor which is a bit too early (namely, even though you are setting WindowState = FormWindowState.Maximized before everything else, ClientSize still has values corresponding to non-maximized window because the window has not yet been created and shown). If you move your original code to e.g. a Form.Load handler it will give the opposite result - looking correct when the form is maximized and incorrect if not.
The padding approach works as expected in all cases.

winforms: Slow performance on form load

I have a VB.NET winforms application. One of its forms, contains a flowlayoutpanel which I populate dynamically (programmatically) on form load event with pairs of label-textbox. My flowlayoutpanel is created in design time with all the properties set to default except below ones:
AutoSize: true
AutoScroll: true
Dock: fill
FlowDirection: TopDown
Then I populate it using below code within the form load event:
Private Sub MyForm_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Handles Me.Load
Dim lbl As Label
Dim txt As TextBox
Dim flowLayout As FlowLayoutPanel
Dim g As Graphics
For i As Integer = 0 To 253
lbl = New Label
lbl.Text = i.ToString("000") + ":"
lbl.Anchor = AnchorStyles.None
lbl.AutoSize = True
txt = New TextBox
txt.Text = "<" + i.ToString.PadLeft(3, " ") + ">"
txt.MaxLength = 5
txt.Anchor = AnchorStyles.None
txt.ReadOnly = True
g = txt.CreateGraphics
txt.Width = g.MeasureString(txt.Text, txt.Font).Width + 5
g.Dispose()
flowLayout = New FlowLayoutPanel
flowLayout.FlowDirection = FlowDirection.LeftToRight
flowLayout.AutoSize = True
flowLayout.Anchor = AnchorStyles.None
flowLayout.Margin = New Padding(0)
flowLayout.Padding = New Padding(0)
flowLayout.Controls.Add(lbl)
flowLayout.Controls.Add(txt)
Me.FlowLayoutPnl.Controls.Add(flowLayout)
Next
End Sub
As I have stated above FlowLayoutPnl is created on design time and components on this are added following TopDown flow direction.
Above code produces this result.
The problem here is that on opening this form it takes so much time (a few seconds) to open because it is doing all the stuff in form load event. It takes 35 seconds to open!. When all the stuff is done then form becomes visible after 35 seconds...
So I would like to know if there is some kind of method to speed up form load. I have read some posts here saying about implement and show some kind of splash screen while it loads indicating user that it is being loaded or even perform an asynchronous load. What about creating a background thread from form load event in order to do this stuff? Anyone could guide me in the right direction? A very little example will be highly appreciated. How this kind of problems are normally resolved?

DataGridView bound to DataTable is not showing

I am trying to show a DataGridView in a form that is bound to a DataTable, but it's not showing up. I was doing this using a C1TrueDBGrid and that was working...I decided to switch to using a DataGridView due to some complications with the TrueDBGrid. Can anyone help me figure out why nothing is showing?
In the form I declare these:
Public binData As DataSet
Friend WithEvents dgvData As System.Windows.Forms.DataGridView
The binData is filled with tables created via a separate calculation routine. Then this is the form load event:
'create a tab page and add data grid view for every table in the set
For i = 0 To binData.Tables.Count - 1
Dim tabPage As C1.Win.C1Command.C1DockingTabPage = New C1.Win.C1Command.C1DockingTabPage
tabPage.Text = binData.Tables(i).TableName
tabContent.TabPages.Add(tabPage)
Dim dgvData = New System.Windows.Forms.DataGridView
Dim binding As New BindingSource
binding.DataSource = binData.Tables(i)
With dgvData
.Dock = DockStyle.Fill
.AllowUserToOrderColumns = False
.AllowUserToAddRows = False
.AllowUserToDeleteRows = False
.DefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomLeft
.DataSource = binding
.AutoGenerateColumns = True
End With
tabPage.Controls.Add(dgvData)
Next 'DataTable In binData.Tables
When the form loads, the tab pages are there and labeled as expected, but they look empty (no table).
I did try instead setting the DataSource to the DataSet called binData (as opposed to a specific table), and then setting dgvData's DataMember property to the name of the specific table I want to display in it...that made no difference.
Note: I need to be able to do this programmatically at runtime as opposed to using the visual designer because I do not know the exact number of grids I need until the form loads with a particular dataset - the dataset it gets can have a different number of tables depending on what the user wants.
Here's some rough code to add dgvs to a flow panel:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Static dgvCount As Integer
dgvCount += 1
Dim dgvNew As New DataGridView
dgvNew.Width = DataGridView1.Width
dgvNew.Height = DataGridView1.Height
dgvNew.Name = "dgv" & dgvCount
' clone other properties as need
FlowLayoutPanel1.Controls.Add(dgvNew)
Debug.Print(FlowLayoutPanel1.Controls(FlowLayoutPanel1.Controls.Count - 1).Name)
End Sub
Starts with one dgv - DataGridView1 as the model for properties. Anchoring is not working in the flow panel so some custom code may be need to change width.
Flow panel doesn't scroll so may not be the best choice - look into TableLayout as a possibility. TabControl is another option.
OK, well it turns out there was nothing wrong with what I was doing. The issue turned out to be in one line of code that has nothing to do with binding the DGV's datasource or anything.
ComponentOne has a control called a ThemeController in which you can set themes for your forms and the controls within. I had a line of code to set the theme for dgvData to my default application theme (which sets visual style and details regarding colors, fonts, etc.). For whatever reason, THAT was rendering my grid non-visible. I will be logging a ticket with them.

DataGridViewButtonColumn icon

i am using vb.net 2.0 and i would like to set an icon or image in a DataGridViewButtonColumn. I know the class has no member for it. Anyone has an idea?
Best answer is from http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/b0dfb55c-8bad-4c2d-aa72-36d8c138484e/
But as usual, you Google vb.Net and get answers in C#. I use C# to vb.net tool on the developerfusionwebsite to help me convert to vb.net but usually end up changing a fair amount.
Once you have a pointer this one is quite easy really.
In the dataGridView_CellPainting event add something like this
Private Sub InvoiceLinesDataGridView_CellPainting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles InvoiceLinesDataGridView.CellPainting
If e.ColumnIndex = 3 AndAlso e.RowIndex >= 0 Then
e.Paint(e.CellBounds, DataGridViewPaintParts.All)
Dim bmpFind As Bitmap = My.Resources.binoc16_h1
Dim ico As Icon = Icon.FromHandle(bmpFind.GetHicon)
e.Graphics.DrawIcon(ico, e.CellBounds.Left + 3, e.CellBounds.Top + 3)
e.Handled = True
End If
End Sub
Just to explain this a little, I wanted to use a resource which is a bitmap so I am converting that to an icon also. This works really well for me and I get a proper button column with an image. The column index is a bit rough as that could change so I was looking to refer using the column name - shouldn't be too hard but you get the idea. SO much easier than the other options I have see around that get you making an extended custom column type.
This really should have just been part of the original control and I cannot fathom why MS crippled the grid so much. I have been trying to use third party controls like Telerik but the originals always seem to be more stable so am now seeing if I can stick with vanilla controls and adding my on extensions where required.
I created a method that can be called in the CellPainting datagridview event.
Public Shared Sub SetImageToDataGridViewButtonColumn_CallInCellPaintingEvent(ByRef img As Bitmap, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs)
e.Paint(e.CellBounds, DataGridViewPaintParts.All & (DataGridViewPaintParts.ContentBackground) & (DataGridViewPaintParts.ContentForeground))
Dim destRect As Rectangle = New Rectangle(e.CellBounds.X + (e.CellBounds.Width - img.Width) / 2, e.CellBounds.Y + (e.CellBounds.Height - img.Height) / 2, img.Width, img.Height)
Dim srcRect As Rectangle = New Rectangle(0, 0, img.Width, img.Height)
e.Graphics.DrawImage(img, destRect, srcRect, GraphicsUnit.Pixel)
e.Handled = True
End Sub
In the CellPainting event, call this method passing the image you want on the button and e. Ensure you use some sort of condition to set on the column you need, this example the If specifies column 0. Also notice I have my image in My.Resources:
Private Sub dgv_CellPainting(sender As Object, e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles dgv.CellPainting
If (e.ColumnIndex = 0 And e.RowIndex >= 0) Then
SetImageToDataGridViewButtonColumn_CallInCellPaintingEvent(My.Resources.myImg, e)
End If
End Sub
Tips: I found 16x16 png were perfect for my use. You can resize using http://images.my-addr.com/resize_png_online_tool-free_png_resizer_for_web.php
You can try using a DataGridViewImageColumn add attach an event to the grid's CellContentClick event (in the event process only the events comming from the column/columns that is/are images)