TnTinMN 418 Practically a Master Poster

Now when I type something in textbox1 and lose focus, textbox2 is altered but when I click the button neither textbox is updated.

Obviously if I uncomment the call to notifyPropertyChanged all works fine. This however brings up questions in my mind.

  1. If I change textfield1 this must be changing the datasource and then the datasource somehow triggers textbox2 to re-fetch the data then displaying it.

The default datasource update mode is . When you leave the textbox you trigger its validation. If you set the TextBox.CauseValidation property to false, you would not see the second textbox update to reflect the change to the datasource.

If you use the longer Add method overload and specify "OnPropertyChanged" for the update mode, you will see the other textbox change as you type. "OnValidation" and "OnPropertyChanged" are for the control and its property to which you are adding the binding, not the datasource.

I'm not sure about this but it makes sense to me. If one databound control fires an event to update the datasource, then the binding manager does not require the property change event from the datasource (as it is the source of the change) to know that it needs to update all other controls bound to the same datasource.

  1. If I click the button this changes the datasource but for some reason the control isn't triggered to fetch the data again.

As you have disabled the property change notification, the binding manager has no way to …

TnTinMN 418 Practically a Master Poster

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.

TnTinMN 418 Practically a Master Poster

I recommend that you create a BindingNavigator to manage navigation.
Your current implimentation has no error checking and the navigator will do all that for you.
http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingnavigator(v=vs.90).aspx

With a navigator you can define the buttons that handle navigation. The one draw back is that they need to be ToolStrip items. Add an undocked toolstrip for each button that you want to have in your form and set the autosize property to false; also set the LayoutStyle to Table. To replace your current buttons, add a Toolstipbutton to the toolstrip and make it look like your original button. You can also add buttons for goto first and goto end. To allow jumping to a specific row (PositionItem), add a toolstriptextbox. To get a total of the row, add another toolstriptextbox for CountItem and make it read-only.

If you do this and modify your code as follows, you can delete all your existing button-click code and your "gridvalues" method code.

On an issue of readability, I suggest that you name the buttons and textboxes to reflect what they actually display on the form.

Private MyNavigator as New BindingNavigator(False)

Private Sub Telefon_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    OleDbDataAdapter1.Fill(DatasetTelefonija1)
    DataGridView1.Columns(0).HeaderText = "Redni broj"
    DataGridView1.Columns(1).HeaderText = "Ime i prezime"
    DataGridView1.Columns(2).HeaderText = "Telefon"
    DataGridView1.Columns(3).HeaderText = "Ostalo"


    With MyNavigator
       .Parent = Me
       .BindingSource = Me.TelefoniBindingSource
       .PositionItem = ToolStripTextBox1
       .CountItem = ToolStripTextBox2
       .MovePreviousItem = ToolStripButton1
       .MoveNextItem = ToolStripButton2
       .AddNewItem = ToolStripButton3
       .DeleteItem = ToolStripButton4
       .MoveFirstItem = ToolStripButton5
       .MoveLastItem = …
TnTinMN 418 Practically a Master Poster

Here is what the source will look like:
text1 = text1
text2 = text2
text3 = text3
text4 = text4
text5 = abcdefg (Yes)
text6 = hijklmn (Yes)
text7 = 1234567 (No)
text8 = abcdefg (No)

What I want to pull is any data that is marked Yes, so in this case abcdefg and hijklmn.

   'get all lines in the text file
   Dim text() As String = System.IO.File.ReadAllLines("sample.txt")

   'create an array of only those lines that contain "(Yes)"
   Dim YesLines() As String = Array.FindAll(text, Function(str As String) str.Contains("Yes")).ToArray
   ' or
   'Dim YesLines() As String = text.Where(Function(str As String) str.Contains("Yes")).ToArray


   'Process the lines to remove unwanted text (Text# = ) and (Yes)
   '1st cut-off "Text# =" using SubString
   'then replace (Yes) with nothing
   'finally trim leading and trailing spaces
   Dim WantedText() As String = YesLines.Select( _
                                   Function(str As String) _
                                   str.Substring(str.IndexOf("=") + 1).Replace("(Yes)", "").Trim _
                                               ).ToArray()

   'You now have the data you want in a string array
   'If you need this array as a single string
   Dim oneline As String = String.Concat(WantedText)
