I am not aware of any issues in setting this property. I suspect that any issues you had in Excel VBA may have involved a registry value getting changed when you set a property, but that's just a guess. I normally enable script error suppression at the design level.
As these are errors are typically generated by bad java script code, thus supressing them should not be an issue. However, this little tidbit from MS makes me wonder.
When ScriptErrorsSuppressed is set to true, the WebBrowser control hides all its dialog boxes that originate from the underlying ActiveX control, not just script errors. Occasionally you might need to suppress script errors while displaying dialog boxes such as those used for browser security settings and user login. In this case, set ScriptErrorsSuppressed to false and suppress script errors in a handler for the HtmlWindow.Error event. For more information, see the code example in this topic.
See this for more info.
I also get browser errors regarding javascript and I don’t know how to handle that within the confines of VB.NET’s WebBrowser. As it is, I have to manually stop it from running or don’t, it doesn’t matter with regards to the query but it does stop my code at the DocumentCompleted event.
I don't know if you are aware of this or not, but when navigating to a given Url, you will likely get multiple "DocumentCompleted" events fired. The way to handle this is:
Private …
I do not use WPF much, but I believe the "IsHitTestVisible" property is the one that you want to set to false and not the "IsEnabled" property.
Sub SetVisibility()
Dim i As Int32 = 1
CType(Me.FindName("Button_" & i.ToString), Control).Visibility = Windows.Visibility.Hidden
End Sub
This may help with the script errors issue. Set the "ScriptErrorsSuppressed" property on the WebBrowser control to True. That will prevent the error dialog from opening.
I'm not sure about how you select the image to place in "pBox", but I think this will give you the effect you are seeking.
Private TrackedPB As PictureBox
Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles PictureBox1.MouseDown
If e.Button = Windows.Forms.MouseButtons.Left Then
' Left Button Down
' Using this function allows you to drag over existing
' PictureBoxes added to PictureBox1
Dim loc As Point = PictureBox1Coord(sender, e)
' set the image however you want
Dim pBox As New PictureBox With {.Image = My.Resources.SomeImage, _
.Location = loc, _
.Size = New Size(64, 64), _
.BorderStyle = BorderStyle.FixedSingle, _
.SizeMode = PictureBoxSizeMode.Zoom, _
.Parent = PictureBox1 _
}
TrackedPB = pBox
TrackedPB.BringToFront() 'Make sure this new PB is on top
' Need to wire-up the MouseDown and MouseMove Events for the
' added PB to allow drag over and click
AddHandler TrackedPB.MouseDown, AddressOf PictureBox1_MouseDown
AddHandler TrackedPB.MouseMove, AddressOf PictureBox1_MouseMove
End If
End Sub
Private Function PictureBox1Coord(ByVal sender As Object, ByVal e As MouseEventArgs) As Point
If CType(sender, PictureBox).Equals(PictureBox1) Then
Return e.Location
Else
Return PictureBox1.PointToClient(CType(sender, PictureBox).PointToScreen(e.Location))
End If
End Function
Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
If TrackedPB IsNot Nothing AndAlso e.Button = Windows.Forms.MouseButtons.Left Then
TrackedPB.Location = PictureBox1Coord(sender, e)
Else
TrackedPB = Nothing
End If
End Sub
Try changing: MainForm.WebBrowser1.DataBindings.Add("Url", ds.Tables("item"), "link")
To: MainForm.WebBrowser1.DataBindings.Add("Url", ds.Tables("item"), "link", True)
This enables formatting of the value which invokes the property's TypeConverter.
I'm freehanding these modifications to add the count field, but I sure that you will let me know if it throws an error. ;)
Select DTRow(grpDT, _
New Object() {LINENAME, _
New TimeSpan(CType( _
grp.Average(Function(r2 As DataRow) TimeSpan.Parse(r2.Field(Of String)("EVENTTM")).Ticks), _
Int64 _
) _
), _
grp.Count() _
} _
)
Now you need to make room for the count in the datatable.
Dim grpDT As DataTable = Ds.Tables(0).Clone 'Copy structure of original Table
'Make the changes you indicated to the Table structure. You can do this as long as the table is empty.
grpDT.Columns("EVENTTM").DataType = GetType(TimeSpan)
grpDT.Columns("EVENTTM").ColumnName = "DURATION"
' ******** Column to hold Count
grpDT.Columns.Add("Count", gettype(Int32))
As far as examples of LINQ go, there are a lot of them out there.
Just search:
- MSDN LINQ VB 101 Examples
- MSDN IEnumerable LINQ extensions
- MSDN IEnumerable
Unfortunately, MS created an abomination called the anonymous type in some perverted effort to make writing LINQ queries simpler. If you read some of their BS, they will claim that you have to use the Anonymous type to hold the result. This is total misinformation and they can not even keep their own ranks in line as many of them write LINQ examples, as I have shown you, using a strongly typed target variable. This is a somewhat of a style preference, but to use the anonymous type you have to have Option Infer On, and this goes against my personal philosphy. I believe code should explicitly …
I had merged the Date.Add into the LINQ. This should work.
Select DTRow(grpDT, _
New Object() {LINENAME, _
New TimeSpan(CType( _
grp.Average(Function(r2 As DataRow) TimeSpan.Parse(r2.Field(Of String)("EVENTTM")).Ticks), _
Int64 _
) _
) _
} _
)
So what you want is the the arithetic mean (average) of the timespan values? This can be done using the "Average" function instead of the "Sum" function. However the "Average" function will return a value of type "Double" and the TimeSpan constructor takes a "Int64" type, so a type conversion is needed as well.
Change:
Select DTRow(grpDT, _
New Object() {LINENAME, _
myToday.Add( _
New TimeSpan( _
grp.Sum(Function(r2 As DataRow) TimeSpan.Parse(r2.Field(Of String)("EVENTTM")).Ticks) _
) _
) _
} _
)
to:
Select DTRow(grpDT, _
New Object() {LINENAME, _
myToday.Add( _
New TimeSpan(CType( _
grp.Average(Function(r2 As DataRow) TimeSpan.Parse(r2.Field(Of String)("EVENTTM")).Ticks), _
Int64 _
) _
) _
) _
} _
)
You will probably need to go one level lower in the event order; that is why I suggested the KeyDown event. You may need to use the PreviewKeyDown event and set the IsInputKey property.
Sorry, but our required compliance with the guidelines of the National Organization for Computer Homework Excellence Authorization Treaty prevents us from providing you the information you are requesting.
Do you have the C# Code? If so, you could reconfigure it as class library and call the download method.
If not, there are two options: 1) Process.WaitForExit and 2) The Process.Exit event.
http://msdn.microsoft.com/en-us/library/fb4aw7b8.aspx
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.exited.aspx
Next time you have the urge to make a post similar to this, try sites like these:
I glad that you have it working. :))
First, regarding the timespan. From the result that i get, total sum that is more than 24 hours will be converted to 1 day, for example: 1.03:04:49.
How can I change the day to 24 hours like 1.03:04:49 will become 27:04:49. Is it possible to do like that?
Yes. There are two ways that I know of to do this. Here is the simplest one.
Private Sub Chart1_FormatNumber(ByVal sender As Object, ByVal e As System.Windows.Forms.DataVisualization.Charting.FormatNumberEventArgs) Handles Chart1.FormatNumber
If sender Is Chart1.ChartAreas("Fred").AxisY OrElse TypeOf sender Is System.Windows.Forms.DataVisualization.Charting.DataPoint _
AndAlso e.ValueType = ChartValueType.DateTime Then
' recreate original TimeSpan
' Remember that the Chart control uses OADates
Dim ts As TimeSpan = DateTime.FromOADate(e.Value).Subtract(myToday)
e.LocalizedValue = Trim(String.Format("{0,4:##00}:{1,2:00}:{2,2:00}", _
(ts.Days * 24) + ts.Hours, _
ts.Minutes, _
ts.Seconds) _
)
End If
End Sub
Second, how can i set the Y-Axis to become larger so that the total hour can see clearly
First off, you could make the size of the control taller. There are several values you can set regarding the interval to display less info if that is what you mean. Here is an extend section of what I showed earlier. Its best to play with these and see if you like the results. Normally, I would recommend looking at the documentation, but is this case that is an almost useless activity.
' Setup the chart
With Chart1
'.Dock = DockStyle.Fill
.DataSource = dt
.Legends.Clear() …
Hi lulu:
The following example is for a WinForm, but I believe the charting control works the same for the a Web app.
You need to first convert the Timespan to a datetime value to chart it, but I guess you already discovered that. ;)
The problem then becomes one of formatting the Y-axis. Not too hard, but it can be confusing. Give this a try on a new WinForm project to which you have added a single chart control to the form.
Imports System.Windows.Forms.DataVisualization.Charting
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' Make some data
Dim dt As New DataTable
Dim r As DataRow
With dt
.Columns.Add("Label", GetType(String))
.Columns.Add("TS", GetType(TimeSpan))
r = .NewRow : r(0) = "A1" : r(1) = TimeSpan.Parse("0.00:45:00") : .Rows.Add(r)
r = .NewRow : r(0) = "A2" : r(1) = TimeSpan.Parse("1.01:00:00") : .Rows.Add(r)
r = .NewRow : r(0) = "A3" : r(1) = TimeSpan.Parse("0.06:00:00") : .Rows.Add(r)
r = .NewRow : r(0) = "A4" : r(1) = TimeSpan.Parse("0.12:45:00") : .Rows.Add(r)
End With
' Add a DateTime Column
dt.Columns.Add("ChartTime", GetType(DateTime))
' Now for the real work!
' I use "Today" as the base date. In a perfect world we could do:
'For Each r In dt.Rows
' r("ChartTIME") = New DateTime(CType(r("TS"), TimeSpan).Ticks)
'Next
' but the chart control uses OLE Automation dates and they use a
' different time basis than .Net Dates.
' set a temp Today to prevent the unlikely case the the day changes while executing …
Performing computions on TimeSpan and DateTime types are two areas that the DataTable class does not support very well.
That said, you are left to process the rows yourself in code.
Here are two options, both of which entail creating an array of resultant rows that can then be added to a new DataTable
You could iterate through the table and create a list of unique LINENAME's and then do a DT.Rows.Select to pull those rows. You would then need to iterate through the returned rows and perform the summation. Then this result would be converted into a new DataRow and stored in an Array of DataRows.
Not difficult to do and it is easy to follow the code logic.
The second option essentially does the above, but uses a LINQ query on the DataTable to group and compute. These can be compact statements, but are confusing to those who do not use them very often. This will return an IENumerable(Of DataRow) that can then be iterated through and added to a DataTable.
I am going to show the LINQ method.
For your particular problem, we need to deal with the TimeSpan structure. To get a value that can be summed, I use the "Ticks" property and sum that value.
The method shown below handles the conversion the string TimeSpan value directly. No need for the TimeSpan conversion sterp that you showed.
As I do not do webpages, I have written and tested this in a WinForm project. You …
You are adding parameters that may not exist in the command string.
INSERT INTO [Customer] (Company, Business_Phone, Home_Phone, Mobile_Phone, Fax) VALUES (@CMPNY, @BUSPH, @HOMPH, @MBLPH, @FAXNM)
In this case you will have parameters for Last_Name and First_Name that are empty. I believe that the parameters must be in the order requested as it doe not do a look-up of the provided parameters.
I have restructured your code and eliminated some unnecessary functional but confusing code.
Dim custstr As String = "INSERT INTO [Customer] ("
Dim valuestr As String = ") VALUES ("
Dim custcmd As New OleDbCommand()
Dim txt As String
txt = txt_company.Text
If Not String.IsNullOrEmpty(txt) AndAlso txt.Trim.Length <> 0 Then
custstr &= "Company"
valuestr &= "@CMPNY"
custcmd.Parameters.AddWithValue("@CMPNY", txt_company.Text)
End If
txt = txt_lastname.Text
If Not String.IsNullOrEmpty(txt) AndAlso txt.Trim.Length <> 0 Then
custstr &= ", Last_Name"
valuestr &= ", @LSTNM"
custcmd.Parameters.AddWithValue("@LSTNM", txt_lastname.Text)
End If
txt = txt_firstname.Text
If Not String.IsNullOrEmpty(txt) AndAlso txt.Trim.Length <> 0 Then
custstr &= ", First_Name"
valuestr &= ", @FSTNM"
custcmd.Parameters.AddWithValue("@FSTNM", txt_firstname.Text)
End If
txt = txt_busphone.Text
If Not String.IsNullOrEmpty(txt) AndAlso txt.Trim.Length <> 0 Then
custstr &= ", Business_Phone"
valuestr &= ", @BUSPH"
custcmd.Parameters.AddWithValue("@BUSPH", txt_busphone.Text)
End If
txt = txt_homephone.Text
If Not String.IsNullOrEmpty(txt) AndAlso txt.Trim.Length <> 0 Then
custstr &= ", Home_Phone"
valuestr &= ", @HOMPH"
custcmd.Parameters.AddWithValue("@HOMPH", txt_homephone.Text)
End If
txt = txt_mobilephone.Text
If Not String.IsNullOrEmpty(txt) AndAlso txt.Trim.Length <> 0 Then
custstr &= ", Mobile_Phone"
valuestr &= ", @MBLPH"
custcmd.Parameters.AddWithValue("@MBLPH", txt_mobilephone.Text)
End If
txt = txt_fax.Text
If Not String.IsNullOrEmpty(txt) AndAlso txt.Trim.Length …
You may want to review this article.
http://www.codeproject.com/Articles/3467/Arrays-UNDOCUMENTED
I also remebered reading somewhere that the outermost dimension should be iterated before the inner ones. If I recall correctly, it has something to do with the layout in memory, but don't quote me on that.
I ran a test case of your original versus flipping the iteration sequence and it made a big improvement. I also tried using jagged arrays as mentioned in the article.
On my test system Vista32, VS2008, the jagged array (modified iterator sequnce) had the best performance. Approx 35% of original time.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
public Form1()
{
InitializeComponent();
if (System.Diagnostics.Stopwatch.IsHighResolution)
{
Console.WriteLine("Operations timed using the system's high-resolution performance counter.");
}
else
{
Console.WriteLine("Operations timed using the DateTime class.");
}
}
int iterations = 100;
private void button1_Click(object sender, EventArgs e)
{ // original
button1.Enabled = false;
GC.Collect(); // just for performance testing
sw.Reset();
sw.Start();
double[,] Redmap = new double[640, 480];
double[,] Greenmap = new double[640, 480];
double[,] Bluemap = new double[640, 480];
double[,] Redmap2 = new double[640, 480];
double[,] Greenmap2 = new double[640, 480];
double[,] Bluemap2 = new double[640, 480];
for (int i = 0; i < iterations; i++)
{
for (int y = 0; y < 480; y++)
{
for (int x = 0; x < 640; x++)
{
Redmap2[x, y] = Redmap[x, y] * 2;
Greenmap2[x, y] = Greenmap[x, y] …
Hiba,
No offense intended, but the DataGridView control is really intended as a viewer for data in a tabular format and not as a spreadsheet. It would be better to handle these calculations in the backing data storage. Even if the data is not pulled from a database, it is much easier to create a datatable with a computed column and set the DGV's datasource to your created table.
Let's assume you are using a database for that you have created a dataset for through the designer. We will edit the datasource. This is just a simple Access DB that I created, but the type of database is irrelevant.
Now we are going to add a new column to hold the result of multiplying "Hours_Worked" by "Rate". We will name this column "Cost".
Go to the properties for "Cost" and set its DataType to decimal.
Ok, now we have cost column in the dataset, however it does not exist in the database. We will create it in our fill query.
Click the "Next" button until you reach the Sql screen.
We will edit the "Select" statement to add the "Cost" column
Hours_Worked * Rate As Cost
Click "Next" and give a name for the two methods.
The richtextbox uses chr(10) (VBLf) to designate a new line. So if that is working, then check for VBLf (this is a VB character constant).
On non-Unix systems, the System.Environment.NewLine is a two character string equivalent to chr(13) & chr(10). You could also use the VB constant VBCrLf for this.
What is it that you are trying to accomplish? There are most likely other methods that could be suggested.
I am going to assume that you mean adding a video to the embedded resources.
From the menu, goto Project->Properties. Then select the "Resources" tab. Next Select "Add Rersource"->"From Existing File". You can then select your video file. The file will be inserted with the File Name minus the extension as a binary array.
As far as I know, the media player control can only except a file reference to play. Therefore, you will need to write the binary array to a temporary file first.
Private TmpFiles As New List(Of String)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim fi As New IO.FileInfo(IO.Path.GetTempFileName())
Dim tmppath As String = IO.Path.GetTempFileName()
' The tmp file will have a ".tmp" extension
' The media player uses the extension to identify the proper codec to use to decode the file
' I used a wma video, so I will change the extension to that
tmppath = tmppath.Replace(".tmp", ".wma")
' Create the file and write the resource array to it
Dim tmp As IO.Stream = IO.File.Create(tmppath)
' Amanda is the name of my file
tmp.Write(My.Resources.Amanda, 0, My.Resources.Amanda.Length)
tmp.Close()
'Save a reference to tmp file so that you can delete it on the Form.Closing event
TmpFiles.Add(tmppath)
' tell the player to play the file
WMP1.currentMedia = WMP1.newMedia(tmppath)
End Sub
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
For Each file As String In TmpFiles
Try
IO.File.Delete(file)
Catch ex As Exception
''
End Try
Next
End Sub …
kRod,
First off, GREAT JOB!!!!!
Two minor things in your code.
You declare and set "maxSize", but it is never used in your logic. Just delete all references to it.
You use GetNextControl. This is a tricky function to use and I wish MS would reroute people to SelectNextControl as that is what most people really want anyways.
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.selectnextcontrol.aspx
Your code is fine as is, but I took the liberty to convert it to a custom control for you and to show a different style of handling the keypress event. This will also show you how to use the SelectNextControl function. Just add this class to your project and rebuild it. If you have the default settings for Visual Studio, you should see it show up in your toolbox.
Public Class kRodsTB
Inherits System.Windows.Forms.TextBox
Public Sub New()
Me.MaxLength = 10
End Sub
Public Shadows Property MaxLength() As Int32
Get
Return MyBase.MaxLength
End Get
Set(ByVal value As Int32)
If value = 4 OrElse value = 10 Then
MyBase.MaxLength = value
Else
Throw New ArgumentException("MaxLength must be either 4 or 10")
End If
End Set
End Property
Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)
' The "Select Case" block processes the conditions in the order written
' and allows (IMO) easier reading and segmentation of the conditional logic
Select Case e.KeyChar
Case Chr(Keys.Enter)
'If only a decimal point is in the box clear TextBox
If Me.TextLength = 1 And (Me.Text = "." Or Me.Text = "-") Then Me.Clear() …
Just food for thought, but why not impliment the API function CopyFileEx? http://msdn.microsoft.com/en-us/library/windows/desktop/aa363852%28v=vs.85%29.aspx
PInvoke.Net has an example. http://www.pinvoke.net/default.aspx/kernel32/CopyFileEx.html
This function gives you the relative safety of using a standard Windows library function along with the file progress reporting capability that you want.
A BindingSource also has a "Sort" property.
I have not investigated the actual logic for this, but if the bindingsource.sort property is set to an empty string, the behaviour your are seeing will occur.
If you set bindingsource.Sort to null before assigning the "DataSource", it will not clear the DefaultView.Sort value.
It's really pretty simple.
Steps:
Goto your Report in design view and hit the F4 key to bring up the property window for the report.
You need to define a ReportParameter. Click on the elipsis next to the ReportParameters field in the property windows. This will bring up the "Report Parameters" dialog box. Click "Add" then "OK". This will add a string parameter with name "Report_Parameter_0". You can change the name later.
Now click on your textbox and hit the "F4" key again if needed to view its properties. We are interested in the "Value" property. Enter this for the value. You could also use the expresion builder dialog.
=Parameters!Report_Parameter_0.Value
Now your textbox is setup to set the value from code.
- Now for the code to set the parameter. Make sure that you project has a Reference to "Microsoft.Reporting.WinForms"; it should since you already have added the reportviewer control.
I am assuming that your reportviewer is named "ReportViewer1" and the DateTimePicker is named "DateTimePicker1".
'Define an array to hold the parameter definintion.
'This could also be a List(of Microsoft.Reporting.WinForms.ReportParameter)
'or any class that implements IEnumerable
'Since I am assuming you have only 1 report parameter, the array will have size=1
'If you have other parameters, size the array appropriately and define a value for
'all parameters. Afterwards, You can set an individual parameter of a multi-parameter report
Dim params(0) As Microsoft.Reporting.WinForms.ReportParameter
'The value can only be set in the ReportParameter constructor …
taskman,
I believe that the OP found the this article: "Error message "Cannot open file <path>\xxx.DBC" reading Microsoft Visual FoxPro tables via the VFP OLE DB Provider" that shows the posted code solution. It is for dealing with the situation where you do not have the "dbc" file.
I question if this would even be necessary if you where to use one of the other drivers to access the records. I doubt that they would be aware of the "backlink" record in the dbf.
+1 for the concerns you raised.
Does this make things more clear? Perhaps I misunderstood your original request.
The Except method is described here: Click Here
Dim A() As String = IO.File.ReadAllLines("fileA")
Dim B() As String = IO.File.ReadAllLines("fileB")
Dim InA_notIn_B() As String = A.Except(B).ToArray
Dim InB_notIn_A() As String = B.Except(A).ToArray
If InA_notIn_B IsNot Nothing Then
IO.File.WriteAllLines("InA_notInB", InA_notIn_B)
End If
If InB_notIn_A IsNot Nothing Then
IO.File.WriteAllLines("InB_notIn_A", InB_notIn_A)
End If
Assuming that the datagridview is bound to a datatable, then you can use the DataTable.Compute method.
Dim total As Decimal = CDec(dt.Compute("Sum([Payments])", "True"))
Where "dt" is the name of the datatable. I assumed that the column name in the datatable for "paymenents" is "Paymenents".
Put the controls you are enabling/disabling in a container control (panel or group) if possible. Then just enable or disable that one. The child controls will be enabled/disabled as well.
Assuming this is the code that you are using to write the file (found in your other thread),
Private Sub WriteAccounts(filename As String, Accounts As List(Of Account))
Dim lines As String = ""
For Each acct As Account In Accounts
lines &= acct.ToString() & vbCrLf
Next
System.IO.File.WriteAllText(filename, lines)
End Sub
you could modify it something like this
Private Sub WriteAccounts(ByVal filename As String, ByVal Accounts As List(Of account))
Dim encrypt As New Security
Dim sb As New System.Text.StringBuilder(500)
For Each acct As account In Accounts
sb.AppendLine(encrypt.encryptstring(acct.ToString))
Next
System.IO.File.WriteAllText(filename, sb.ToString)
End Sub
Private Sub ReadAccounts(ByVal filename As String, ByVal Accounts As List(Of account))
Dim encrypt As New Security
Accounts.Clear()
Dim lines() As String = System.IO.File.ReadAllLines(filename)
Dim decrypted As String
For Each ln As String In lines
decrypted = encrypt.decryptstring(ln)
Accounts.Add(New account(decrypted.Split(","c)))
Next
End Sub
Another option is to use the Linq extensions on the array class.
For example:
Dim A() As String = {"a", "b", "c", "d", "e"}
Dim B() As String = {"a", "g", "c", "h", "k"}
Dim InA_notIn_B() As String = A.Except(B).ToArray 'yields: b, d, e
Dim InB_notIn_A() As String = B.Except(A).ToArray 'yields: g, h, k
'another way
Dim CommonTo_A_and_B() As String = A.Intersect(B).ToArray 'yields: a, c
Dim Union_A_and_B() As String = A.Union(B).ToArray 'yields: a, b, c, d, e, g, h, k
Dim InA_notIn_BV2() As String = A.Where(Function(s As String) Not CommonTo_A_and_B.Contains(s)).ToArray 'yields: b, d, e
Dim InB_notIn_AV2() As String = B.Where(Function(s As String) Not CommonTo_A_and_B.Contains(s)).ToArray 'yields: g, h, k
Most of your needs are pretty straight forward. The adding a button one is the stickler. I've hosted other apps in a winform before, so I thought why not follow the same method to host a winform button in another app? It sort of works ok.
You need to control force repainting of the control as the other app will not do it for you. I used a timer to do this. Also, once the button is on the other app, if you click it, it gains focus and you need to send the focus back to the form from which it originated in its click event handler.
Start a new winform project:
Form1.vb code
Imports System.Runtime.InteropServices
Public Class Form1
Private WithEvents Slave As Process
Private Slave_SI As New ProcessStartInfo
Private OldButtonLoc As Point
Private WithEvents btn2Refresher As New Timer With {.Interval = 500}
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Button1.Enabled = False
With Slave_SI
.FileName = "notepad.exe"
.Arguments = ""
.WindowStyle = ProcessWindowStyle.Normal
End With
Slave = Process.Start(Slave_SI)
Slave.EnableRaisingEvents = True
Slave.WaitForInputIdle(5000) ' give it 5 seconds to startup
'add the button you wanted
'will steal a button from this form
SetParent(Button2.Handle, Slave.MainWindowHandle)
'position the button
OldButtonLoc = Button2.Location
Button2.Location = New Point(50, 0)
Button2.Visible = True
btn2Refresher.Start() 'hack to repaint button on host window
Me.ActiveControl = Me.Button3 'need to force focus back to a current form window
'It jumped to button2 when I disabled Button1
End Sub
Private Sub Button2_Click(ByVal …
Hi Jim,
If I'm understanding your problem correctly, I think what you want is a message prefilter. These filters are added to the application and filter all application messages. By combining WM_MOUSEMOVE and WM_MOUSELEAVE with a hit test on the clientrectangle you can achieve this.
Public Class Form1
Implements IMessageFilter
Private Const WM_MOUSELEAVE As Int32 = &H2A3
Private Const WM_MOUSEMOVE As Int32 = &H200
Private MouseInForm As Boolean = False
'Add a dock-filled panel to the form to block the normal MouseLeave, MouseEnter Events
Private pnl As New Panel With {.Dock = DockStyle.Fill, .Parent = Me, .BorderStyle = BorderStyle.Fixed3D}
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Application.AddMessageFilter(Me)
End Sub
Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
If m.Msg = WM_MOUSELEAVE OrElse m.Msg = WM_MOUSEMOVE Then
'hit test the client rectangle
'since WM_MOUSELEAVE does not provide the mouse location, use MousePosition
Dim hit As Boolean = Me.ClientRectangle.Contains(Me.PointToClient(MousePosition))
If hit Then
If Not MouseInForm Then
OnMouseEnter(Nothing)
End If
MouseInForm = True
Else
If MouseInForm Then
OnMouseLeave(Nothing)
End If
MouseInForm = False
End If
End If
End Function
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Application.RemoveMessageFilter(Me)
End Sub
Private Sub Form1_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseEnter
Debug.WriteLine("mouse entered form")
End Sub
Private Sub Form1_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseLeave
Debug.WriteLine("mouse left form")
End Sub
End Class
Hi kRod,
In terms of speed the Linq method will be the slowest as it will search against every record in the list. If you use Redgate's Reflector to inspect the code that executes for the other three methods, you find that at the end of the call tree that they all enumerate sequentially through the list. Their only saving grace is that once a match is found, they stop searching.
Based on the class compareto method, you are defining equality based solely on the extension field. Is each extension in the list unique? If so, then using a dictionary would give you better search performance.