Posts


C# version of turning a website into a chm file. Requires that html workshop (http://msdn.microsoft.com/library/en-us/htmlhelp/html/vsconhh1start.asp) is installed. If anyone knows of a working open source chm compiler let me know.

Can be used like: html2chm.Html2chm action = new html2chm.Html2chm(); This will run and prompt you for which website directory and which file in the directory to convert to a chm file.

Or it can be used like this: bool eachFileAsTopic = true; html2chm.Html2chm action = new html2chm.Html2chm(@”\Path\to\directory\to\convert”, @”mainTopic.html”, eachFileAsTopic);

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Diagnostics;


namespace html2chm
{

    public class Html2chm
    {
        //http://www.majorsilence.com/csharp_html2chm
        //The generated CHM file is named YourCHMFile.chm on your desktop.

        string HHC;
        // Path to hhc.exe

        // Directory path where HHP file is stored
        // and base directory of the html files to be converted
        string RepBase;

        string FicHHP;
        // Path to HHP file

        string fileListString;


        public Html2chm() : this("", "", false)
        {
        }

        public Html2chm(string convertDirectory, string mainTopic, bool filesAsTopics)
        {
            List<string> fileList = new List<string>();

            HHC = System.IO.Path.Combine("C:\\Program Files\\HTML Help Workshop", "hhc.exe");

            if (System.IO.File.Exists(HHC) == false)
            {
                HHC = System.IO.Path.Combine("C:\\Program Files (x86)\\HTML Help Workshop", "hhc.exe");
                if (System.IO.File.Exists(HHC) == false)
                {
                    MessageBox.Show("In order to use this script, you need HTML Help Workshop" + System.Environment.NewLine + "http://msdn.microsoft.com/library/en-us/htmlhelp/html/vsconhh1start.asp");
                    return;
                }
            }

            if (convertDirectory == string.Empty)
            {
                System.Windows.Forms.FolderBrowserDialog DirectoryBrowser = default(System.Windows.Forms.FolderBrowserDialog);
                DirectoryBrowser = new System.Windows.Forms.FolderBrowserDialog();
                DirectoryBrowser.Description = "Which directory do you want to use?";
                if ((DirectoryBrowser.ShowDialog() == System.Windows.Forms.DialogResult.OK))
                {
                    RepBase = DirectoryBrowser.SelectedPath;
                }
            }
            else
            {
                RepBase = convertDirectory;
            }


            if (RepBase == null)
            {

                MessageBox.Show("Please choose a Folder");
            }
            else
            {
                fileList.AddRange(RecursiveFileList(new DirectoryInfo(RepBase), new DirectoryInfo(RepBase)));
                string fileHHC="";
                string FicHHC = System.IO.Path.Combine(RepBase, "chm-editor-Temp-HHC.hhc");
                foreach (string s in fileList)
                {
                    this.fileListString += s + System.Environment.NewLine;

                    if (filesAsTopics)
                    {
                        string value = s.Replace(RepBase, "");

                        string textValue = ""; 

                        if (value.StartsWith("\\"))
                        {
                            value = value.Remove(0, 1);
                        }

                        textValue = System.IO.Path.GetFileName(value); 
                        textValue = textValue.Replace(System.IO.Path.GetExtension(textValue), "");

                        fileHHC += "<LI><OBJECT type=\"text/sitemap\"><PARAM name=\"Name\" value=\"" + textValue + "\"><PARAM name=\"Local\" value=\"" + value + "\"><PARAM name=\"ImageNumber\" value=\"0\"></OBJECT>";
                    }
                }

                if (filesAsTopics)
                {
                    System.IO.File.WriteAllText(FicHHC, fileHHC);
                }

                FicHHP = System.IO.Path.Combine(RepBase, "chm-editor-Temp" + DateTime.Now.Millisecond.ToString() + ".HHP");
                string output = "[OPTIONS]" + System.Environment.NewLine;
                output += "Compatibility=1.1 or later" + System.Environment.NewLine;
                output += "Compiled file=" + System.IO.Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "YourCHMFile.chm") + System.Environment.NewLine;
                string main_topic;

                if (mainTopic == string.Empty)
                {
                    main_topic = MainTopic();
                }
                else
                {
                    main_topic = mainTopic;
                }

                if (filesAsTopics)
                {
                    output += "Contents file=" + FicHHC + System.Environment.NewLine;
                }

                output += "Default topic=" + main_topic.Substring(RepBase.Length + 1, main_topic.Length - (RepBase.Length + 1)) + System.Environment.NewLine; //Strings.Mid(MainTopic(), Strings.Len(RepBase) + 2) + System.Environment.NewLine;
                output += "Display compile progress=No" + System.Environment.NewLine;
                output += "Language=0x409 English (standard)" + System.Environment.NewLine;
                // 0x40C - French
                // 0x407 - German
                output += "Title=(c) 2010 MajorSilence" + System.Environment.NewLine;
                output += System.Environment.NewLine + "[FILES]" + System.Environment.NewLine;
                output += this.fileListString + System.Environment.NewLine;
                output += System.Environment.NewLine + "[INFOTYPES]" + System.Environment.NewLine;

                System.IO.File.WriteAllText(FicHHP, output);

                System.Diagnostics.Process p = new System.Diagnostics.Process();
                p.StartInfo.FileName = HHC;
                p.StartInfo.Arguments = FicHHP;
                p.StartInfo.CreateNoWindow = true;
                p.Start();
                p.WaitForExit();

                // Finally Remove 
                try
                {
                    System.IO.File.Delete(FicHHP);

                    if (System.IO.File.Exists(FicHHC))
                    {
                        System.IO.File.Delete(FicHHC);
                    }
                }
                catch (Exception ex)
                {
                }
            }

            
        }