TnTinMN 418 Practically a Master Poster

Just thought about the decimal seperator.

   Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
      If (Not Char.IsLetterOrDigit(e.KeyChar)) And e.KeyChar <> Threading.Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberDecimalSeparator Then
         e.Handled = True
      End If
   End Sub
TnTinMN 418 Practically a Master Poster

You lost me on your sequence of events. However, the simplest way to store the textbox is to use "UserSettings". Go to Project->Properties and select the Settings tab. Create three setting like these:

Then in your notepad form do something like this:

   Private Sub btnSave_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSave.Click
      My.Settings.SavedTBText = TextBox1.Text
      My.Settings.SavedTBSelectionStart = TextBox1.SelectionStart
      My.Settings.SavedTBSelectionLength = TextBox1.SelectionLength
   End Sub

   Private Sub Form_NotePad_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
      With TextBox1
         .Text = My.Settings.SavedTBText
         .SelectionStart = My.Settings.SavedTBSelectionStart
         .SelectionLength = My.Settings.SavedTBSelectionLength
      End With
   End Sub

This will save/restore the state of the textbox on the notepad form.

TnTinMN 418 Practically a Master Poster
   Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
      If Not Char.IsLetterOrDigit(e.KeyChar) Then
         e.Handled = True
      End If
   End Sub
TnTinMN 418 Practically a Master Poster

Do you have a "Button1" on your form or did you name it something else?

Please post your code.

TnTinMN 418 Practically a Master Poster

VB2005 has VB6 converter built-in. For simple projects it can be a time saver. As the others have stated, the converted source can be more work than starting from scratch.

Here are download links for VB2005.

Visual Basic 2005 Express Edition (445,282 KB)
* IMG File: http://go.microsoft.com/fwlink/?linkid=54764
* ISO File: http://go.microsoft.com/fwlink/?linkid=57033

As far as writing your own converter, you will have the investment in writing the converter itself that I think could be better invested in getting the needed conversions done.

TnTinMN 418 Practically a Master Poster

Add a constructor to the form (call it Form2) that needs to hide the button on the first form (call it Form1). Like this:

Public Class Form2

   Private ButtonToHide As Button

   Public Sub New(ByVal ButtonToHide As Button)
      Me.InitializeComponent()
      Me.ButtonToHide = ButtonToHide
   End Sub

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      ButtonToHide.Hide()
   End Sub
End Class

Then in Form1, call the constructor like this:

Public Class Form1
   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      Dim frm As New Form2(Button2)
      frm.Show()
   End Sub
End Class
TnTinMN 418 Practically a Master Poster

I just realized that I made mistake in my first response to you. The textbox is updating as you append text in your loop. These updates are very resource intensive. If you can live with updating every "X" lines, then this modifcation will give you even better performance. The larger "X" is (less repainting the textbox) the faster your code will proceed.

Dim counter as Int32 = 0
TextBox1.AllowRedraw(False)
For Each TextLine In ArrayList

... Your Code


If counter Mod 5 = 0 Then 'update every 5 lines process
   TextBox1.AllowRedraw()
   TextBox1.AllowRedraw(False)
End If

Next

TextBox1.AllowRedraw() ' make sure to re-enable redraw

Where the AllowRedraw Method is an extension method defined as:

Module MyExtensions
   Private Const WM_SETREDRAW As Int32 = &HB
   <System.Runtime.CompilerServices.Extension()> _
   Public Sub AllowRedraw(ByVal cntrl As Control, Optional ByVal allow As Boolean = True)

      If allow Then
         SendMessage(cntrl.Handle, WM_SETREDRAW, New IntPtr(1), IntPtr.Zero)
         cntrl.Refresh()
      Else
         SendMessage(cntrl.Handle, WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero)
      End If
   End Sub

   <Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True, CharSet:=Runtime.InteropServices.CharSet.Auto)> _
   Private Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As Int32, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As UInt32
   End Function
