How to Hide or Show Console Windows from WPF App

This post shows how to hide or show console window from your WPF app. The use case for this could be when your WPF app triggers some function that makes the console window visible. You might need to hide the console window programmatically from your WPF app.

If you are using a external functions from C++ app in your C# app then that might trigger a console window to be opened. From user’s point of view they won’t like to see the console window. It makes sense to hide the console window. Here’s how it can be done.

Step 1: Add a Native Methods class to expose the external C++ functions

Add the following class to your project.

static class NativeMethods
    {

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetConsoleWindow();

        [DllImport("user32.dll")]
        public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        public const int SW_HIDE = 0;
        public const int SW_SHOW = 5;
    }

The DllImport method uses the following namespace.

using System.Runtime.InteropServices;

If the namespace is not available in your project then add a reference to it by using the Add Reference option.

Step 2: Get the console window

To get a reference to the active console window use the following code snippet. You can put the code after the InitializeComponent() call in the constructor of the MainPage.xaml.cs.

var handle = NativeMethods.GetConsoleWindow();

Step 3: Hide or Show the Console Window

To hide the console window use the following code.

// Hide
NativeMethods.ShowWindow(handle, NativeMethods.SW_HIDE);

Similarly to show the console windows use the following code.

// Show
NativeMethods.ShowWindow(handle, NativeMethods.SW_SHOW);

That’s it. Run the project to see if it works.

How to Zoom Image in WPF app

This post shows how to zoom an image in WPF app. The image can be zoomed by rolling the mouse scroller or by double clicking on the image.

Step 1: Add the ZoomBorder Class to the project

Add the following ZoomBorder class to your project.

public class ZoomBorder : Border
    {
        private UIElement child = null;
        private Point origin;
        private Point start;

        private TranslateTransform GetTranslateTransform(UIElement element)
        {
            return (TranslateTransform)((TransformGroup)element.RenderTransform)
              .Children.First(tr => tr is TranslateTransform);
        }

        private ScaleTransform GetScaleTransform(UIElement element)
        {
            return (ScaleTransform)((TransformGroup)element.RenderTransform)
              .Children.First(tr => tr is ScaleTransform);
        }

        public override UIElement Child
        {
            get { return base.Child; }
            set
            {
                if (value != null && value != this.Child)
                    this.Initialize(value);
                base.Child = value;
            }
        }

        public void Initialize(UIElement element)
        {
            this.child = element;
            if (child != null)
            {
                TransformGroup group = new TransformGroup();
                ScaleTransform st = new ScaleTransform();
                group.Children.Add(st);
                TranslateTransform tt = new TranslateTransform();
                group.Children.Add(tt);
                child.RenderTransform = group;
                child.RenderTransformOrigin = new Point(0.0, 0.0);
                this.MouseWheel += child_MouseWheel;
                this.MouseLeftButtonDown += child_MouseLeftButtonDown;
                this.MouseLeftButtonUp += child_MouseLeftButtonUp;
                this.MouseMove += child_MouseMove;
                this.PreviewMouseRightButtonDown += new MouseButtonEventHandler(
                  child_PreviewMouseRightButtonDown);
            }
        }

        public void Reset()
        {
            if (child != null)
            {
                // reset zoom
                var st = GetScaleTransform(child);
                st.ScaleX = 1.0;
                st.ScaleY = 1.0;

                // reset pan
                var tt = GetTranslateTransform(child);
                tt.X = 0.0;
                tt.Y = 0.0;
            }
        }

        #region Child Events

        private void child_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (child != null)
            {
                var st = GetScaleTransform(child);
                var tt = GetTranslateTransform(child);

                double zoom = e.Delta > 0 ? .2 : -.2;
                if (!(e.Delta > 0) && (st.ScaleX < .4 || st.ScaleY < .4))
                    return;

                Point relative = e.GetPosition(child);
                double abosuluteX;
                double abosuluteY;

                abosuluteX = relative.X * st.ScaleX + tt.X;
                abosuluteY = relative.Y * st.ScaleY + tt.Y;

                st.ScaleX += zoom;
                st.ScaleY += zoom;

                tt.X = abosuluteX - relative.X * st.ScaleX;
                tt.Y = abosuluteY - relative.Y * st.ScaleY;
            }
        }

        private void child_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (child != null)
            {
                var tt = GetTranslateTransform(child);
                start = e.GetPosition(this);
                origin = new Point(tt.X, tt.Y);
                this.Cursor = Cursors.Hand;
                child.CaptureMouse();
            }
        }

        private void child_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (child != null)
            {
                child.ReleaseMouseCapture();
                this.Cursor = Cursors.Arrow;
            }
        }

        void child_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.Reset();
        }

        private void child_MouseMove(object sender, MouseEventArgs e)
        {
            if (child != null)
            {
                if (child.IsMouseCaptured)
                {
                    var tt = GetTranslateTransform(child);
                    Vector v = start - e.GetPosition(this);
                    tt.X = origin.X - v.X;
                    tt.Y = origin.Y - v.Y;
                }
            }
        }

        #endregion
    }

