[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now

x
?
Solved

Printing a screen shot from VB.net

Posted on 2010-09-22
10
Medium Priority
?
842 Views
Last Modified: 2012-05-10
Hello All
I have been working on some code that will do a screen capture and then save as a file. This is working OK so now i want to either automatically print the file or automatically attach to an email

Code i have so far is

 Private Sub Button8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button8.Click
        ' Copy the form's image into a bitmap.Needed for screen print
        Screenshot.CreateBitmap()
    End Sub

    Public Class Screenshot
        Public Declare Function BitBlt Lib "gdi32" Alias "BitBlt" (ByVal hDestDC As Integer, ByVal x As Integer, ByVal y As Integer, ByVal nWidth As Integer, ByVal nHeight As Integer, ByVal hSrcDC As Integer, ByVal xSrc As Integer, ByVal ySrc As Integer, ByVal dwRop As Integer) As Integer
        Public Declare Function GetWindowDC Lib "user32" Alias "GetWindowDC" (ByVal hwnd As Integer) As Integer
        Public Declare Function ReleaseDC Lib "user32" Alias "ReleaseDC" (ByVal hwnd As Integer, ByVal hdc As Integer) As Integer
        Public Const SRCCOPY As Integer = &HCC0020

        Public Shared Sub CreateBitmap()
            Dim gDest As Graphics
            Dim hdcDest As IntPtr
            Dim hdcSrc As Integer
            Dim MyProcess As New Process
            Dim hWnd As Integer '= Control.Handle.ToInt32
            Dim bmp As Bitmap
            hWnd = Process.GetCurrentProcess.MainWindowHandle.ToInt32
            bmp = New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
            gDest = Graphics.FromImage(bmp)
            hdcSrc = GetWindowDC(hWnd)
            hdcDest = gDest.GetHdc
            BitBlt(hdcDest.ToInt32, 0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, hdcSrc, 0, 0, SRCCOPY)
            gDest.ReleaseHdc(hdcDest)
            ReleaseDC(hWnd, hdcSrc)
            bmp.Save("C:\BITMAP.png")
           
        End Sub

    End Class

Question is now how best to print the file automatically with no user interference and how best to attach to an email

the file format doesnt have to be PNG if any one has a better suggestion

Many thanks in advance
0
Comment
Question by:bostonste
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 3
10 Comments
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 33737386
Your other questions list VB.Net 2008...if this is the case then you can simplify with:

    Private Sub Button8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button8.Click
        Dim bmp As New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
        Using G As Graphics = Graphics.FromImage(bmp)
            G.CopyFromScreen(0, 0, 0, 0, bmp.Size)
        End Using
        bmp.Save("C:\Screenshot.png", System.Drawing.Imaging.ImageFormat.Png)
    End Sub

*Note that you were not actually saving a PNG in the original code as you have to explicitly set the second parameter.  What you were doing was saving a Bitmap with a .png extension.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 33737394
You can print the image using the PrintDocument() class:
http://msdn.microsoft.com/en-us/library/system.drawing.printing.printdocument.aspx
0
 
LVL 12

Expert Comment

by:Anuradha Goli
ID: 33739296
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;


public partial class Form1 : System.Windows.Forms.Form
{
    private System.ComponentModel.Container components;
    private System.Windows.Forms.Button printButton;
    private Font printFont;
    private StreamReader streamToPrint;

    public Form1()
    {
        // The Windows Forms Designer requires the following call.
        InitializeComponent();
    }

    // The Click event is raised when the user clicks the Print button.
    private void printButton_Click(object sender, EventArgs e)
    {
        try
        {
            streamToPrint = new StreamReader
               ("C:\\My Documents\\MyFile.txt");
            try
            {
                printFont = new Font("Arial", 10);
                PrintDocument pd = new PrintDocument();
                pd.PrintPage += new PrintPageEventHandler
                   (this.pd_PrintPage);
                pd.Print();
            }
            finally
            {
                streamToPrint.Close();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

    // The PrintPage event is raised for each page to be printed.
    private void pd_PrintPage(object sender, PrintPageEventArgs ev)
    {
        float linesPerPage = 0;
        float yPos = 0;
        int count = 0;
        float leftMargin = ev.MarginBounds.Left;
        float topMargin = ev.MarginBounds.Top;
        string line = null;

        // Calculate the number of lines per page.
        linesPerPage = ev.MarginBounds.Height /
           printFont.GetHeight(ev.Graphics);

        // Print each line of the file.
        while (count < linesPerPage &&
           ((line = streamToPrint.ReadLine()) != null))
        {
            yPos = topMargin + (count *
               printFont.GetHeight(ev.Graphics));
            ev.Graphics.DrawString(line, printFont, Brushes.Black,
               leftMargin, yPos, new StringFormat());
            count++;
        }

        // If more lines exist, print another page.
        if (line != null)
            ev.HasMorePages = true;
        else
            ev.HasMorePages = false;
    }


    // The Windows Forms Designer requires the following procedure.
    private void InitializeComponent()
    {
        this.components = new System.ComponentModel.Container();
        this.printButton = new System.Windows.Forms.Button();

        this.ClientSize = new System.Drawing.Size(504, 381);
        this.Text = "Print Example";

        printButton.ImageAlign =
           System.Drawing.ContentAlignment.MiddleLeft;
        printButton.Location = new System.Drawing.Point(32, 110);
        printButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        printButton.TabIndex = 0;
        printButton.Text = "Print the file.";
        printButton.Size = new System.Drawing.Size(136, 40);
        printButton.Click += new System.EventHandler(printButton_Click);

        this.Controls.Add(printButton);
    }

}
0
NFR key for Veeam Backup for Microsoft Office 365

Veeam is happy to provide a free NFR license (for 1 year, up to 10 users). This license allows for the non‑production use of Veeam Backup for Microsoft Office 365 in your home lab without any feature limitations.

 

Author Comment

by:bostonste
ID: 33741799
Hello All

After reading all your posts i have made adjustments to my code as folows
 Private Sub Button8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button8.Click
        ' Copy the form's image into a bitmap.Needed for screen print
        Dim bmp As New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
        Using G As Graphics = Graphics.FromImage(bmp)
            G.CopyFromScreen(0, 0, 0, 0, bmp.Size)
        End Using
        bmp.Save("C:\Screenshot.bmp", System.Drawing.Imaging.ImageFormat.Bmp)
        streamToPrint = New StreamReader("C:\Screenshot.bmp")
        Try
            printFont = New Font("Arial", 10)
            Dim pd As New PrintDocument()
            AddHandler pd.PrintPage, AddressOf Me.pd_PrintPage
            pd.Print()
        Finally
            streamToPrint.Close()
        End Try
    End Sub
    Private Sub pd_PrintPage(ByVal sender As Object, ByVal ev As PrintPageEventArgs)
        Dim linesPerPage As Single = 0
        Dim yPos As Single = 0
        Dim count As Integer = 0
        Dim leftMargin As Single = ev.MarginBounds.Left
        Dim topMargin As Single = ev.MarginBounds.Top
        Dim line As String = Nothing
        ' Calculate the number of lines per page.
        linesPerPage = ev.MarginBounds.Height / printFont.GetHeight(ev.Graphics)
        ' Print each line of the file.
        While count < linesPerPage
            line = streamToPrint.ReadLine()
            If line Is Nothing Then
                Exit While
            End If
            yPos = topMargin + count * printFont.GetHeight(ev.Graphics)
            ev.Graphics.DrawString(line, printFont, Brushes.Black, leftMargin, yPos, New StringFormat())
            count += 1
        End While
        ' If more lines exist, print another page.
        If (line IsNot Nothing) Then
            ev.HasMorePages = True
        Else
            ev.HasMorePages = False
        End If
    End Sub

This saves a screen shot , starts the print process but it then gives me numerous pages of rubbish instead of a picture.

Where have i gone wrong

Cheers
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 33743774
Just move the "bmp" declaration up to CLASS level:

    Private bmp As Bitmap

    Private Sub Button8_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button8.Click
        ' Copy the form's image into a bitmap.Needed for screen print
        bmp = New Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)

Then use DrawImage() in the PrintPage() event:

    ev.Graphics.DrawImage(bmp, x, y)
0
 

Author Comment

by:bostonste
ID: 33745411
Almost there and many thanks so far

I now have this code for the printpage event

       Dim linesPerPage As Single = 0
        Dim yPos As Single = 0
        Dim xPos As Single = 0
        Dim count As Integer = 0
        Dim leftMargin As Single = ev.MarginBounds.Left
        Dim topMargin As Single = ev.MarginBounds.Top
        Dim line As String = Nothing
        ' Calculate the number of lines per page.
        linesPerPage = ev.MarginBounds.Height / printFont.GetHeight(ev.Graphics)
        ' Print each line of the file.
        While count < linesPerPage
            line = streamToPrint.ReadLine()
            If line Is Nothing Then
                Exit While
            End If
            yPos = topMargin + count * printFont.GetHeight(ev.Graphics)
            ev.Graphics.DrawImage(bmp, leftMargin, topMargin)
            count += 1
        End While
        ev.HasMorePages = False
    End Sub

wich does print but , but only about a quarter of the screen shot on a page, is it possible to make it all fit on a single page
(A4)

Thanks
0
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 2000 total points
ID: 33745639
Sure...look at all the overloads for DrawImage():
http://msdn.microsoft.com/en-us/library/system.drawing.graphics.drawimage.aspx

You can specify a "destination size" which will resize the image into that area...LOTS of different ways to do it!

This overload simply takes a Rectangle specify the destination location/size:
http://msdn.microsoft.com/en-us/library/yws82c40.aspx

    "Draws the specified Image at the specified location and with the specified size."

So you'd define a Rectangle like this:

    Dim rc As New Rectangle(leftMargin, topMargin, desiredWidthHere, desiredHeightHere)

Then pass that to DrawImage():

    ev.Graphics.DrawImage(bmp, rc)

*If your only printing ONE page then get rid of all the paging code!
0
 

Author Closing Comment

by:bostonste
ID: 33745803
My code is now down to this
    Dim leftMargin As Single = 5 'ev.MarginBounds.Left
        Dim topMargin As Single = 5 'ev.MarginBounds.Top
        Dim rc As New Rectangle(leftMargin, topMargin, 850, 1100)
        ev.Graphics.DrawImage(bmp, rc)
    End Sub

many thanks

On a side note is it possible to amend my code to only capture the active form on the screen rather than the whols screen ??
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 33746525
Yes...but you have to use some APIs to accomplish this...

First, get the "active" window with GetForegroundWindow(), then pass that to GetWindowRect() to determine its location/size.  Armed with that info you can now modify your existing code to only read that portion of the screen:

    Public Structure RECT
        Public Left As Integer
        Public Top As Integer
        Public Right As Integer
        Public Bottom As Integer
    End Structure

    Private Declare Function GetWindowRect Lib "user32" Alias "GetWindowRect" _
        (ByVal hWnd As IntPtr, ByRef lpRect As RECT) As Integer

    Private Declare Function GetForegroundWindow Lib "user32.dll" () As IntPtr

To get the active window and its location/size:

    Dim ActiveWindow As IntPtr = GetForegroundWindow()
    Dim ActiveRECT As RECT
    GetWindowRect(ActiveWindow, ActiveRect)
    Dim sz As New Size(ActiveRECT.Right - ActiveRECT.Left + 1, ActiveRECT.Bottom - ActiveRECT.Top + 1)
 
Now use "ActiveRECT" and "sz" in the CopyFromScreen() call:

    G.CopyFromScreen(ActiveRECT.Left, ActiveRECT.Top, 0, 0, sz)
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 33746542
*Also use "sz" to determine the size of your dynamic Bitmap:

    Dim bmp As New Bitmap(sz.Width, sz.Height)
    Using G As Graphics = Graphics.FromImage(bmp)
        G.CopyFromScreen(ActiveRECT.Left, ActiveRECT.Top, 0, 0, sz)
    End Using
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
This article is meant to give a basic understanding of how to use R Sweave as a way to merge LaTeX and R code seamlessly into one presentable document.
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

649 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question