how to create dashed line separator using iTextSharp in vb.net - itext

I have gone through the custom dotted line separator example but unable
do it in visual basic is there any example in vb
I am getting following errors
1)'Dash' is already declared as 'Protected Friend dash As Single' in this class.
2)'Phase' is already declared as 'Protected Friend phase As Single' in this class.
3)'LineWidth' is not a member of 'iTextSharp.text.pdf.PdfContentByte'.
4) Variable 'Dash' is used before it has been assigned a value. A null
reference exception could result at runtime.
5) Variable 'Phase' is used before it has been assigned a value. A null
reference exception could result at runtime.
6) sub 'draw' shadows an overridable method in the base class 'DottedLineSeparator'. To override the base method, this method must be declared 'Overrides'.
Option Strict On
Option Explicit On
Imports iTextSharp.text
Imports iTextSharp.text.pdf
Imports iTextSharp.text.pdf.draw
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs)
Handles MyBase.Load
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs)
Handles Button1.Click
Dim FileName As String = System.IO.Path.Combine
(AppDomain.CurrentDomain.BaseDirectory, "Customers.pdf")
'Dim PageSize As New iTextSharp.text.Rectangle
(iTextSharp.text.PageSize.A4)
Dim Document As Document = New Document(iTextSharp.text.PageSize.A4,
50, 10, 10, 10)
Try
PdfWriter.GetInstance(Document, New System.IO.FileStream(FileName,
System.IO.FileMode.Create))
Document.Open()
Dim separator As New CustomDashedLineSeparator()
separator.dash = 10
separator.Gap = 7
separator.LineWidth = 3
Dim linebreak As New Chunk(separator)
Document.Add(linebreak)
Document.Close()
Catch ex As Exception
MsgBox("Pdf is Created")
End Try
End Sub
End Class
Friend Class CustomDashedLineSeparator
Inherits pdf.draw.DottedLineSeparator
Protected Friend dash As Single = 5
Protected Friend phase As Single = 2.5F
Public Overridable Property Dash As Single
Get
Return Dash
End Get
Set(ByVal dash As Single)
Me.dash = dash
End Set
End Property
Public Overridable Property Phase As Single
Get
Return Phase
End Get
Set(ByVal phase As Single)
Me.phase = phase
End Set
End Property
Public Overridable Sub draw(ByVal canvas As PdfContentByte, ByVal llx As
Single, ByVal lly As Single, ByVal urx As Single, ByVal ury As Single,
ByVal y As Single)
canvas.SaveState()
canvas.LineWidth = LineWidth
canvas.SetLineDash(dash, Gap, phase)
DrawLine(canvas, llx, urx, y)
canvas.RestoreState()
End Sub
End Class

Visual Basic is generally case-insensitive unlike C# and Java. You have both a property and field named Dash and also the same with Phase. That's your first two errors as well as your fourth and fifth. You can fix this by renaming your fields. One common way is to just prefix them with underscores.
For the third error, you need to use the SetLineWidth() method instead of using the LineWidth property.
For your sixth error, you are trying to override a method without explicitly telling VB that you want to. To do that you need to use Overrides instead of Overridable.
Your cleaned up class should look like this:
Friend Class CustomDashedLineSeparator
Inherits iTextSharp.text.pdf.draw.DottedLineSeparator
Protected Friend _dash As Single = 5
Protected Friend _phase As Single = 2.5F
Public Overridable Property Dash As Single
Get
Return Dash
End Get
Set(ByVal dash As Single)
Me._dash = dash
End Set
End Property
Public Overridable Property Phase As Single
Get
Return _Phase
End Get
Set(ByVal phase As Single)
Me._phase = phase
End Set
End Property
Public Overrides Sub Draw(ByVal canvas As PdfContentByte, ByVal llx As Single, ByVal lly As Single, ByVal urx As Single, ByVal ury As Single, ByVal y As Single)
canvas.SaveState()
canvas.SetLineWidth(LineWidth)
canvas.SetLineDash(Dash, Gap, phase)
DrawLine(canvas, llx, urx, y)
canvas.RestoreState()
End Sub
End Class
However, I'm betting that you don't really need those internal properties in the first place. If not, you can make that class even simpler:
Friend Class CustomDashedLineSeparator
Inherits iTextSharp.text.pdf.draw.DottedLineSeparator
Public Property Dash As Single
Public Property Phase As Single
Public Overrides Sub Draw(ByVal canvas As PdfContentByte, ByVal llx As Single, ByVal lly As Single, ByVal urx As Single, ByVal ury As Single, ByVal y As Single)
canvas.SaveState()
canvas.SetLineWidth(LineWidth)
canvas.SetLineDash(Dash, Gap, phase)
DrawLine(canvas, llx, urx, y)
canvas.RestoreState()
End Sub
End Class
Lastly, please never try/catch giant blocks of code. At best, your app will politely crash however you'll have no idea why and you'll never be able to fix it. Although not as pretty "Unable to open file XYZ.pdf for writing" is way more helpful than "Unable to create PDF".