Step 2: Use the ZoomBorder class in your XAML page.

Firstly add a reference to the directory in which the ZoomBorder class in located. For example I have added the ZoomBorder class in Utils folder so i add a reference to this folder in the XAML page.

xmlns:utils="clr-namespace:MyProject.Utils"

Next wrap the image inside the ZoomBorder control.

<utils:ZoomBorder x:Name="border" ClipToBounds="True" Background="Gray">
    <Image Source="/myimage.png"/>
</utils:ZoomBorder>

That’s it. Deploy the project to see if it works. 🙂

Write DataGrid to CSV file in WPF app

This post shows how to write a DataGrid in WPF to a CSV file. We will export the data contained in the DataGrid along with the column headers to a CSV file. Here’s how it can be done.

Step 1: Build a CSV string from the DataGrid

Use the following method to convert a DataGrid to a CSV string.

public static string DataTable2CSV(DataGrid table, string separator=",")
{
    object[,] data = table.PrepareData();
    StringBuilder builder = new StringBuilder(Convert.ToString((char)65279));

    for (int k = 0; k < data.GetLength(0); k++)
    {
        List<string> tempList = new List<string>();
        for (int l = 0; l < data.GetLength(1); l++)
            tempList.Add(data[k, l].ToString());
        builder.Append(string.Join(separator, tempList)).Append(Environment.NewLine);
    }
    return builder.ToString();
}

The method accepts a DataGrid name as a parameter and converts it to a comma separated string value.

Step 2: Write the String to a Excel file.

Next write the above generated string to a excel file. The function WriteToXls takes the string to be written as an input and writes its to a excel file. It actually writes a CSV file which is saved with an .xlsx extension. It will open as an Excel file.

private string WriteToXls(string dataToWrite)
{
    try
    {
        string destination = DateTime.Now.ToString("dd_MM_yyyy_HH_mm") + LotNumber;
        foreach (char c in System.IO.Path.GetInvalidFileNameChars())
        {
            destination = destination.Replace(c, '_');
        }
        destination = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + destination + ".xlsx";
        FileStream fs = new FileStream(destination, FileMode.Create, FileAccess.Write);
        StreamWriter objWrite = new StreamWriter(fs);
        objWrite.Write(dataToWrite);
        objWrite.Close();
    }
    catch (Exception ex)
    {
        return null;
    }
}

Step 3: Use the above Methods to write to CSV

Here’s how you can use the above functions to write to CSV.

WriteToXls(DataTable2CSV(myDataGrid, ","));

Note: myDataGrid is the name of the DataGrid present in your XAML page.

Call C-Sharp from javaScript using CefSharp in WPF app

Here’s how you can invoke a C# function from javaScript while using CefSharp in a WPF app.

Step 1: Create a Class with the Method to be Invoked

Create a CallbackObjectForJs class that contains a showMessage function which would be invoked from javascript.

public class CallbackObjectForJs{
    public void showMessage(string msg){//Read Note
        MessageBox.Show(msg);
    }
}

Step 2: Register the JS object

The next step is to register the JS object. This can be done by adding the following code in the MainPage.xaml.cs file.

private CallbackObjectForJs _callBackObjectForJs;
public MainWindow()
{
    InitializeComponent();
    _callBackObjectForJs= new CallbackObjectForJs();
    ChromiumWebBrowser.RegisterAsyncJsObject("callbackObj", _callBackObjectForJs);
}

Step 3: Invoke the C# function from JavaScript

Next, simply invoke the C# function from your javascript code.

<script>
    callbackObj.showMessage("Hello World!");
</script>

Note: The name of the C# function should start with a small letter.

Using Chromium Web Browser Control in WPF app