End Module

Just add this module to your project. It's one of my favorite tricks to speed things up.

TnTinMN 418 Practically a Master Poster

Two things standout as big performance hits:
1) string concatenation: This is very slow and gets worse as the length of the string grows. Your "Display" variable gets longer as the loop progresses.

2) unnecessary assignment statements in the loop: The big one is assigning TextBox1.Text. Since you have not issued a TextBox1.Refresh command after the assignment, I assume that you can wait until the loop finishes to view the results. The minor assigment is the "btn2003.Ennabled"

No guaranty of major performance improvement, but I reccommend that you use a System.Text.StringBuilder for "Display" and modify the logic as follows:

        Try

            Dim Display As New System.Text.StringBuilder(100) 'adjust this initial size (100) to what makes sense
            textbox1.Text = n1 & vbNewLine 'initialize the textbox's text
            btn2003.Enabled = False
            For Each TextLine In ArrayList

                ' Dim tmp() As String = Split(TextLine)
                Dim split As String() = TextLine.Split(New [Char]() {"/"c})
                ipaddress = split(0)
                subnet = split(1)
                If subnet.Contains("32") Then
                    subnet = subnet.Replace("32", "255.255.255.255")
                    .
                    . the rest of the "if-then" block
                    .
               Display.Length = 0 ' clears the stringbuilder
               With Display
                  .Append(p1)
                  .Append(p2)
                  .Append(P3)
                  .Append(ipaddress)
                  .Append(p4)
                  .Append(subnet)
                  .Append(p5)
                  .Append(p6)
                  .AppendLine(p7)

               End With

                'let the textbox append the text, this eliminates a couple to string copys that can be quite long
                textbox1.AppendText(Display.ToString)

            Next
            btn2003.Enabled = True  'If this is the correct spot        

Also, what does this function return?

TnTinMN 418 Practically a Master Poster

You have not assigned the connection to "OComn" (OleCoDbCommand).
see: http://msdn.microsoft.com/en-us/library/system.data.oledb.oledbconnection%28v=vs.90%29.aspx

TnTinMN 418 Practically a Master Poster

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.

TnTinMN 418 Practically a Master Poster

I would suggest that you place your logic in the PlayStateChange event handler. Here is a snippet from a program of mine.

   Sub WMP1_PlayStateChange(ByVal sender As Object, _
         ByVal e As AxWMPLib._WMPOCXEvents_PlayStateChangeEvent) _
         Handles wmp1.PlayStateChange

         Select Case e.newState

            Case WMPLib.WMPPlayState.wmppsUndefined
            currentStateLabel.Text = "Undefined"

            Case WMPLib.WMPPlayState.wmppsStopped
            currentStateLabel.Text = "Stopped"

            Case WMPLib.WMPPlayState.wmppsPaused
            currentStateLabel.Text = "Paused"

            Case WMPLib.WMPPlayState.wmppsPlaying
               currentStateLabel.Text = "Playing"
               SetSelectedPlayListItem()

            Case WMPLib.WMPPlayState.wmppsScanForward
            currentStateLabel.Text = "ScanForward"

            Case WMPLib.WMPPlayState.wmppsScanReverse
            currentStateLabel.Text = "ScanReverse"

            Case WMPLib.WMPPlayState.wmppsBuffering
            currentStateLabel.Text = "Buffering"

            Case WMPLib.WMPPlayState.wmppsWaiting
            currentStateLabel.Text = "Waiting"

            Case WMPLib.WMPPlayState.wmppsMediaEnded
            currentStateLabel.Text = "MediaEnded"

            Case WMPLib.WMPPlayState.wmppsTransitioning
            currentStateLabel.Text = "Transitioning"

            Case WMPLib.WMPPlayState.wmppsReady
            currentStateLabel.Text = "Ready"

            Case WMPLib.WMPPlayState.wmppsReconnecting
            currentStateLabel.Text = "Reconnecting"

            Case WMPLib.WMPPlayState.wmppsLast
            currentStateLabel.Text = "Last"

            Case Else
            currentStateLabel.Text = ("Unknown State: " + e.newState.ToString())

         End Select
   End Sub