Related

Window layout changes to Aero when moved into panel

I use the code down below to open a cmd.exe window and move it into a panel on my form. I do this so that I can change the title permanently during execution.
When cmd.exe is started, the window layout looks like this:
Which is the standard Windows 10 layout. But as soon as it's moved into the panel in my form, the window layout changes to the old Aero layout:
I don't know why the layout changes, does anybody know why?
Thanks for any help in advance!
Kind regards,
Eric
Imports System.Runtime.InteropServices
Public Class Form1
Private WithEvents Tmr As New Timer With {.Interval = 100}
Private Const HWND_BOTTOM As Integer = &H1
Private WithEvents proc As New Process
<DllImport("user32.dll", EntryPoint:="SetParent")>
Private Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", EntryPoint:="SetWindowPos")>
Private Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Text = "My title"
proc.EnableRaisingEvents = True
proc.StartInfo.FileName = "cmd"
proc.Start()
Tmr.Start()
End Sub
Private Sub Tmr_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Tmr.Tick
If SetParent(proc.MainWindowHandle, Panel1.Handle) <> IntPtr.Zero Then
Tmr.Stop()
SetWindowPos(proc.MainWindowHandle, New IntPtr(HWND_BOTTOM), 0, 0, Panel1.ClientSize.Width, Panel1.ClientSize.Height, 0)
End If
End Sub
Private Sub Proc_Exited(ByVal sender As Object, ByVal e As System.EventArgs) Handles proc.Exited
Invoke(Sub() Close())
End Sub
End Class
This issue seems to be related to the way a MDI child is handled. Since MDI is no longer maintained, this issue will probably never be fixed by Microsoft.

Renaming a window which runs a character based application