WebBroswer control in WPF by default uses IE 7 engine for rendering webpages. This may become an issue while displaying modern websites. There are two alternatives. One is to use browser emulation feature to use a different IE version browser instead of IE 7. How that can be done is explained in this post.

Using Browser Emulation for Web Browser control in WPF app

The other way is to use V8 engine(Chromium) used by Google Chrome. There are various libraries that let you use Chromium browser in your WPF project. We will be using the CefSharp library. You can read more about the various options available for using Chromium engine in WPF app.

CefSharp is a C# import for Cef framework. It is available as a Nuget package too.

Step 1: Install the CefSharp library

Install the CefSharp library using nuget. Here’s the link to the Nuget package.
https://www.nuget.org/packages/CefSharp.Wpf

You could refer to this article if you need assistance in adding a Nuget package to your project in Visual Studio.

Initialize the Cef browser in App.xaml.cs

You need to initialize the browser with some default settings. Here’s the code that you need to add in your project’s App.xaml.cs. This is required because of a known issue (#1634) that makes the screen flicker after the page is loaded.

public App()
{  
    //Perform dependency check to make sure all relevant resources are in our output directory.
    var settings = new CefSettings();
    settings.EnableInternalPdfViewerOffScreen();
    // Disable GPU in WPF and Offscreen examples until #1634 has been resolved
    settings.CefCommandLineArgs.Add("disable-gpu", "1");
    settings.CachePath = "cache";
    
    Cef.Initialize(settings, shutdownOnProcessExit: true, performDependencyCheck: true);
}

Add a reference to CefSharp in MainPage.xaml

Add a reference in MainPage.xaml before you could use it.

xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"

Add the Chromium Web Browser control in your page

Now you can add the web browser control in your page. Here’s the code that is required.

<cefSharp:ChromiumWebBrowser
        x:Name="ChromiumWebBrowser"
        Address="http://www.google.com" />

That’s it you are done. Try deploying the app to see if it works.

Using Browser Emulation for Web Browser control in WPF app

WebBrowser control in WPF by default uses IE 7 browser engine to render webpages. This may not be desired in some situations as modern websites are not rendered correctly on IR 7. You may get other version of IE working with the WebBrowser control using the browser emulation feature in WPF. This is not a trivial thing to do and requires a couple of registry changes. Here’s how it can be done.

Step 1: Define an enum for the Different Browser Versions

We define an enum that contains the different IE browser versions.

public enum BrowserEmulationVersion
{
    Default = 0,
    Version7 = 7000,
    Version8 = 8000,
    Version8Standards = 8888,
    Version9 = 9000,
    Version9Standards = 9999,
    Version10 = 10000,
    Version10Standards = 10001,
    Version11 = 11000,
    Version11Edge = 11001
}

Step 2: Add Browser Emulation class

Add the following class ie InternetExplorerBrowserEmulation class to your project. We will be calling functions from this class to use browser emulation in our project.

public class InternetExplorerBrowserEmulation
{
    private const string InternetExplorerRootKey = @"Software\Microsoft\Internet Explorer";
    private const string BrowserEmulationKey = InternetExplorerRootKey + @"\Main\FeatureControl\FEATURE_BROWSER_EMULATION";


    public static int GetInternetExplorerMajorVersion()
    {
        int result;

        result = 0;

        try
        {
            RegistryKey key;

            key = Registry.LocalMachine.OpenSubKey(InternetExplorerRootKey);

            if (key != null)
            {
                object value;

                value = key.GetValue("svcVersion", null) ?? key.GetValue("Version", null);

                if (value != null)
                {
                    string version;
                    int separator;

                    version = value.ToString();
                    separator = version.IndexOf('.');
                    if (separator != -1)
                    {
                        int.TryParse(version.Substring(0, separator), out result);
                    }
                }
            }
        }
        catch (SecurityException)
        {
            // The user does not have the permissions required to read from the registry key.
        }
        catch (UnauthorizedAccessException)
        {
            // The user does not have the necessary registry rights.
        }

        return result;
    }

    public static bool SetBrowserEmulationVersion(BrowserEmulationVersion browserEmulationVersion)
    {
        bool result;

        result = false;

        try
        {
            RegistryKey key;

            key = Registry.CurrentUser.OpenSubKey(BrowserEmulationKey, true);

            if (key != null)
            {
                string programName;

                programName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);

                if (browserEmulationVersion != BrowserEmulationVersion.Default)
                {
                    // if it's a valid value, update or create the value
                    key.SetValue(programName, (int)browserEmulationVersion, RegistryValueKind.DWord);
                }
                else
                {
                    // otherwise, remove the existing value
                    key.DeleteValue(programName, false);
                }

                result = true;
            }
        }
        catch (SecurityException)
        {
            // The user does not have the permissions required to read from the registry key.
        }
        catch (UnauthorizedAccessException)
        {
            // The user does not have the necessary registry rights.
        }

        return result;
    }

    public static bool SetBrowserEmulationVersion()
    {
        int ieVersion;
        BrowserEmulationVersion emulationCode;

        ieVersion = GetInternetExplorerMajorVersion();

        if (ieVersion >= 11)
        {
            emulationCode = BrowserEmulationVersion.Version11;
        }
        else
        {
            switch (ieVersion)
            {
                case 10:
                    emulationCode = BrowserEmulationVersion.Version10;
                    break;
                case 9:
                    emulationCode = BrowserEmulationVersion.Version9;
                    break;
                case 8:
                    emulationCode = BrowserEmulationVersion.Version8;
                    break;
                default:
                    emulationCode = BrowserEmulationVersion.Version7;
                    break;
            }
        }

        return SetBrowserEmulationVersion(emulationCode);
    }

    public static BrowserEmulationVersion GetBrowserEmulationVersion()
    {
        BrowserEmulationVersion result;

        result = BrowserEmulationVersion.Default;

        try
        {
            RegistryKey key;

            key = Registry.CurrentUser.OpenSubKey(BrowserEmulationKey, true);
            if (key != null)
            {
                string programName;
                object value;

                programName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
                value = key.GetValue(programName, null);

                if (value != null)
                {
                    result = (BrowserEmulationVersion)Convert.ToInt32(value);
                }
            }
        }
        catch (SecurityException)
        {
            // The user does not have the permissions required to read from the registry key.
        }
        catch (UnauthorizedAccessException)
        {
            // The user does not have the necessary registry rights.
        }

        return result;
    }


    public static bool IsBrowserEmulationSet()
    {
        return GetBrowserEmulationVersion() != BrowserEmulationVersion.Default;
    }
}