        // Recurse through directory and return string of files
        public List<String> RecursiveFileList(DirectoryInfo source, DirectoryInfo target)
        {
            // loop through each file in current directory
            List<string> fileList = new List<string>();

            foreach (FileInfo file in source.GetFiles())
            {
                if (file.Name.ToLower().EndsWith("html") | file.Name.ToLower().EndsWith("htm") | file.Name.ToLower().EndsWith("mov") | file.Name.ToLower().EndsWith("au"))
                {
                    fileList.Add(file.FullName);

                }
            }

            // Then loop through each directory
            foreach (DirectoryInfo dir in source.GetDirectories())
            {
                fileList.AddRange(RecursiveFileList(dir, new DirectoryInfo(dir.Name)));
            }


            return fileList;
        }


        // Select the root file (Main topic) in base directory
        public string MainTopic()
        {
            System.Windows.Forms.OpenFileDialog dlg = new System.Windows.Forms.OpenFileDialog();

            if (dlg.ShowDialog() == DialogResult.OK)
            {
                return dlg.FileName;
            }

            return string.Empty;
        }

    }

}


I needed a screen video capture software that was free and open source and worked with several different video types. I also wanted the program to record the proper screen colours. So I wrote a small program to do this. It uses mencoder to do the video processing so I will be able to add almost any video format as the output. Current it outputs mpeg/mp3 in an avi container.

See the two attached files. Warning, this is very alpha quality software. When doing a new recording always make sure it is in a new empty folder. It should not harm any other files but I would not take the chance. Tested on 64 bit Vista. Not sure how well it will work on Windows XP or 7.

It currently uses a lot of memory. Can only record from the primary screen. Only does full screen recordings. Which is fine for my needs.

It also currently highlights the mouse location and records from the computer mic.

UPDATE: Get the latest release and news from http://majorsilence.com/screen_video_capture


So I can now play Cocaine Cowgirl acceptably good.

List of songs that that I can play but need more practice: Wonderwall Feliz Navidad O Holy Night I Don’t want to miss a thing Winter wonderland Have yourself a merry little Christmas Leaving on a jet plane I’m Yours


Simple download file example. Works with http, https, and ftp. If username and password are required add them to the client using System.Net.NetworkCredential(“username”, “password”).

Use the WebClient DownloadProgressChanged and DownloadFileCompleted events to display percent and start on finish action.

These examples will not work unless you create a winform to go along with them.

VB.net

Imports System.IO
Imports System.Net
Imports System.Threading
Imports System.Text

Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDownload.Click
        download(txtDownloadPath.Text.Trim, txtSavePath.Text.Trim)
    End Sub

    Private Shared percent As Integer = 0

    Public Sub Download(ByVal urlPath As String, ByVal savePath As String)
        Dim client As WebClient = New WebClient()
        'client.Credentials = New System.Net.NetworkCredential("username", "password")

        AddHandler client.DownloadProgressChanged, AddressOf ClientDownloadProgressChanged
        AddHandler client.DownloadFileCompleted, AddressOf ClientDownloadFileCompleted

        client.DownloadFileAsync(New Uri(urlPath), savePath)

    End Sub

    Private Sub ClientDownloadProgressChanged(ByVal sender As Object, ByVal e As DownloadProgressChangedEventArgs)

        Dim bytesIn As Double = Double.Parse(e.BytesReceived.ToString())
        Dim totalBytes As Double = Double.Parse(e.TotalBytesToReceive.ToString())
        Dim percentage As Double = bytesIn / totalBytes * 100

        ProgressBar1.Value = Integer.Parse(Math.Truncate(percentage).ToString())
        PaintProgressBarPercent(ProgressBar1)
    End Sub

    Private Sub ClientDownloadFileCompleted(ByVal sender As Object, ByVal e As EventArgs)
        'AsyncCompletedEventArgs
        MessageBox.Show("Download Completed")
    End Sub

    Private Sub PaintProgressBarPercent(ByRef a As ProgressBar)
        Dim percent As Integer = CInt(((CDbl((ProgressBar1.Value - ProgressBar1.Minimum)) / CDbl((ProgressBar1.Maximum - ProgressBar1.Minimum))) * 100))

        Using gr As Graphics = ProgressBar1.CreateGraphics()
            Dim p1 As New PointF(CType(a.Width / 2 - (gr.MeasureString(percent & "%", SystemFonts.DefaultFont).Width / 2.0F), Single), CType(a.Height / 2 - (gr.MeasureString(percent & "%", SystemFonts.DefaultFont).Height / 2.0F), Single))
            Try
                gr.DrawString(percent & "%", SystemFonts.DefaultFont, Brushes.Black, p1)
            Catch ex As Exception
            End Try

        End Using

    End Sub