TnTinMN 418 Practically a Master Poster

You could accomplish your goal via Reflection something like this:

private bool fred;
public void SetBoolean(string boolToSet, bool Value)
{
    System.Reflection.FieldInfo fi = this.GetType.GetField(boolToSet, Reflection.BindingFlags.Instance | Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Public);
    fi.SetValue(this, Value);
}
public void test()
{
    SetBoolean("fred", true);
}

However, I would recommend that you consider using a Dictionary(Of String, Boolean) instead. It will give you the access by name feature that you want.

TnTinMN 418 Practically a Master Poster

You are not clearing MyDataTable before filling in CnScrip.
Try adding MyDataTable.Clear before MyAdapter.Fill(MyDataTable).

TnTinMN 418 Practically a Master Poster

Nutster, you may find this article helpful: Click Here

The code placed under the "Finally" section can be viewed like an in-place method definition that will always be called before leaving the "Try-End Try" block.

Let's say in your IOException example, that you can not recover from the file error and need to return control to the calling procedure via an "Exit Sub", "Exit Function", or "Return" statement. The "Finally" code will execute before the return. You could accomplish the same thing without using the "Finally" section, but it keeps the logic all together and easier to maintain.

TnTinMN 418 Practically a Master Poster

The Form.Close method does exactly that; it tells the form to close. It does not stop the currently executing code block. The following code will demonstrate this behavior and show you an alternative to achieve your goal of stoping execution. Just step through the code in the debugger to observe how the code execution branches and returns.

Public Class Form1
   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      CheckFiles()
      Stop 'this line will be reached

   'This will exit the executing code block on return.  
   'Since the main form is closed, the program will terminate.
      If Not CheckFilesV2() Then Exit Sub

      Stop 'this one will not
      MsgBox("hi")
   End Sub

   Private Sub CheckFiles()
      CloseForm()
      Stop 'and here
   End Sub

   Private Function CheckFilesV2() As Boolean
      CloseForm()
      Stop 'and here
      Return False
   End Function

   Private Sub CloseForm()
      Me.Close()
      Stop 'yep you got here
   End Sub
End Class
TnTinMN 418 Practically a Master Poster

Here is an example that shows four methods to access a "dbf" file. Since you started with OBDC and wanted info on that, that section is quite long. Personally, I would use the ACE driver, but to each their own. The simplest/most flexible for "dbf" is the visual foxpro driver. I cover handling deleted records in the "dbf" because this is an area that can cause those that need to access them quite a bit of headaches. Delete records are not deleted from the file until in is "packed".

Public Class Form1

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

      'My dBase files are in the application folder
      Dim AppDir As String = My.Application.Info.DirectoryPath

      '=======================================================
      'Open Database Connectivity (ODBC) DSN-Less Connection
      'see: http://support.microsoft.com/kb/310985

      Dim connSB As New Odbc.OdbcConnectionStringBuilder()
      With connSB
         'these parameters are called "Connection String Attributes"
         'They are driver specific.  

      'see: Initializing the dBASE Database Driver
      '     http://office.microsoft.com/en-us/access-help/initializing-the-dbase-database-driver-HP001032158.aspx

      'see: SQLConfigDataSource (dBASE Driver) 
      '     http://msdn.microsoft.com/en-us/library/windows/desktop/ms710137%28v=vs.85%29.aspx

         .Add("DRIVER", "Microsoft dBase Driver (*.dbf)")
         .Add("DefaultDir", AppDir) 'Path to dbase files
         .Add("FIL", "dBase 5.0") 'File type dBase III, dBase IV, or dBase 5
         .Add("DriverID", 533) '21 (dBASE III), 277 (dBASE IV), 533 (dBASE 5.0)

         'Do not load deleted records.  
         'Tag would be better named "IgnoreDeleted"
         'where 0 = Off, 1 = On
         'My experience is that this tag does not work unless the application is running 
         'with full administrator privilages
         'a work around is presented next
         .Add("DELETED", 0)

         .Add("CollatingSequence", "ASCII") 'can be: ASCII (the …
