setting up margin in vb.net while printing - vb.net

i am developing a school management software in which i have given a small handy functionality of a mini notepad so that it can make notice or doc within the software.
I have taken a RichTextBox for this, Now my problem is that when i enter text in richtextbox without giving space in between ( eg. aaaaaaaa..........) continous for 2 lines and when i click on PrintPreview, it leave some space from it start displaying on left but the text leaves the page from right side.
What i want is that i should a margin on both the side i.e. left & right side.
Below is my code on Print Document Click
Private Sub PrintDocument1_PrintPage_1(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim font1 As New Font("Arial", 12, FontStyle.Regular)
'Dim formatF As StringFormat = StringFormat.GenericDefault
'formatF.Alignment = StringAlignment.Center
'formatF.LineAlignment = StringAlignment.Center
e.Graphics.DrawString(RichTextBox1.Text, font:=font1, brush:=Brushes.Black, x:=10, y:=50)
End Sub
So it basically do is represented in below images. Please have a look.
Text in richtextbox
Image of print preview

To print a string within a certain area of the page, specify a Rectangle which should contain the string.
Imports System.Drawing.Printing
Public Class Form1
Dim pd As PrintDocument
Public Sub New()
' This call is required by the designer.
InitializeComponent()
pd = New PrintDocument()
AddHandler pd.PrintPage, AddressOf pd_PrintPage
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim preview = New PrintPreviewDialog()
preview.Document = pd
preview.ShowDialog()
End Sub
Private Sub pd_PrintPage(sender As Object, e As PrintPageEventArgs)
'Create a long sample string
Dim s As New String("a"c, 2048)
'Create a rectangle which describes the area where the string
'should print
Dim r As New Rectangle(50, 50, 500, 500)
'Draw the string
e.Graphics.DrawString(s, Me.Font, Brushes.Black, r)
'Since there is no more data to print, set to False
e.HasMorePages = False
End Sub
End Class

Related

Type Text Directly On A Bitmap Image at Mouse Position

I am trying to write (type) directly onto a bitmap. I need to be able to type at the mouse position, so where ever on the screen i click the mouse, I can start typing text with the keyboard.
Here is a working VS 2017 VB Win Form code that will print "Hello World" at the mousedown position. But it only works with predetermined text. I would like to be able to just type at that spot. I feel I am so close, just can't get it to work.
Imports System.IO
Imports System.Windows.Forms.DataVisualization.Charting
Public Class Form1
Dim WithEvents Chart1 As New Chart
Private Structure TextPoints
Dim MPos As Point
Dim Txt As String
End Structure
Private TextList As New List(Of TextPoints)
Private TempPoint As Point
Private FirstPoint As Point
Dim xcnt As Integer = -1
Dim ycnt As Integer = -1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Me.Size = New Size(1100, 700)
Me.Location = New Point(10, 10)
MakeBackImage()
With Chart1
.Name = "Chart1"
.Location = New System.Drawing.Point(40, 40)
.Size = New System.Drawing.Size(1010, 610)
.BackImage = "BackImg.jpg"
.Parent = Me
End With
End Sub
Private Sub Chart1_MouseDown(ByVal sender As Object,
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles Chart1.MouseDown
FirstPoint = New Point(e.X, e.Y)
TempPoint = New Point(e.X, e.Y)
Me.Refresh()
End Sub
Private Sub Chart1_MouseUp(ByVal sender As Object,
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles Chart1.MouseUp
Dim T As New TextPoints With {
.MPos = TempPoint,
.Txt = "Hello World"}
TextList.Add(T)
Me.Refresh()
End Sub
Private Sub MakeBackImage()
Dim x, y As Integer
Dim img As Image = New Bitmap(1020, 620)
Dim graphics As Graphics = Graphics.FromImage(img)
graphics.Clear(Drawing.Color.White)
For x = 0 To 1000 Step 20
graphics.DrawLine(Pens.Black, x, 0, x, 600)
xcnt += 1
Next
For y = 0 To 600 Step 20
ycnt += 1
graphics.DrawLine(Pens.Black, 0, y, 1000, y)
Next
img.Save("BackImg.jpg", Imaging.ImageFormat.Jpeg)
End Sub
Private Sub Chart1_Paint(ByVal sender As Object,
ByVal e As System.Windows.Forms.PaintEventArgs) _
Handles Chart1.Paint
Dim drawString As String = "Hello World"
Dim drawFont As New Font("Arial", 14)
Dim drawBrush As New SolidBrush(Color.Black)
For Each t As TextPoints In TextList
e.Graphics.DrawString(t.Txt, drawFont,
drawBrush, t.MPos.X, t.MPos.Y)
Next
End Sub
End Class
This is a simplified code. Actually, the background image is only created once, but I added code to dynamically create it here to make the demo better.

Should I use me.invalidate or me.refresh when repainting my form?

I'm experimenting on paint event in Windows Form, what I want to achieved is to repaint the colors of the arrow. I think I successfully did that, I just have a question on whether should I use the Me.Invalidate or Me.Refresh when performing the repaint event on the form? Both of them are working.
Note that I will create many objects later so one of my goals is to lessen the performance issues.
When you clicked the button 1 it will change the color of the line 1 to yellow using the Me.Invalidate, when you clicked the button 2 it will change the line 1 to blue using the Me.Refresh. Both of them are working.
This is my whole code:
Public Class Form1
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
drawLeftArrow(e, "a", 100, 250, 400, 50)
End Sub
Dim aPen As Pen = New Pen(Color.Red, 8)
Dim bPen As Pen
Dim cPen As Pen
Dim line1 As Point()
Dim line2 As Point()
Dim line3 As Point()
Sub drawLeftArrow(e As PaintEventArgs, letterPosition As String, startPointX As Integer, startPointY As Integer, endPointX As Integer, endPointY As Integer)
bPen = New Pen(Color.Green, 8)
cPen = New Pen(Color.Yellow, 8)
Dim mycap As Drawing2D.CustomLineCap = New Drawing2D.AdjustableArrowCap(5, 5)
' Create points that define curve.
Dim startPoint As New Point(startPointX, startPointY)
Dim endPoint As New Point(endPointX, endPointY)
Select Case letterPosition
Case "a"
Dim middlePoint1 As New Point(startPointX + 250, startPointY)
Dim middlePoint2 As New Point(startPointX + 300, endPointY + 150)
line1 = {startPoint, middlePoint1}
line2 = {middlePoint1, middlePoint2}
line3 = {middlePoint2, endPoint}
cPen.CustomEndCap = mycap
' Draw lines between original points to screen.
e.Graphics.DrawLines(aPen, line1)
e.Graphics.DrawLines(bPen, line2)
e.Graphics.DrawLines(cPen, line3)
Exit Select
End Select
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
aPen = New Pen(Color.Yellow, 8)
Me.Invalidate()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
aPen = New Pen(Color.Blue, 8)
Me.Refresh()
End Sub
End class
Output:

Printing to Multiple Pages

The code below that can nicely print image and text.
The problem now is, how can I automatically move printing to next page when a page is filled.
Will be nice to add a page number, too:
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PrintPreviewDialog1.Document = PrintDocument1
PrintPreviewDialog1.ShowDialog()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
PrintDocument1.Print()
End Sub
Private Sub printDocument1_PrintPage(sender As Object, e As PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim rect1 As Rectangle = New Rectangle(New Point(0, 0), PictureBox1.Image.Size)
Dim rect2 As Rectangle = New Rectangle(New Point(100, 200), PictureBox1.Image.Size)
Dim fmt As StringFormat = New StringFormat()
e.Graphics.DrawImage(PictureBox1.Image, rect1)
e.Graphics.DrawString(RichTextBox1.Text, RichTextBox1.Font, New SolidBrush(Color.Red), rect2, fmt)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For S = 1 To 200
RichTextBox1.AppendText("Test Line No. - " & S & vbCrLf)
Next
End Sub
End Class
PrintPageEventArgs contains a member HasMorePages that you can set to True to raise the same event again at the end of current iteration.
To print page numbers, you'll need to keep a local class variable to track current page number. Then use an e.Graphics.DrawString() overload to print page numbers anywhere on the page.
An example using your own code:
Private mPageNumber As Integer = 1
Private Sub printDocument1_PrintPage(ByVal sender As System.Object, ByVal e As _
System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim rect1 As Rectangle = New Rectangle(New Point(0, 0), PictureBox1.Image.Size)
Dim rect2 As Rectangle = New Rectangle(New Point(100, 200), PictureBox1.Image.Size)
Dim fmt As StringFormat = New StringFormat()
e.Graphics.DrawImage(PictureBox1.Image, rect1)
e.Graphics.DrawString(RichTextBox1.Text, RichTextBox1.Font, New SolidBrush(Color.Red), rect2, fmt)
Using f as New Font("Arial" , 10)
e.Graphics.DrawString(mPageNumber.ToString(), , Brushes.Black, 0, 0) 'Page number at top-left of the page
End Using
mPageNumber += 1
e.HasMorePages = (mPageNumber <= 10) 'Will keep printing till 10 pages are printed
End Sub
Going to next page is entirely dependent upon how you want to compute next page. Specifically, you'll need to print each character in its own font (since it is a RichTextBox) and then take care of paragraphs etc. as well. And as if that were not enough, you may need to tackle bidirectional text, text wrapping, alignment and what not too. Welcome to the world of printing!!
I won't be writing the exact code here, but will give you some hints so you could start your journey. RichTextBox has a method named GetPositionFromCharIndex() that gives you the x,y coordinates of the specified character index. You could use a loop to determine the last character whose Y-coordinate is less than or equal to e.MarginBounds.Height in your PrintPage event handler and then send all words upto that index to DrawString() function. You should keep a class level variable to track the last character upto which you have printed on the current page and then start from that point forward in the next iteration. You could use DrawString() overload that takes layout rectangle as parameter and send e.MarginBounds to it to let it automatically do word-wrapping for you.
Remember that this will only work with RichTextBox that has a single font used for all its text, which is highly unlikely given the very purpose of RichTextBox. For situations where you have multiple fonts, you'll need to call DrawString() many times for each character range comprising of a single font. As I said, this has lots of details (such as font kerning, hanging edges and other devils) that cannot be covered here. Keep reading and you'll find lots of good stuff on SO and other places.

vb.net 2010 PrintDocument Margins not working even if I set the margins

I am reading from a text file and then printing the string using printdocument via vb.net 2010.
Here is my code :
Public Class myPrinter
Friend TextToBePrinted As String
Public Sub prt(ByVal text As String)
Dim psize As New System.Drawing.Printing.PaperSize("Custom Paper Size", 850, 550)
Dim newMargins As New System.Drawing.Printing.Margins(0, 0, 0, 0)
TextToBePrinted = text
Dim prn As New Printing.PrintDocument
Using (prn)
prn.PrinterSettings.PrinterName = frmStockOut.printer
prn.PrinterSettings.Copies = frmStockOut.copies
prn.PrinterSettings.DefaultPageSettings.PaperSize = psize
prn.PrinterSettings.DefaultPageSettings.Margins = newMargins
prn.DefaultPageSettings.PaperSize = psize
prn.DefaultPageSettings.Margins = newMargins
AddHandler prn.PrintPage, _
AddressOf Me.PrintPageHandler
prn.Print()
RemoveHandler prn.PrintPage, _
AddressOf Me.PrintPageHandler
End Using
End Sub
Private Sub PrintPageHandler(ByVal sender As Object, _
ByVal args As Printing.PrintPageEventArgs)
Dim myFont As New Font("Courier New", 11)
args.Graphics.DrawString(TextToBePrinted, _
New Font(myFont, FontStyle.Regular), _
Brushes.Black, 50, 50)
End Sub
End Class
Private Sub PrintDocument1_PrintPage(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage
Dim charactersOnPage As Integer = 0
Dim linesPerPage As Integer = 0
' Sets the value of charactersOnPage to the number of characters
' of stringToPrint that will fit within the bounds of the page.
e.Graphics.MeasureString(stringToPrint, Me.Font, e.MarginBounds.Size, _
StringFormat.GenericTypographic, charactersOnPage, linesPerPage)
' Draws the string within the bounds of the page
e.Graphics.DrawString(stringToPrint, Me.Font, Brushes.Black, _
e.MarginBounds, StringFormat.GenericTypographic)
' Remove the portion of the string that has been printed.
stringToPrint = stringToPrint.Substring(charactersOnPage)
' Check to see if more pages are to be printed.
e.HasMorePages = stringToPrint.Length > 0
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
ReadFile() ' will read text file and store in a string
Dim Print As New myPrinter
Dim myprintdialog As New PrintDialog
With myprintdialog
If .ShowDialog = Windows.Forms.DialogResult.OK Then
printer = .PrinterSettings.PrinterName
copies = .PrinterSettings.Copies
Print.prt(stringToPrint)
End If
End With
End Sub
The problem is even after I set the left margin and top margin to 0, it seems nothing has changed, it is still printing almost 3/4 inch for top margins and 1 inch for the left margin. This is also the output when I didn't set the margins. However, when I prn.OriginAtMargins = True , the output becomes a little different, left margin is now almost 1/2 inch but top margin remains the same. Something wrong with my code?
What I want to accomplish is the top margin can be set at approximately 20 pixels (assuming 100 pixels is equal to 1 inch) and left margin be set at 20 pixels too. Hope somebody can help me.

hiding process icon to run in background

I have a programs path..like utorrent and it pid too. I have achieved these values programatically using vb.net. I just want to hide their icon form tray just to run them in background and if possible attach the process with a hotkey to call them back. Is there any way to achieve this.
Option Strict On
Option Explicit On
Option Infer Off
Imports TrayHelper
Public Class Form1
Dim x1, y1 As Single
Friend WithEvents lv As New ListView With {.Parent = Me, .Dock = DockStyle.Fill}
Private il As New ImageList
Dim nxt As Integer
Friend WithEvents mnuContextMenu As New ContextMenu() 'Moved this to be declared as global
Dim mnuItemHide As New MenuItem()
Dim mnuItemExit As New MenuItem()
Dim things As List(Of TrayButton) = TrayHelper.Tray.GetTrayButtons()
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.Controls.Add(lv)
lv.View = View.Details
il.ColorDepth = ColorDepth.Depth32Bit
lv.SmallImageList = il
lv.Columns.Add("Button Text", 300, HorizontalAlignment.Left)
lv.Columns.Add("PID", 50, HorizontalAlignment.Left)
lv.Columns.Add("Process Path", 600, HorizontalAlignment.Left)
'Dim things As List(Of TrayButton) = TrayHelper.Tray.GetTrayButtons()
For Each b As TrayButton In things
If b.Icon IsNot Nothing Then
il.Images.Add(b.TrayIndex.ToString, b.Icon)
Else
' When we can't find an icon, the listview will display this form's one.
' You could try to grab the icon from the process path I suppose.
il.Images.Add(b.TrayIndex.ToString, Me.Icon)
End If
Dim lvi As New ListViewItem(b.Text)
lvi.SubItems.Add(b.ProcessIdentifier.ToString)
lvi.SubItems.Add(b.ProcessPath)
lvi.ImageKey = b.TrayIndex.ToString
lv.Items.Add(lvi)
Next
lv.MultiSelect = False
'lv.ContextMenu = mnuContextMenu 'Don`t need to add if done this way
lv.FullRowSelect = True 'Added this but, you don`t need it if you don`t want it
mnuItemHide.Text = "&Hide"
mnuItemExit.Text = "&Exit"
mnuContextMenu.MenuItems.Add(mnuItemHide)
mnuContextMenu.MenuItems.Add(mnuItemExit)
AddHandler mnuItemHide.Click, AddressOf Me.menuItem1_Click
End Sub
Private Sub lv_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles lv.MouseDown
If e.Button = Windows.Forms.MouseButtons.Right Then
If lv.GetItemAt(e.X, e.Y) IsNot Nothing Then
lv.GetItemAt(e.X, e.Y).Selected = True
mnuContextMenu.Show(lv, New Point(e.X, e.Y))
mnuItemExit.Visible = True
mnuItemHide.Visible = True
End If
End If
End Sub
Private Sub menuItem1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim txtValue as String
txtValue = lv.FocusedItem.SubItems(2).Text
Kill(txtValue)
Dim txtValue1 As String
txtValue1 = lv.FocusedItem.SubItems(0).Text
MessageBox.Show(txtValue1 + " has been hidden")
End Sub
End Class
this is my code
To hide your form -> form1.visible=false
To hide your form from taskbar -> form1.ShowinTaskbar=false
then go to the form1 keydown event and put this...
If e.Control And e.KeyCode = Keys.Q Then ' ---> activate with Ctrl-Q
form1.visible=true
End If