Visual Studio 2010,
Visual Basic .NET
I have a form (frmImages) that opens when an image is clicked on inside a WebBrowser (wbContent) contorl on a form (frmContent).
I want the user to be able to click multiple images and open multiple instances of frmImages.
UPDATE
Here is what I am working with now, am I heading in the right direction?
This gives me the ability to open multiple instances but opens a duplicate. So for every image I click on, two identical forms open.
Dim images As New frmImages
If engineLine.IndexOf("\") <> -1 Then
images.wbImages.Navigate(New Uri(engineLine & holdHTML))
Else
images.wbImages.Navigate(New Uri(filePath & "IETMS\" & engineLine & "\" & engineLine & holdHTML))
End If
images.Text = ietmSelect & " - " & workPacket & " - " & removeTitleLinks(figTitle)
images.Show()
You just need to create another instance of the form (NEW). Of coarse, your form cannot be modal or else they will never be able to access the parent form to click another image.
Dim x as new frmImages
x.show
x = new frmImages
x.show
Create all your form instances explicitly, especially when you want more than one instance of a form. In your example, you are creating one explicitly (frmImages2), but also using the VB default instance. VB allows you to use the name of the form class as a default instance, but this is a bad practice (and a bad feature - but VB is designed around making it easier for very junior programmers even if it makes it more confusing for all the rest).
Related
I'm trying to get started with my first add-in for Autodesk Inventor, and of course, I'm starting from an existing sample to make this task easier for a newbie like me.
I have a decent command of VB.NET, but I cannot understand what's going on here.
In this link: https://drive.google.com/drive/folders/1rs2zVzf8Ib8iwd8JjCWZ-KQbWJUAqFyJ?usp=sharing
There are two ZIP files with VS2019 Solutions:
This_Sample_Works.zip - I used this as the baseline for my new project
This_Sample_Does_Not.zip
In both, there is this line of code:
dc.Show(New WindowWrapper(ThisApplication.MainFrameHWND))
But it only compiles in the project This_Sample_Works.zip - In the project within This_Sample_Does_Not.zip, I get the error in the image below.
Frankly, I'm not even asking someone to fix it for me. I just wanted to understand why it works in one project and not in another, despite the code being virtually the same.
What is bugging me is what piece of information/skills I currently don't have to understand what the compiler is telling me.
Public Function CreateChildDialog() As Long
CreateChildDialog = Nothing
Try
'Dim dc As Object
If Not dc Is Nothing Then
dc.Dispose()
dc = Nothing
End If
dc = New dockable_form(ThisApplication)
dc.Show(New WindowWrapper(ThisApplication.MainFrameHWND))
MsgBox("Handle ID:" & dc.Handle.ToInt64(), MsgBoxStyle.OkCancel, "Debug Info")
Return dc.Handle.ToInt64()
Catch ex As Exception
MsgBox("There is problem in CreateChildDialog" & vbCrLf & vbCrLf & ex.Message & vbCrLf & vbCrLf & ex.StackTrace & vbCrLf & vbCrLf & ex.ToString)
End Try
End Function
Any help is welcome - Thanks in advance!
In your project This_Sample_Does_Not the class dockable_form is a Control (the class inherits from System.Windows.Forms.UserControl).
In the reference project This_Sample_Works the class form_dockable is a Form (the class inherits from System.Windows.Forms.Form).
The two are very different types, though a Form can behave like a Control, the opposite is not true. A control will need a containing form.
Thus, the Control does not have a Parent that can be assigned when the method Show is called, it already has a parent.
From MSDN - Control.Show Method
Showing the control is equivalent to setting the Visible property to true. After the Show method is called, the Visible property returns a value of true until the Hide method is called.
Questions for your final preferred solution:
Do you really want to create a Control that is placed on another form? or
Do you want a Form that can be shown or popped up as required?
Driving me bonkers...
The problem is one of speed.
I have a working SQL Server linked to a client accessible website, which I am wanting to add an Access front end to enable us office bound staff to better support both client and field staff.
The current form I have constructed is a main form with five sub forms contained within it, giving us all the relevant client information in one view. This works however is taking 24 seconds to load a single clients complete records.
I have looked at the SQL Server and found the absence of indexes, fixed this and got the time down to 24 seconds with consequent loads closer to 18 seconds depending on the client (some have a lot more records). This might be okay, as whilst this is a relative eternity in computing time in real world time its okay...but not great. I would like to see if I can get a better load by changing the way I connect and how the form is bound to the records etc.
In looking at the various ideas and reading a lot I found:
https://learn.microsoft.com/en-us/office/vba/access/concepts/activex-data-objects/bind-a-form-to-an-ado-recordset?source=docs
Which appealed to me as I am more inclined to use ADO, seldom if ever to I use DAO. ADO I understood originally was intended to use with SQL and so on, and it seems like a sensible idea.
Again as I understand it if I can get this to work it will act as a pass through query returning only one record over the net and should consequently speed my form up considerably. However it wont work.
My code is:
Private Sub cssSetForm(lngID As Long)
Dim cnn As New ADODB.Connection
Dim Rs1 As New ADODB.Recordset
Dim strSQL As String
Dim strR As String
cnn = "Provider=MSOLEDBSQL;Server=Server;Database=DatabaseName;UID=UserName; PWD=Password;"
cnn.Open
strSQL = "SELECT Clients.Clientid, Clients.AccountContact, Clients.AccountEmail, Clients.Address, Clients.Name, Clients.OfficePhone, Clients.PostCode, " & _
"Clients.ShentonAcc, Clients.Suburb FROM Clients WHERE (((Clients.Clientid)=" & lngID & "));"
With Rs1
Set .ActiveConnection = cnn
.Source = strSQL
.LockType = adLockPessimistic
.CursorType = adOpenKeyset
.Open
End With
Debug.Print Rs1.RecordCount
Me.Recordset = Rs1
End sub
Now I am getting no errors until Me.Recordset=rs1 which is generating an error 3251 Operation is not supported for this type of object which is very nice for someone that understands why this is not supported when it is no different than I can see to the example I was copying from.
I don't understand why the form I am working on doesn't support recordsets according to the error message? Is there an error in my code? Is the error in my understanding of the destructions from the linked site? Is the error something else?
Thanks for the help
Well, loading up 5 sub forms is a lot of data pulling. converting to ado reocdsets is NOT going to speed this up.
What you want to do here is NOT load up the sub forms until such time the user say clicks on the appropriate tab to load the one given sub form.
As long as the form in question is opened with a were clause, then the one main form will ONLY pull the one main record from sql server. So doing all kinds of fancy reocrdsets etc. will gain you next to nothing. So, always - but always launch your main form to the one record. If that main form is bound to a table of 5,000 rows, or 1 million rows, it will load instant despite the fact that the form is bound directly to the linked table with 1 million rows.
With this one main form, you edit or do whatever, and then close it. You are then of course right back to the search form/prompt you have to ask the user what reocrd to work on. So, how a accouting package works, or even google? You search, display the search resutlts and pick ONE thing to view. This approach should get your main form load down to about 1 second. Again, just use the "where" clause when you open that form:
eg:
dim strInv as string
strInv = InputBox("Enter invoice number to view")
docmd.OpenForm "frmInvoice",,,"InvoiceNum = " & strInv
Of course the above is air code, and you will likely build some search form say like this:
So in above, the user types in a bit of the name. We then fill the form with a simple where clause, or
me.MySubForm.RecordSource = "select * from tourCust where LastName like '" & sTextbox & "*'"
When a user clicks on the glasses icon to edit + view the ONE row, we use this:
docmd.OpenForm "frmDetails",,,"id = " & me!id
Again, all bound forms, and dispite the tables having 500,000+ rows, the loading of the forms is instant - even when the back end is SQL server.
So, adopt a prompt + search results + edit/view design pattern. EVERY single software system has this loop or design pattern. Not only is it user friendly, it also performs well since access DOES NOT pull the whole table, but ONLY the reocrds you tell the form to load by using the where clause as per above.
Now, for the child forms (sub forms).
As noted, don't load them until the user actually clicks on the given tab.
So, in the on-change event of the tab, you can go:
If Me.TabMainpage.Pages(Me.TabMainpage).Name = Me.pgeDocs.Name Then
'' the tab been changed to show past tours
dim strSQL as string
strSQL = "select * from tblPastTours where tour_ID = " & me!ID
me.
' dynamic load the sub form
If Me.frmSubPastTours .SourceObject = "" Then
Me.frmSubPastTours.SourceObject = "Forms.frmPastTours"
End If
' now load sql into form
me.frmSubPastTours.Form.RecordSource = strSQL
The above is mostly air code, but the idea here is:
don't load the sub form until you need to.
OR YOU can have the sub form load, but leave its RecordSource blank and STUFF in the sql you need for display WHEN you click on the tab.
It is possible that you need all sub forms to display. You could thus leave all sub form RecordSource blank, and then it the main form on-load event, simply stuff in the sql to each sub form. This might improve speed a bit, and with your slower connection this would be the least amount of work.
You "fail" to mention how you launch + load the main form, but as noted, it should be opend to the ONE reocrd. The link master/child pulling of data can be bit slow, and I can't say JUST using the above sql stuff into those forms will help a lot. I would try that first as it is the least amount of work. If load time is still too slow, then placing te sub forms behind a tab control and ONLY loading the sub form, and then setting the datasource will be the fastest.
Attempting to build all those recordsets, and then bind them to a form? It not speed things up, and just shoving a sql string into the form (or sub form) recordSource amounts to really the SAME thing and same performance anyway. So, you save tons of work and code, and quite much the above idea not only applies to sql server back ends, but we all VERY often dynamic load sub-forms and don't load them until such time you view the sub form say behind a tab control.
I have a form in MS Access (365) which accepts various selection criteria and runs a report with those criteria built into the wherecondition of a DoCmd.OpenReport command. The report is run via a button with On Click VBA code, since the wherecondition has to be built according to which, if any, criteria have been chosen. That all works fine when I open the selection criteria form directly. I want to open the selection criteria form via a navigation form, since there will be other, similar reports with selection criteria that I want to run from within the same navigation form.
As stated above, everything works when I open the selection criteria form directly and run the report but when I tried it via a navigation form, it didn't work. That's ok, I found a solution on the MS Dev Center site which works when I run the selection criteria form (and then the report) from the navigation form. All fine. But then (of course) the references within the button On Click code don't work when I open the selection criteria form directly and run the report. I would like to be able to run the selection criteria form and then the report from both positions - directly from MS Access and via the navigation form. There will presumably be some way to achieve this but (as I said above, I am new to MS Access and VBA) I could spend a lot of time clutching at shadows. Hopefully, someone will be able to tell me the simplest way to do this?
Code sample with relevant comments below. On runnning the selection criteria form and report directly, the line commented as AAA works ok, MsgBox ABB and DDD and those beyond all show; on running them via the navigation form, line BBB works ok, MsgBox ABB and DDD and those beyond all show (well, they would except that I haven't yet coded the [NavigationSubform] option into all the other whereconditon building stuff). When I switch the lines AAA and BBB (ie, comment the other one out) MsgBox AAA show ok, then it fails with:
Can't find referenced form "frmSelectSpeciesSiteDates"
before reaching MsgBox DDD.
MsgBox "ABB"
'If Not Forms![frmSelectSpeciesSiteDates]![cboCommonName] = "" Then
' AAA Works when frmSelectSpeciesSiteDates is run directly
If Not Forms![frmNavSelectiveReports]![NavigationSubform].[Form]![cboCommonName] = "" Then
' BBB Works when frmSelectSpeciesSiteDates is called from a navigation form
strWhereCondition = strWhereCondition & "[common name] = " & Chr(34) & Me![cboCommonName] & Chr(34)
End If
MsgBox "DDD"
You have a form named frmSelectSpeciesSiteDates which has a combobox named cboCommonName. The form also includes VBA code which uses the combobox value to modify a string variable ...
strWhereCondition = strWhereCondition & "[common name] = " & Chr(34) & Me![cboCommonName] & Chr(34)
However you only want to modify the string when the combobox contains something other than an empty string. And that is where you're struggling. You reference the combobox one way when the form is opened directly as a top-level form, and another way when it is contained in a navigation form ...
Forms![frmSelectSpeciesSiteDates]![cboCommonName]
Forms![frmNavSelectiveReports]![NavigationSubform].[Form]![cboCommonName]
I suggest you abandon both of those and refer to the combobox the same as where you modify the string (Me!cboCommonName) ...
If Not Me!cboCommonName = "" Then
strWhereCondition = strWhereCondition & "[common name] = " & Chr(34) & Me!cboCommonName & Chr(34)
End If
I'm looking for a way to hide the standard Home tab on the ribbon in my Access 2016 application. I would like to do this from VBA. Hiding the complete ribbon isn't an option. I've tried to do this using the commandbars-collection, but without any positive results.
Consider using the Application.LoadCustomUI method but the process is a little involved on initial setup. Below are the directions and the same steps when creating new custom tabs:
Create or load the custom UI xml (a well-formed xml document) and then pass it as a string to method, giving the ribbon a name such as HideHome:
Public Function CustomRibbon()
Dim customXML As String
customXML = "<customUI xmlns=""http://schemas.microsoft.com/office" _
& "/2009/07/customui"">" _
& " <ribbon startFromScratch=""false"">" _
& " <tabs>" _
& " <tab idMso=""TabHomeAccess"" visible=""false"" />" _
& " </tabs>" _
& " </ribbon>" _
& "</customUI>"
Application.LoadCustomUI "HideHome", customXML
End Function
Call this function or subroutine in an OnOpen or OnLoad trigger event of opening form or in a macro named AutoExec. This step is important as you cannot re-load or change the ribbon once it is visible else an error will emerge so be sure it is part of opening automation.
The very first time you open database, nothing will happen because you must first select the created ribbon under options. After first opening database with above first two steps handled, under File / Options / Current Database, scroll down to Ribbon and Tab Options, select your new ribbon name (the one created and named in Step #1) in drop down field.
Close and re-open the database and Home tab should no longer be visible on ribbon. Going forward in changing the same named ribbon, you can skip 3.
**I know above steps works for MS Access 2007-2013, hopefully more or less the same in 2016.
I just started to study Visual Basic .NET. I would like to build a dynamic system log text box.
When program is passing one point of code or function, a textbox in another form is updating with the system log.
For example, when the program starts, it appends "System start" to the textbox in another form. When the program starts to use the "cal" function, then the program appends "System: start to cal data" on the textbox in another form.
However, I am not really sure how to update this system log dynamically. Do I need to use threading? Can I do it without threading? Can anyone give me an example?
To add to Mertis's suggestion, what you can do is to fire a code which concatenates details to your textbox whenever an object is called/code is executed
for example, a function was executed:
Function sampleFunc()
.....
Textbox1.text = Textbox1.Text & vbnewline & DateTime.Now & _
" a Function was Executed"
End Function
Note that I added a datetimenow, in case you needed time details.