TnTinMN 418 Practically a Master Poster

How would I go about placing the title into a label first, then sorting and placing all of the other information into the textbox. Sorry to keep asking questions, but reading and sorting from text files is something I am finding hard to figure out.

Hi Minko,

I can sympathize with your problems with text files. I personally prefer to use a binary file as you don't need to go through all the conversions and the loss of floating point accuracy.

But that is not what you need today, so here is a revised version of my example that will process a text file. Most of the code in the subroutine to read the text file is error checking and handling. I added this just to give you an idea how to accomplish some of that. The checking is not exhaustive, but it covers most of the problems that might be encountered. I also added a short function to the Data class to format it as a string.

Public Class Form1

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

      'ignore the next line, I need this to test for your date format. 
      'You should delete it
      Threading.Thread.CurrentThread.CurrentCulture = New Globalization.CultureInfo("en-GB")

      Dim myArray() As Data = GetDataFromFile("data.txt", Label1.Text)
      If myArray IsNot Nothing Then 'sucessfully read file
         Array.Sort(myArray)
         TextBox1.Text = ""
         For i As Int32 = 0 To UBound(myArray)
            TextBox1.Text &= myArray(i).FormattedString & vbCrLf
         Next
         TextBox1.SelectionStart = 0 'move cursor to start of text
      Else …
TnTinMN 418 Practically a Master Poster