End Class

C# Example

using System.IO;
using System.Net;
using System.Threading;
using System.Text;

public class Form1
{
    private void Button1_Click(System.Object sender, System.EventArgs e)
    {
        download(txtDownloadPath.Text.Trim, txtSavePath.Text.Trim);
    }
    
    private static int percent = 0;
    
    public void Download(string urlPath, string savePath)
    {
        WebClient client = new WebClient();
        //client.Credentials = New System.Net.NetworkCredential("username", "password")
        
        client.DownloadProgressChanged += ClientDownloadProgressChanged;
        client.DownloadFileCompleted += ClientDownloadFileCompleted;
        
            
        client.DownloadFileAsync(new Uri(urlPath), savePath);
    }
    
    
    private void ClientDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
    {
        
        double bytesIn = double.Parse(e.BytesReceived.ToString());
        double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
        double percentage = bytesIn / totalBytes * 100;
        
        ProgressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
            
        PaintProgressBarPercent(ProgressBar1);
    }
    
    
    private void ClientDownloadFileCompleted(object sender, EventArgs e)
    {
        //AsyncCompletedEventArgs
        MessageBox.Show("Download Completed");
    }
    
    
    
    private void PaintProgressBarPercent(ref ProgressBar a)
    {
        int percent = (int)(((double)(ProgressBar1.Value - ProgressBar1.Minimum) / (double)(ProgressBar1.Maximum - ProgressBar1.Minimum)) * 100);
        
        using (Graphics gr = ProgressBar1.CreateGraphics()) {
            PointF p1 = new PointF((float)a.Width / 2 - (gr.MeasureString(percent + "%", SystemFonts.DefaultFont).Width / 2f), (float)a.Height / 2 - (gr.MeasureString(percent + "%", SystemFonts.DefaultFont).Height / 2f));
            try {
                gr.DrawString(percent + "%", SystemFonts.DefaultFont, Brushes.Black, p1);
            }
            catch (Exception ex) {
                
            }
            
        }
    }
}


The following code is a partial example of using backgroundworker ReportProgress method to access controls from the backgroundworker thread.

The form has one button called Button2. When the form is activated it creates a balloon tooltip message for 5 seconds on it.

These examples will not work unless you create a winform to go along with them.

VB.NET Example

Imports System.ComponentModel
Public Class Form1

    Dim bwCheckForUpdates As BackgroundWorker

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ToolTip1.SetToolTip(Button2, "An update is available.")
    End Sub

    Private Sub Form1_Activated(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Activated

        bwCheckForUpdates = New BackgroundWorker()
        bwCheckForUpdates.WorkerReportsProgress = True
        AddHandler bwCheckForUpdates.ProgressChanged, AddressOf bwCheckForUpdates_ProgressChanged
        AddHandler bwCheckForUpdates.DoWork, AddressOf bwCheckForUpdates_DoWork
        bwCheckForUpdates.RunWorkerAsync()

    End Sub

    Private Sub bwCheckForUpdates_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        ' Check for update
        ' if available call bwCheckForUpdates.ReportProgress(100, True) with value of true
        bwCheckForUpdates.ReportProgress(100, True)

    End Sub
    Private Sub bwCheckForUpdates_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        If CType(e.UserState, Boolean) = True Then
            ToolTip1.Show("An update is available.", Button2, 5000)
        End If
    End Sub


End Class

C# Example

using System.ComponentModel;

public class Form1
{
    BackgroundWorker bwCheckForUpdates;
    
    private void  Button1_Click(System.Object sender, System.EventArgs e)
    {
        Balloon b = new Balloon();
        b.Show();
    }
    
    private void Form1_Load(System.Object sender, System.EventArgs e)
    {
        ToolTip1.SetToolTip(Button2, "An update is available.");
    }
    
    private void  Form1_Activated(System.Object sender, System.EventArgs e)
    {
        
        bwCheckForUpdates = new BackgroundWorker();
        bwCheckForUpdates.WorkerReportsProgress = true;
        bwCheckForUpdates.ProgressChanged += bwCheckForUpdates_ProgressChanged;
        bwCheckForUpdates.DoWork += bwCheckForUpdates_DoWork;
            
        bwCheckForUpdates.RunWorkerAsync();
    }
    
    private void bwCheckForUpdates_DoWork(System.Object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        // Check for update
        // if available call bwCheckForUpdates.ReportProgress(100, True) with value of true
            
        bwCheckForUpdates.ReportProgress(100, true);
    }
    private void  bwCheckForUpdates_ProgressChanged(System.Object sender, System.ComponentModel.ProgressChangedEventArgs e)
    {
        if ((bool)e.UserState == true) {
            ToolTip1.Show("An update is available.", Button2, 5000);
        }
    }
   
}