Step 3: Use the Browser Emulation class

Finally use the browser emulation class as follows. You could include the code for browser emulation in MainPage.xaml.cs constructor itself.

if (!InternetExplorerBrowserEmulation.IsBrowserEmulationSet())
{
  InternetExplorerBrowserEmulation.SetBrowserEmulationVersion();
}

Note: This works only if you change the browser version before loading any WebBrowser control.

How to Scan an Image using Interop.WIA in a WPF app

This post shows how to scan an image using a scanner in a WPF app.

Step 1: Add a Reference to WIA dll

Firstly, you need a reference to Interop.WIA.dll in the project. Download the dll file from the following link.

Download Interop.WIA.dll

Once you have downloaded the dll file add a reference to it by right click on the project name and selecting Add > Reference.

Add a reference to Interop.WIA.dll

Step 2: Add the ScannerService class to the project

Here’s the complete code for the ScannerService class that you can directly include in your project.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using WIA;

namespace WPF_Example.Services
{
    public class ScannerService
    {
        public static void Scan()
        {
            try
            {
                CommonDialogClass commonDialogClass = new CommonDialogClass();
                Device scannerDevice = commonDialogClass.ShowSelectDevice(WiaDeviceType.ScannerDeviceType, false, false);
                if (scannerDevice != null)
                {
                    Item scannnerItem = scannerDevice.Items[1];
                    AdjustScannerSettings(scannnerItem, 600, 0, 0, 1010, 620, 0, 0);
                    object scanResult = commonDialogClass.ShowTransfer(scannnerItem, WIA.FormatID.wiaFormatPNG, false);
                    if (scanResult != null)
                    {
                        ImageFile image = (ImageFile)scanResult;
                        SaveImageToJpgFile(image, Constants.ScannedImageLocation);
                     }
                }
            }
            catch (System.Runtime.InteropServices.COMException)
            {
                MessageBox.Show("Problem with scanning device. Please ensure that the scanner is properly connected and switched on", "Inweon Grain Management System");
            }
        }