I just realized that I had this line in the code above: myArray(4) = New data(#3/1/2001#, 1005)

It should have been: myArray(3) = New data(#3/1/2001#, 1005)

TnTinMN 418 Practically a Master Poster

Hi Minko,

You did not show how you defined your array so I had to guess. If you have a one dimensional array you can use the Array.Sort method. I defined a class to hold you data and made an array of those data items. Since the array holds a user defined class, it is necessary to define a way to compare them. The comparer is defined in the class. By implementing the Icomparable interface, it is possible to define a default comparer. It is also possible to specify a specific compare to use.

Public Class Form1

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      'create an array with 4 items
      Dim myArray(0 To 3) As data
      'create something to work with
      myArray(0) = New data(#3/1/2011#, 13)
      myArray(1) = New data(#2/1/2003#, 15)
      myArray(2) = New data(#3/1/2001#, 1000)
      myArray(4) = New data(#3/1/2001#, 1005)

      Array.Sort(myArray) 'use default comparer (ascending) defined in class
         'or
      Array.Sort(myArray, AddressOf data.Sort_Descending) 'specify a sort order

   End Sub

   Private Class data
      Implements IComparable(Of data)
      Public dt As Date
      Public data As Int32
      Public Sub New(ByVal dt As Date, ByVal data As Int32)
         Me.dt = dt.Date 'force date component only just in case datetime value given
         Me.data = data
      End Sub

      'default comparer ascending on date
      Public Function CompareTo(ByVal other As data) As Integer Implements System.IComparable(Of data).CompareTo
         If Me.dt = other.dt Then
            'sort ascending on data
            Return Me.data.CompareTo(other.data)
         Else
            Return Me.dt.CompareTo(other.dt) 'ascending order
         End If
      End Function

      Public Shared Function Sort_Ascending(ByVal x As data, …
TnTinMN 418 Practically a Master Poster

The problem is caused by: ListBox1.Items.RemoveAt(ListBox1.SelectedIndex)
When you remove the item, there is nothing selected and SelectedIndex = -1.

That explains the error, but I have a feeling that your program logic may not be correct.
Is the listbox used to select the meals or is it selected by the combobox and added to the listbox with your "Add" button? The latter case makes sense to me. However, you are traping a change in the listbox and setting the text of the combobox.

TnTinMN 418 Practically a Master Poster

FoxPro uses a variant of the old dBase(Click Here) file format. There is a program (free trial) called DBF Manager that works well with these file types.

You can find it here:
Click Here

TnTinMN 418 Practically a Master Poster

Isn't the correct syntax: System.IO.File.AppendAllText(filepath, strToAppend)

not: System.IO.File.AppendAllText(strToAppend)?

TnTinMN 418 Practically a Master Poster

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.

iFrolox commented: Yea, its what i had to do. +1
TnTinMN 418 Practically a Master Poster

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
iFrolox commented: Went ahead of me and did it for me XD thanks for saving my time :) worked perfectly +1
TnTinMN 418 Practically a Master Poster

You are out of luck with a color cursor using the built-in .Net functions.

From the documentation:

The Cursor class does not support animated cursors (.ani files) or cursors with colors other than black and white.

But why limit yourself to what is built-in?

Here is a class that you can use to create a cursor from a .Net Image.

Imports System.Runtime.InteropServices

Public Class Form1

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      'make cursor with the hotspot (click point) the top-right corner
      Dim mc As New MakeCursor( _
         MakeCursor.ScaleImage(PictureBox1.Image, _
                               MakeCursor.SystemCursorSize.Width, MakeCursor.SystemCursorSize.Height), _
                               MakeCursor.SystemCursorSize.Width, 0)
      Me.Cursor = mc.Cursor
   End Sub

End Class

''' <summary>
''' Allows creating as cursor from an image
''' </summary>
''' <remarks>True Cursor Size is stored in the "Tag" Property</remarks>
Public Class MakeCursor
   Implements IDisposable
   Private cursorptr As IntPtr

   ''' <summary>
   ''' creates cursor from an Image class
   ''' </summary>
   ''' <param name="img">Source Image for cursor</param>
   ''' <param name="HotSpot_x">the x coordinate of the click pt</param>
   ''' <param name="hotSpot_y">the y coordinate of the click pt</param>
   ''' <remarks></remarks>
   Public Sub New(ByVal img As Image, ByVal HotSpot_x As Int32, ByVal hotSpot_y As Int32)
      Dim cusorrinfo As New IconInfo
      Dim bm As Bitmap = CType(img, Bitmap)
      With cusorrinfo
         .fIcon = False 'cursor
         .xHotspot = HotSpot_x
         .yHotspot = hotSpot_y
         .hbmMask = bm.GetHbitmap
         .hbmColor = bm.GetHbitmap
      End With
      Dim cursorinfoptr As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(cusorrinfo))
      Marshal.StructureToPtr(cusorrinfo, cursorinfoptr, True)
      cursorptr = CreateIconIndirect(cursorinfoptr)
      Dim icon As Icon = icon.FromHandle(cursorptr)
      Cursor = New Cursor(cursorptr)
      Cursor.Tag = bm.Size
      Me.Size = bm.Size …
TnTinMN 418 Practically a Master Poster

Sorry for the late reply; I got distracted.
I have not experienced this blink issue. Can you post your project as a sip file, so that we can look it over. It may be an issue with your timer interval an/or your saving of the image.

TnTinMN 418 Practically a Master Poster

Have you tried the example in the documentation?
Click Here

TnTinMN 418 Practically a Master Poster

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 …
iFrolox commented: Useful post :) +1
Reverend Jim commented: good stuff here +9
TnTinMN 418 Practically a Master Poster

The problem I'm having with the latest implementation is this: when saving a file in a local folder, about four extensionless files are created before finally saving the Excel document.

You may find this article to educational on this issue.
Click Here

TnTinMN 418 Practically a Master Poster

Resequencing the line numbers is fairly trivial. The issue is if there are any GOTO’s in the CNC code. Based on a quick internet search, a GOTO can be defined line number. The line number can be either directly specified or via a variable. Variables are prefixed with the hash “#” symbol followed by an integer.
For example:

N100
GOTO 100

100=100

GOTO #100

To remap the GOTO statements, I used a dictionary (of int32, int32) where the key value is the N####’s original numeric value. It allows looking up the original value and retrieving the new line number. In the code that follows, only variables used in a GOTO statement will be treated as line numbers and be remapped to the new line number. To test this logic, I added these lines to the end of your example.

    #100=1000
    #101=1000
    #101=1040
    GOTO #101
    GOTO 100

There appears to be other types of GOTO's used in CNC code (GOTOF, GOTOB), if you need to account for these, you can follow the pattern demonstrated in my code.

Here is the code. It writes the original code followed by the resequenced code to a RichTextBox.

Public Class Form1

   Private Const fmt As String = "0000"

   'a class to assist in storing info about lines that define a variable
   'variable start with a '#' followed by an integer
   Private Class VariableLine
      Public Name As Int32
      Public LineNumber As Int32 'the line of code that contains the declaration …
TnTinMN 418 Practically a Master Poster

The WebBrowser control uses the installed IE. The problem is that IE8 and above will default to IE7 standards mode. To enable the newer standards, you need to make a registry entry for you specific application executable.

See: Click Here

Click Here

TnTinMN 418 Practically a Master Poster

Add this to your code right after the "CopyFromScreen".

      Cursor.Current.Draw(GraphX, New Rectangle(Point.Subtract(Cursor.Position, New Size(Cursor.Current.HotSpot.X, Cursor.Current.HotSpot.Y)), Cursor.Current.Size))

I hope that you are calling Dispose on GraphX when you are done with it.

TnTinMN 418 Practically a Master Poster

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
TnTinMN 418 Practically a Master Poster

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.

TnTinMN 418 Practically a Master Poster

What type of database are you using? You indicate the SQL Date type; to me this implies possibly a MySQL DB. If it is a MS SQL Server DB, the type is probably a datetime type. If this is the case then your data may contain a time component that is causing your search to fail.

Another possibility is how you are defining the search key value. If you use the MonthCalendar.SelectionStart property, there should not be a problem. If you are entering the date as string, you could be encountering a culture format issue.

Based on your "3.7.2012" format, I assume that you mean "3 July 2012". Assuming your data has a record for "3 July 2012", this code should work if: System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern ="dd.MM.yyyy"

      Dim d As Date = CDate("3.7.2012")
      Dim r As DataRow = dt.Rows.Find(d)

However this code will search for "7 March 2012" as it uses the invariant culture to covert the string to a date.

      Dim r As DataRow = dt.Rows.Find("3/7/2012")

I knew this was the case when using an expression filter (DataTable.Select(filter)) as it is stated in the documentation that this is so, but their is no corresponding comment for the DataRow.Find method (thankyou very much MS). I had to discover this the hard way.

TnTinMN 418 Practically a Master Poster

What i had in mind was saving it as ini file, encrypting the file to another extension, and encrypt it to binary, but to do that i would use the special folder in the AppData, is there a better way for me to save the arrays and encrypt it and be able to read it again and load it in my application?

Hi,

I don’t know if this is a better way, but I’ll leave it to you to decide. It totally changes the way you are managing your data.

Basically what you have is a set of account records that you wish to store and retrieve. You also want to obfuscate the data so users can not see sensitive data.

Two alternatives that immediately come to mind are first a database and second one is to store the data in a user-setting. Personally, I would opt for the database, but some people some to find them to be difficult to work with particularly in getting them stored in the proper location so that they can be written back to without bumping into security issues. The user-setting option alleviates the issue of dealing with the file location as .Net will handle this for you, so that is the route that I plan to show you below.

Since your have a defined Account record format, it makes sense to use a datatable to store each record. You can add a datatable to the user-settings as shown in the this …

TnTinMN 418 Practically a Master Poster

Is there a specific reason for developing in such an outdated version of VB?
If you could update to more recent VB version, you could make use of the My.Application.OpenForms collection. I believe the My namespace became available in VB2005.

TnTinMN 418 Practically a Master Poster

Would you please add some comments/documentation as to what this code is doing other than "look for inconsistencies" and "invokes a reordering logic"? Your code is appreciated but it would be even better if the mechanics were explained.

Jim,
I did not realize that it was as requirement of this site to post fully documented code.

I also did not realize that I was presenting anything that complex and it was not my intent to offer that code as a solution, but rather an example to continue the discussion that I had started with the OP that a simple sort was probably not a good idea as it could easily make a bad situation worse.

Oh well, live and learn. In complying with your request, I found a few logic mistakes that are now corrected in the code below. I suppose that I should state that to use this code one should open a new WinForm project in visual studio. Add two buttons and a richtextbox to Form1. Open the Form1.vb file in code view and replace the code found there with that shown below.

Public Class Form1

   Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
      'Read in the CNC code file
      Dim fs As New IO.FileStream("code.txt", IO.FileMode.Open)
      Dim sr As New IO.StreamReader(fs)

      'Read lines into a stringbuilder. 
      'This is a waste of memory, but will speed up loading
      'could prevent RTB from repainting and append directly to RTB, but do not …
TnTinMN 418 Practically a Master Poster

It sounds like the logic is alreagy becoming more complex than a simple sorting based on N###. I have put together a simple demo program, that offers two options. Button1 will look for inconsistencies based on N### and present the offending block to the user for editing. Button2 invokes a reordering logic based on N###, but this type of logic is prone to failure as there is no way a programmer can forsee every possible mistake a human can make in coding and automatically correct it.

Public Class Form1

   Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
      Dim fs As New IO.FileStream("code.txt", IO.FileMode.Open)
      Dim sr As New IO.StreamReader(fs)

      Dim sb As New System.Text.StringBuilder(CInt(fs.Length))
      Do Until sr.EndOfStream
         sb.AppendLine(sr.ReadLine)
      Loop
      sr.Close()
      With RichTextBox1
         .WordWrap = False
         .ScrollBars = RichTextBoxScrollBars.ForcedBoth
         .Text = sb.ToString
         .HideSelection = False
      End With
   End Sub

   Sub OrderOnN_Numbers()
      Dim ErrorExists As Boolean = False
      Dim lastNumber As Int32 = -1
      Dim currentNumber As Int32
      Dim BadnumberRef As LineNumberRef = Nothing

      Dim NumberIndices As New List(Of LineNumberRef)
      Dim lines() As String = RichTextBox1.Lines
      Dim l As String
      Dim index As Int32
      For i As Int32 = 0 To lines.Count - 1
         l = lines(i).Trim
         If l.StartsWith("N") Then
            index = l.IndexOf(" ", 1)
            currentNumber = -1
            If index = -1 Then
               Int32.TryParse(l.Substring(1), currentNumber)
            Else
               Int32.TryParse(l.Substring(1, index - 1), currentNumber)
            End If

            If currentNumber <> -1 Then
               If lastNumber >= currentNumber Then 'error

                  If Not ErrorExists Then
                     BadnumberRef = New LineNumberRef(lastNumber, i)
                     With RichTextBox1
                        .SelectionStart = .GetFirstCharIndexFromLine(i) …
TnTinMN 418 Practically a Master Poster

Are you sure that sorting based on N#### is really the best logic?
In your sample file, there appears to be condition statements defined after the N####.
i.e.

N1040 IF (LAST_TOOL <> 0)
N1050 WHEN TRUE DO $R21=1
N1060 T1=LAST_TOOL
N1070 GOTOF (<<"T_"<<LAST_TOOL)
N1080 ENDIF

A typo in the N#### followed by sorting could easily change the logic of the CNC program. Would it not be better to make your program a validator/editor that requires human input to check the logic when inconsistencies are found?

TnTinMN 418 Practically a Master Poster

If you have your heart set on gray, then maybe this?

   Dim bc As Color = Me.BackColor
   Me.BackColor = Color.LightGray
   Form2.ShowDialog()
   Me.BackColor = bc

Or if you just want to dull the current backcolor up a bit

   Dim bc As Color = Me.BackColor
   Dim DullFactor As Single = 0.25 'Roange from 0 to 1.  Closer to zero = duller
   Me.BackColor = Color.FromArgb(255, CInt(Me.BackColor.R * DullFactor), CInt(Me.BackColor.G * DullFactor), CInt(Me.BackColor.B * DullFactor))
   Form2.ShowDialog()
   Me.BackColor = bc