I have an application which starts a character based application and then changes the name of that window. It works, but only until you select a character in that application, at which point the name changes back to the original name. I read that this is normal behavior and there's little you can do about that.
So I thought about embedding this application in my own form/panel, so I can change the name of this form to my liking, but that only seems to work for GUI applications, like notepad.exe.
Does anybody know of a way to run such an application in a panel of how you can create a form around a character based application?
Thanks for any help in advance.
Kind regards,
Eric
I found the answer myself on how to run a cmd window inside a form:
Imports System.Runtime.InteropServices
Public Class Form1
Private WithEvents Tmr As New Timer With {.Interval = 100}
Private Const HWND_BOTTOM As Integer = &H1
Private WithEvents proc As New Process
<DllImport("user32.dll", EntryPoint:="SetParent")>
Private Shared Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
End Function
<DllImport("user32.dll", EntryPoint:="SetWindowPos")>
Private Shared Function SetWindowPos(ByVal hWnd As IntPtr, ByVal hWndInsertAfter As IntPtr, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal cy As Integer, ByVal uFlags As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Text = "My title"
proc.StartInfo.FileName = "cmd"
proc.Start()
Tmr.Start()
End Sub
Private Sub Tmr_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Tmr.Tick
If SetParent(proc.MainWindowHandle, Panel1.Handle) <> IntPtr.Zero Then
Tmr.Stop()
SetWindowPos(proc.MainWindowHandle, New IntPtr(HWND_BOTTOM), 0, 0, Panel1.ClientSize.Width, Panel1.ClientSize.Height, 0)
End If
End Sub
End Class

VBA giving method or data member not found for a method I have defined

I have been trying to implement a very simple tree structure in VBA for some basic text parsing needs. The relevant code follows.
Private pLeaves() As CTree
Private numLeaves As Integer
Private leavesLen As Integer
Private iterate As Integer
Private pParent As CTree
Public pValue As Object
Public Sub class_initialize()
ReDim pLeaves(10)
leavesLen = 10
numLeaves = 0
Set pParent = Nothing
iterate = 0
Set pValue = Nothing
End Sub
Public Sub Class_terminate()
'We'll leave it empty for now
'if it looks like it's not working right we might change it
End Sub
Public Property Get Parent() As CTree
Parent = pParent
End Property
Public Property Get Leaves() As CTree
Leaves = pLeaves
End Property
Private Property Set Parent(ByRef p As CTree)
Set pParent = p
End Property
Private Property Set value(ByRef value As Object)
Set pValue = value
End Property
Public Sub Add_Leaf(ByRef value As Object)
Dim n As Integer
n = numLeaves
If numLeaves >= leavesLen Then
ReDim Preserve pLeaves(leavesLen + 10)
leavesLen = leavesLen + 10
End If
Set pLeaves(n) = New CTree
Set pLeaves(n).Parent = Me
Set pLeaves(n).value = value
End Sub
Public Function DFFind_Leaf(value As Object) As CTree
Dim i As Integer
If pValue = value Then
Set DFFind_Leaf = Me
Return
End If
If numLeaves = 0 Then
Set DFFind_Leaf = Nothing
Return
End If
For i = 0 To numLeaves
Set DFFind_Leaf = pLeaves(i).DFFind_Leaf(value)
If DFFind_Leaf <> Nothing Then
Return
End If
Next i
Set DFFind_Leaf = Nothing
Return
End Function
When I try to call the Add_Leaf function with an object though I end up getting a
method or data member not found error from VBA on the line where I'm trying to
set pLeaves(n).Parent= me
Any idea what the reason for that might be?
Edit: ok I figured out how to fix this. Changing the set property Parent(...) from private
to public fixed the problem. So apparently I don't quite understand what private exactly does in vba. If someone wants to explain how to do this without essentially exposing the variables for anyone to set as they want I would be grateful.
Private tells the VBA interpreter that the scope of the variable is restricted to the class/module only. You can therefore access it only inside of the original class, but not from the outside. Publicon the other hand allows you to access the variable from the outside.
However, note that when working with classes, it is strongly discouraged to publicly expose any variables. Instead it is best practice to expose so called properties, using the SET PROPERTYand GET PROPERTY keywords.
I.e. instead of
Public Amount as Double
It is often better to use this approach:
Private mAmount as Double
Property Set Amount(amt as Double) 'Note that by default, properties are public
If amt > 0 Then
mAmount = amt
Else
mAmount = 0
End If
End Property
Property Get Amount as Double
Amount = mAmount
End Property
As you can see from this example, the advantage is that you can actually add additional verifications/modifications and therefore ensure the consistency.
In your example, you could consider to simply provide a method, i.e. a public sub, that adds a leave and takes care of all the settings, e.g.
Public Sub AddLeave(strName as String)
Dim objLeave as New CTree
objLeave.Init strName, Me
mLeaves.Add objLeave, strName
End Sub
Public Sub Init(strName as String, objParent as CTree)
Me.Name = strName
Set Me.Parent = objParent
End Sub

Validate a textbox value to contain certain strings

I have a VB.NET form and the user would select from 40 different values.
I want instead of a dropbox with all 40 values to use a textbox that validates if the stirng given by user is one valuo out off those 40 words.
so for example I need the user writes something and validate the string is one of those 40 reserved words like "urgent","post"... maybe these words stored in an array, and then compared what user wrote against that?
TextBox1.Text.Contains("urgent")
TextBox1.Text.Contains("post")
TextBox1.Text.Contains("standard")
TextBox1.Text.Contains("stay")
Maybe a method
Public Function Contains(ByVal value As String) As Boolean
Return ( TextBox1.Text(value, ...) >= 0)
End Function
What would be the best way to do this?
You can create a List(of String) of your Reserved Words use the Contains method to check if what was typed was one of them using your Contains function something like this. I am not sure how large the Text you are going to be parsing so I am splitting it into individual words.
Public Class Form1
Dim reservedWords As List(Of String) = New List(Of String)({"urgent", "post", "standard", "stay"})
Private Sub TextBox1_TextChanged(sender As System.Object, e As System.EventArgs) Handles TextBox1.TextChanged
Dim text As String = CType(sender, TextBox).Text
If ContainsReservedWord(text) Then Beep()
End Sub
Public Function ContainsReservedWord(value As String) As Boolean
Dim x As Integer
Dim stringSplit As String() = value.Split
If stringSplit.Count > 0 Then
For x = 0 To stringSplit.Count - 1
If reservedWords.Contains(LCase(stringSplit(x))) Then Return True
Next
End If
Return False
End Function
End Class
Use the below code to validate the string that belongs to reserved words or not.
var lstReservedWords = new List<string> {"urgent", "post", "standard", "stay", .......};
bool isReservedWord = lstReservedWords.Any(r => String.Compare(r, TextBox1.Text, true) == 0);
Hope this helps.

How to pass objects to methods in other classes in VB6

I have created two classes as interface / implementation classes, and wish to pass a particular example of one class to a method in the other. The definitions are as follows...
Class BigInt...
Option Explicit
Public Sub dothing(ByRef passed_object As MyInt)
End Sub
and an implementation BigImplementation...
Option Explicit
Implements BigInt
Public Sub BigInt_dothing(ByRef passed_obj As MyInt)
Dim i As Integer
i = passed_obj.getprop
End Sub
The class I am planning to pass is...
Option Explicit
Public Property Get getprop() As Integer
End Property
Public Property Let letprop(ByVal myval As Integer)
End Property
implemented as MyImplementation thus...
Option Explicit
Implements MyInt
Private myval As Integer
Public Property Get myint_getprop() As Integer
myint_getprop = myval
End Property
Public Property Let myint_letprop(ByVal passed_int As Integer)
myval = passed_int
End Property
I am then driving this with the following snippet of code:-
Private Sub Command_Click()
Dim myobj As MyInt
Set myobj = New MyImplementation
Dim mybigobj As BigInt
Set mybigobj = New BigImplementation
myobj.letprop = 1
Call mysub(myobj)
mybigobj.dothing (myobj) ' Line with problem
End Sub
Private Sub mysub(ByVal passed_obj As MyInt)
Dim i As Integer
i = passed_obj.getprop
End Sub
When the execution reaches the line marked, I get run-time error 438 - Object doesn't support property or method. The call to the ordinary function mysub works perfectly. Does anyone know what I am doing wrong and what I need to do to fix this?
Use either
mybigobj.dothing myobj
or
Call mybigobj.dothing(myobj)
Putting extra parentheses around a reference evaluates its default property and passes it's value as actual argument.
mybigobj.dothing requires its parameter to be a MyInt
Public Sub BigInt_dothing(ByRef passed_obj As MyInt)
Dim i As Integer
i = passed_obj.getprop
End Sub
You're passing a MyImplementation
Set myobj = New MyImplementation
So possiblly something like (my vb is rusty)
mybigobj.dothing (myobj.myint_getprop())