        private static void AdjustScannerSettings(IItem scannnerItem, int scanResolutionDPI, int scanStartLeftPixel, int scanStartTopPixel,
            int scanWidthPixels, int scanHeightPixels, int brightnessPercents, int contrastPercents)
        {
            const string WIA_HORIZONTAL_SCAN_RESOLUTION_DPI = "6147";
            const string WIA_VERTICAL_SCAN_RESOLUTION_DPI = "6148";
            const string WIA_HORIZONTAL_SCAN_START_PIXEL = "6149";
            const string WIA_VERTICAL_SCAN_START_PIXEL = "6150";
            const string WIA_HORIZONTAL_SCAN_SIZE_PIXELS = "6151";
            const string WIA_VERTICAL_SCAN_SIZE_PIXELS = "6152";
            const string WIA_SCAN_BRIGHTNESS_PERCENTS = "6154";
            const string WIA_SCAN_CONTRAST_PERCENTS = "6155";
            const string WIA_SCAN_BIT_DEPTH = "4104";
            SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_RESOLUTION_DPI, scanResolutionDPI);
            SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_RESOLUTION_DPI, scanResolutionDPI);
            SetWIAProperty(scannnerItem.Properties, WIA_HORIZONTAL_SCAN_START_PIXEL, scanStartLeftPixel);
            SetWIAProperty(scannnerItem.Properties, WIA_VERTICAL_SCAN_START_PIXEL, scanStartTopPixel);
            //SetWIAProperty(scannnerItem.Properties, WIA_SCAN_BIT_DEPTH, 48);
            SetWIAProperty(scannnerItem.Properties, WIA_SCAN_BRIGHTNESS_PERCENTS, brightnessPercents);
            SetWIAProperty(scannnerItem.Properties, WIA_SCAN_CONTRAST_PERCENTS, contrastPercents);
        }

        private static void SetWIAProperty(IProperties properties, object propName, object propValue)
        {
            Property prop = properties.get_Item(ref propName);
            prop.set_Value(ref propValue);
        }

        private static void SaveImageToJpgFile(ImageFile image, string fileName)
        {
            ImageProcess imgProcess = new ImageProcess();
            object convertFilter = "Convert";
            string convertFilterID = imgProcess.FilterInfos.get_Item(ref convertFilter).FilterID;
            imgProcess.Filters.Add(convertFilterID, 0);
            SetWIAProperty(imgProcess.Filters[imgProcess.Filters.Count].Properties, "FormatID", WIA.FormatID.wiaFormatJPEG);
            image = imgProcess.Apply(image);
            image.SaveFile(fileName);
        }
    }
}

Use the Scan function

To use ScannerService simply use the following code.

ScannerService.Scan();

How to Print an Existing Excel File Using C#

In this tutorial I will show you how to print a Excel file using a WPF app. You might also want to look at a related post.

Create and Download Excel File Using PHP

Step 1: Add a reference to Excel Interop in your Project

Add a reference to Microsoft.Office.Interop.Excel in your project by right clicking on References, Add Reference from the Solution Explorer. Next choose Microsoft.Office.Interop.Excel from the Extensions tab under Assemblies.

Add a using statement at the top of the page in which you want to add the print XlS function.

using Excel= Microsoft.Office.Interop.Excel;

Step 2: Define Public Variables for Excel

Define the following variables before the class constructor.

public Excel.Application APP = null;
public Excel.Workbook WB = null;
public Excel.Worksheet WS = null;
public Excel.Range Range = null;  

Step 3: Add the Method to Print Excel

The following function opens a Excel file to print it and then closes it again.

void PrintMyExcelFile()
{
    this.APP = new Microsoft.Office.Interop.Excel.Application(); 

    // Open the Workbook:
    this.Open("C:\\Users\\maska\\Documents\\MyExcel.xlsx", 1);

    // Get the first worksheet.
    // (Excel uses base 1 indexing, not base 0.)
    WS = (Excel.Worksheet)WB.Worksheets[1];

    // Print out 1 copy to the default printer:
    WS.PrintOut(
        Type.Missing, Type.Missing, Type.Missing, Type.Missing,
        Type.Missing, Type.Missing, Type.Missing, Type.Missing);

    // Cleanup:
    GC.Collect();
    GC.WaitForPendingFinalizers();

    Marshal.FinalReleaseComObject(WS);

    WB.Close(false, Type.Missing, Type.Missing);
    Marshal.FinalReleaseComObject(WB);

    APP.Quit();
    Marshal.FinalReleaseComObject(APP);
}

That’s it. Call this method to print an existing excel file.