Click here to Skip to main content
15,879,535 members
Articles / Programming Languages / C#

Creating a NFO Viewer in C# as a beginner

Rate me:
Please Sign up or sign in to vote.
4.94/5 (11 votes)
21 Apr 2014CPOL25 min read 46.4K   10.7K   32   8
A small application which converts a .nfo text file and views it in a custom form with music and automatic scrolling text!

I have 4 versions, all have Source code and Application only downloads.

============================================

Updated to v1.4. Appearance changed, new improvements and bugfixes (See History at bottom for changes).
I hope you'll enjoy this hopefully Final version!

Introduction

Having a few more months of C# hobby-experience by trial and error and some new updates for this NFO Viewer, I once again updated this article. I'm running Windows 7 Ultimate x64, .NET 4.5 and I use Microsoft Visual Studio 2010.

This application has a custom 'Form', Functions to close application and mute music, custom icon, picture that goes to a website if you click it and the main thing is the richTextBox. In this box I will load the NFO file (text), which will be presented in custom colors, scrolls down automatically and loops, and a last thing: you can't interact with the text. It has to be presented like the end credits of a movie!
Using this article you can pick any part of code to create your own viewer or use the source to create a custom Viewer of the one provided here.

Background

I had a lot of NFO files, which I had to set 'open with notepad' to show them. Notepad doesn't show all correct symbols by default and doesn't position everything in the right place. Eventually I got some NFO Viewer samples that ran instantly and had a lot of custom things. I wanted that too, but couldn't change those files. So I decided to create them myself!

The Application + Options

Since this is a new update, some buttons/functions are different. I'll leave the old options as is, so people can still use those as well. Changes since 1.3: No close button (2) anymore (press Escape instead), Test Speedbuttons removed (7), changed speed options (1x +, 1x - instead of both 2x).

Picture 'Argaï NFO Viewer v1.1'
Picture 'Argaï NFO Viewer v1.3'
Picture 'Argaï NFO Viewer v1.4 Final' (Full image from below)


The above application contains the following parts:

  1. The mainframe (Windows Form, without border);
    I've used a big picture and set the Transparency option to White, to remove all around the actual picture.
    With a small piece of code, you can make the picture drag the whole application around.
  2. A Button (X) to close the application once you run it;
  3. A checkBox which will pause (mute) the music (mod format[.it/.xm/.s3m/.mod]) when it is unchecked;
  4. (Left side) A pictureBox that you can click on. It will open the default user's webbrowser and go to my link;
  5. The most important one for this app: The richTextBox!
    This opens a specified .nfo file, converts it before presenting, load all the text and uses my edited autoscroll code to keep the text going up with a specific speed all the time. When it reaches the end, it will go back to the start and loop the scrolling. I didn't want a scroller, so I decided to 'hide' it. I also disabled all possible interactions with it.
  6. Another pictureBox, that is disabled. This means you can't interact with any event, but you can click on it and drag the application around, like the image of the 'form'.

    Extra
  7. Buttons/KeyPress Events for Speed Options: Pause, Slower, Faster {Limited}
  8. Custom Icon.
  9. PictureBox as Button(Click Event) that opens 'About' Window.
  10. Music (mod format) in background that runs with application. [Needs an external Player]
  11. Additional Settings [Form Name, process name/description etc.]
  12. ToolTips [Popups with text info when mouse Holds on active Form Control]

Using the code

NOTE: As I've changed a lot in v1.4, not all code will be placed in this article. If you want to check some specific code, use the provided source code.

Let's try to explain how to make those individual parts with the specific options I wanted. You can change whatever you want to your own liking, but I wanted to create it this way and it was hard to find around the internet. At first, my application has imported all that's stated below:

C#
using System; // Default, Used for handles.
using System.Diagnostics; // To use Process.
using System.Drawing; // Default, for point locations and colors.
using System.Windows.Forms; // Default, Formrelated code (events, properties, objects).
using IrrKlang; // I added this myself (music player).
using System.Reflection; // To work with Assemblies.
using System.Runtime.InteropServices; // This is for the dll-import.
using System.IO; // Work with files and streams.
using Un4seen.Bass; // This is for the new BASS ModPlayer.

1) The FORM [MAINFRAME]

Form properties:

  • Backgroundimage: to create the custom picture form.
  • BackgroundImageLayout: None (make your white area of the picture big enough, don't repeat the image).
  • DoubleBuffered: True, this prevents the application from flickering when dragging out of screen.
  • Icon: Chose the icon for the application WHEN IT IS RUNNING (format .ico), not for the .exe itself. If you want the white to be transparent, use some software that can delete the unwanted are and save it as a transparent image (e.g. Paint.net). I used http://converticon.com/ to create the icon of my image.
  • Size: you can manually set your size here, but in your Design View you can change it by dragging the borders.
  • StartPosition: CenterScreen, this will open the application in the center of your screen.
  • Text: Here you can set the text you want to appear above the Taskbar Icon of the running application.
  • TransparencyKey: White, depends on the background color you want to remove of your selected picture.

We want to be able to move around our program.
To do this, create 2 new Events for the form and name them wisely, or double click the field and use the default names. In my application I always use the default ones.
In the Properties window, select the lightning icon (Events).

  • MouseDown: Form1_MouseDown
  • MouseMove: Form1_MouseMove

This will create two new methods to do something when these events happen on your picture (form). Add the following code to the methods in your form:

C#
// As I use this in more methods, I placed it before public Form1()
public Point mouse_offset;

// These 2 methods will make it possible to drag your application around.
private void Form1_MouseDown(object sender,
System.Windows.Forms.MouseEventArgs e)
{
    mouse_offset = new Point(-e.X, -e.Y);
}

private void Form1_MouseMove(object sender,
           System.Windows.Forms.MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        Point mousePos = Control.MousePosition;
        mousePos.Offset(mouse_offset.X, mouse_offset.Y);
        Location = mousePos;
    }
} 

There was a 'bug', if users pressed Arrow Keys, they would enter the richTextBox (focus changes) and using the Arrow Keys and PageUp/Pagedown Keys they could navigate in it. I've searched and found working code to disable this. I also added the Escape key function here, as Escape is a Command key. Now you can Close the application by pressing Escape when the application is active.
In the Form_Load( ) Event, add:

C#
foreach (Control control in this.Controls)
{
    control.PreviewKeyDown += new PreviewKeyDownEventHandler(control_PreviewKeyDown);
}

Outside of this Event, add a method with following code:

C#
void control_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{   // This blocks arrow/directional keys.
    if (e.KeyCode == Keys.Up || e.KeyCode == Keys.Down || e.KeyCode == Keys.Left || e.KeyCode == Keys.Right)
    { e.IsInputKey = true; }
    // Here I added the function to close app with Escape.
    if (e.KeyCode == Keys.Escape)
    { this.Close(); }
}

When this code is added, you won't be able to switch from the Form to the richTextBox using arrow Keys.

I also added a Fade Effect of music and app when the application closes.
This effect is triggered when the application gets a message that it needs to close.
The following code handles the effect of the appearance, and also fades the music with it. I used timers to fade away with different speeds. You can combine it and change speed if it fits, do as you want.

C#
// CLOSE FORM [FADE APPLICATION/MUSIC]
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (this.Opacity > 0.01f)
    {
        e.Cancel = true;
        Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_GVOL_MUSIC, 7000);
        AppFadeTimer.Interval = 33;
        VolFadeTimer.Interval = 10;
        AppFadeTimer.Enabled = true;
        VolFadeTimer.Enabled = true;
    }
    else
    { AppFadeTimer.Enabled = false; VolFadeTimer.Enabled = false; }
}
private void AppFadeTimer_Tick(object sender, EventArgs e)
{
    if (this.Opacity > 0.01)
    { this.Opacity = this.Opacity - 0.01f; }
    else
    {
        this.Close();
    }
}
private void VolFadeTimer_Tick(object sender, EventArgs e)
{ vol = vol - 26; Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_GVOL_MUSIC, vol);}

As I make different app designs and versions, this may differ a lot, but it works.

2) The BUTTON [Close Application] <code>

Button Properties:

  • Text: Change it to something that says: 'close me'.
  • Cursor: I changed this to Hand, so you can better see it's clickable.
  • BackColor and ForeColor: Change the color style of button and text.
  • Size and Location: Drag around and resize in Design mode, or type the numbers.

We want to be able to close our program with a X-Button.
In Design Mode, add a Button from the Toolbox, change the Property Text to 'X' or 'Close' and size it to your liking. Add the Event Click: 'button1_Click'. This will create a method for the Event to do something when the user presses the button.

Use the following code to close the application:

C#
// This will close the application when the user presses the X button.
private void button1_Click(object sender, System.EventArgs e)
{
    this.Close();        
}

3) The CHECKBOX [Pause Music]

checkBox Properties:

  • BackColor: I've set this one Transparent, to see only the box, and the text has no white background then.
  • Checked: I want my music ON default, so this one is True when the application starts.
  • CheckState: I want a check in my box, you can also disable the box (gray), but here it's active: Checked.
  • Cursor: Hand.
  • ForeColor: LawnGreen in my example, or change it to any color you want.
  • Text: Type the text that will be next to the checkBox, in my case: Music?
  • Size and Location: Drag around and resize in Design mode, or type the numbers.

We want to be able to mute the music (pause) with a checkBox.
In Design Mode, add a checkBox to the form. Change the properties like the example above or to your own desire. Now we go set the checkBox' event. We simulate that people turn of our check, to disable the music. Add the Event CheckChanged: checkBox2_CheckedChange. Now you have the method for this event.
Add the code to pause or stop the music. In my case, I use irrKlang modplayer BASS to play the mod music files. To see how I implemented this, see 10) Music (.it format) To pause this music in irrKlang BASS, add the following code in the checkBox2_CheckChange method:

C#
// Old version irrKlang.
private void checkBox2_CheckedChange(object sender, EventArgs e)
{
    CheckState state = checkBox2.CheckState; // Get the current state of the check.
    if (state == CheckState.Checked) // If checked after change;
    {
        engine.SetAllSoundsPaused(false); // Do nothing (if already playing) or continue music.
    }
    else // If changed to 'Unchecked'
    {
        engine.SetAllSoundsPaused(true); // Pause the music.
    }
}

// New Version (Bass).
private void checkBox2_CheckedChange(object sender, EventArgs e)
{
    CheckState state = checkBox2.CheckState;
    if (state == CheckState.Checked)
    { Bass.BASS_Start(); }
    else
    { Bass.BASS_Pause(); }
}

4) The PICTUREBOX [Clickable]

pictureBox Properties:

  • BackgroundImage: Select the image you want to show.
  • BorderStyle: I changed this to FixedSingle; seperate the dark image from the black richTextBox background.
  • Cursor: I changed this to AppStarting (just for fun, to show you can click).
  • Size and Location: Drag around and resize in Design mode, or type the numbers.

We want to be able to go to a website by clicking on an image. Besides, don't pick Internet Explorer, but the default browser of the client system. In Design Mode, add a pictureBox to the form. Change the Properties like the example above or to your own desire. Now we add the Event from the Properties' Event window: Click, e.g. pictureBox1_Click.

In the method that we just created add:

C#
private void pictureBox1_Click(object sender, EventArgs e)
{
    Process myProcess = new Process();
    {
    myProcess.StartInfo.UseShellExecute = true; // This runs from command line (default browser).
    myProcess.StartInfo.FileName = "http://tehparadox.com/forum/f73/arga-prophecy-2001-dutch-2631589/";
    myProcess.Start(); // Use any valid link you want above.
    }
}

It's also nice to put ToolTips on PictureBox or other Controls,
so people know what it'll do or where it goes to.
Above and in the Main Form Constructor add:

        System.Windows.Forms.ToolTip ToolTip1 = new System.Windows.Forms.ToolTip();

        public Form1()
        {
            // Info ToolTips for Some Buttons.
            ToolTip1.InitialDelay = 1200;
            ToolTip1.SetToolTip(pictureBox1, "Go to: Dutch Argaï Project Forum!");
            ToolTip1.SetToolTip(buttonQ, "Info");
        }

5) The RICHTEXTBOX [Autoscroll locked NFO viewer]

richTextBox properties:

  • BackColor: In my example set to MenuText (black).
  • BorderStyle: None, as I want to cut of any edges and the scrollbar in my scroll.
  • Cursor: default is IBeam, but I don't want to select text! Set Arrow or Default (pointer).
  • DetectUrls: False, I just want to present the text and I have ASCii art which contains invalid 'links'...
  • Font: If you use ASCii art, this one is important, there are just a few fonts that support that. I've chosen Courier New for my application.
  • ForeColor: LawnGreen in my example, or change it to any color you want.
  • ReadOnly: True, I don't want to change the presented text, in any way.
  • ScrollBars: I wanted this set None, but to get my scrolling working, it needs the scrollbar, so I set Both.
  • Size and Location: Drag around and resize in Design mode, or type the numbers.

We want to be able to view a .nfo file correctly in the richTextBox. In Design mode, add a richTextBox to the form. Change the Properties like the example above or to your own desire. If you don't have the Load event from the Form already, create one (e.g. Form1_Load). When the Form and all components are loaded, we want to check if the .nfo file exists. When it does, convert it to the right format and present it, otherwise put the text 'NFO not found' in the richTextBox.
Final code (this just shows the text in the box, no scrolling yet):

C#
private void Form1_Load(object sender, EventArgs e)
{
    // You can set 'file_name' anything you like.
    string file_name = "C:\\Test\\DARTY.nfo"; // Set the filepath.

        if (System.IO.File.Exists(file_name) == true) // Check for existence.
        {
            // Encode the file and put the endresult in our richTextBox.
            System.Text.Encoding encoding = System.Text.Encoding.GetEncoding(437);
            System.IO.StreamReader file = new System.IO.StreamReader(file_name, encoding);
            richTextBox1.Text = file.ReadToEnd();
            file.Close();
        }
        else // If it doesn't exist/not found... 
        {
            // Put this text in the richTextbox instead.
            richTextBox1.Text = "File not Found! :( --- Where is DARTY.nfo??";
        }
} 

OR we can use a .nfo file as a resource, which will be better in this case.
To do this, open the project properties and select the 'Resources' tab. Add an existing file (our .nfo file)
and view the properties. We need to change the FileType to Text and then another option appears:
Encoding. Set this to OEM United States - Codepage 437. If those options aren't available, try to change the View to 'View Details' instead of View In List or View As Thumbnails (Just like on computer).
When this is set, we don't have to check existence and don't have to read and encode the file anymore.
This will leave the following short code as final result:

C#
string file_name = Properties.Resources.Eng_Dut_01; // Resource doesn't require file extension.
richTextBox1.Text = file_name; // Put the file in the box.

The variable 'file_name' will be directed to the resource we've added and the Text of the richTextBox will be filled with the resource data. We don't need the lines from the previous part anymore to work through the file!

We want to be able to disable all interaction with the richTextBox, without disabling the box itself. Disabling the richTextBox is almost all right, but it prevents us from selecting custom colors!
I've created a new Form with the same size and location as the richTextBox. Opacity 1% so you can't see it and it moves around with the application as well. This prevents any interaction with our richTextBox, just as we wanted!
If you want to see the code, use my source code (v1.3).

In v1.4 I've removed the Shield (Form) that stayed on top of all other Windows Applications and I substituted it with blocking mouseclicks. It didn't work with the clickevents, but I've found great code samples online that worked:

C#
// DISABLE RIGHTCLICK + MIDDLEBUTTON ON RICHTEXTBOX.
public bool PreFilterMessage(ref Message m)
{
    // Filter out WM_NCRBUTTONDOWN/UP/DBLCLK
    if (m.Msg == 0xA4 || m.Msg == 0xA5 || m.Msg == 0xA6) return true;
    // Filter out WM_RBUTTONDOWN/UP/DBLCLK
    if (m.Msg == 0x204 || m.Msg == 0x205 || m.Msg == 0x206 || m.Msg == 0x207 || m.Msg == 0x208 || m.Msg == 0x209) return true;
    return false;
}

Note that this applies to the whole active Form. But as my Form only accepts left mouse clicks, I don't care blocking the other mousebuttons for it.

We want to be able to autoscroll the richTextBox and loop it, to view all the text like movie credits.
Prepare, as this code isn't easy at all. You don't have an option to just automatically scroll a box at a specified speed. There is a code option however to go up line by line, but that isn't easy to read. See it this way: We need a Messageservice from a dll, to tell the richTextBox to move up a pixel each few milliseconds. So we set up the task (moving up) and have to create a timer, that sends the task as a message every few milliseconds we have set before.

I didn't get all of the code, but it worked! See REFERENCES at the bottom for the project I got this from. The only thing I changed was the speed of scrolling + options to adjust that, it goes back to start when it reaches the end (loop) and I changed the color before the text updates to a new location. This was hard as I needed to sync it with the different scrollingspeeds.

Import DLLs, create all references for the code

The following code (except first 'using' line) is placed between the public partial class and public Form1( )

C#
// Paste this line on top of your code. 
using System.Runtime.InteropServices;
 
// The rest.
public partial class Form1 : Form
{
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);

    [DllImport("user32.dll")]
    static extern int SetScrollInfo(IntPtr hwnd, int fnBar, [In] ref SCROLLINFO lpsi, bool fRedraw);

    [DllImport("User32.dll", CharSet = CharSet.Auto, EntryPoint = "SendMessage")]
    static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

    struct SCROLLINFO // These are all required.
    {
        public uint cbSize;
        public uint fMask;
        public int nMin;
        public int nMax;
        public uint nPage;
        public int nPos;
        public int nTrackPos;
    }

    enum ScrollBarDirection
    {
        SB_HORZ = 0,
        SB_VERT = 1,
        SB_CTL = 2,
        SB_BOTH = 3
    }
 
    enum ScrollInfoMask
    {
        SIF_RANGE = 0x1,
        SIF_PAGE = 0x2,
        SIF_POS = 0x4,
        SIF_DISABLENOSCROLL = 0x8,
        SIF_TRACKPOS = 0x10,
        SIF_ALL = SIF_RANGE + SIF_PAGE + SIF_POS + SIF_TRACKPOS
    }

    const int WM_VSCROLL = 277;
    const int SB_LINEUP = 0;
    const int SB_LINEDOWN = 1;
    const int SB_THUMBPOSITION = 4;
    const int SB_THUMBTRACK = 5;
    const int SB_TOP = 6;
    const int SB_BOTTOM = 7;
    const int SB_ENDSCROLL = 8;

    private Timer t = new Timer(); // Create an instance of our Timer.

Set the speed and enable Timer to send messages.

Add this code in the public Form1( )

C#
public Form1()
{
    InitializeComponent();

    // Extra Code. Interval creates the speed, Event sends it.
    t.Interval = 40;
    t.Tick += new EventHandler(t_Tick);
    t.Enabled = true; // We want the Timer to run this instantly, so enable.
}

Almost there, last bit of code for the autoscroll! Create the 2 methods t_Tick( ) and scroll( ) to run the process. I've added additional code to change the text while scrolling. This is in t_Tick( ), it checks the current scrolling speed by getting the interval of the timer, which can be adjusted by pressing + and - .
Depending on the interval, I execute the correct colorchangespeedcode.
I added one method FastScrollpeed( ) (least code) as example, for rest see source code.
Depending on the interval, the color needs to be updated each pixel up or each few pixels up (in fast case). That's why I use int i to check the pixel number and reset on end to loop the color pattern.

C#
       // Timer for scroll + change richTextBox1 color at each interval.
        int i = 1;
        string ScrollEnabled = "true"; // If user presses P (pausing scroll) then this is false. 
        void t_Tick(object sender, EventArgs e) // GetCurrentInterval and call the right color speed change.
        {
            if (t.Interval == 80)
            { SlowScrollSpeed(); }
            else if (t.Interval == 40)
            { CenterScrollSpeed(); }
            else if (t.Interval == 10)
            { FastScrollSpeed(); }

            if (ScrollEnabled == "true") { scroll(richTextBox1.Handle, 1); } else { scroll(richTextBox1.Handle, 0); }
        }

        void FastScrollSpeed() // Change color each 6 lines.
        {
            if (i >= 1 && i <= 6) { richTextBox1.ForeColor = Color.OrangeRed; i = i + 1; }
            else if (i >= 7 && i <= 12) { richTextBox1.ForeColor = Color.DarkOrange; i = i + 1; }
            else if (i >= 13 && i <= 18) { richTextBox1.ForeColor = Color.Yellow; i = i + 1; }
            else if (i >= 19 && i <= 24) { richTextBox1.ForeColor = Color.LawnGreen; i = i + 1; }
            else if (i >= 25 && i <= 30) { richTextBox1.ForeColor = Color.Turquoise; i = i + 1; }
            else if (i >= 31 && i <= 36) { richTextBox1.ForeColor = Color.DodgerBlue; i = i + 1; }
            else if (i >= 37 && i <= 42) { richTextBox1.ForeColor = Color.RoyalBlue; i = i + 1; }
            else if (i >= 43 && i <= 48) { richTextBox1.ForeColor = Color.DarkViolet; i = i + 1; }
            else if (i >= 49 && i <= 53) { richTextBox1.ForeColor = Color.HotPink; i = i + 1; }
            else if (i == 54) { richTextBox1.ForeColor = Color.HotPink; i = 1; }
        }

// Scrolls a textbox. handle: handle to our textbox. pixels: number of pixels to scroll.
void scroll(IntPtr handle, int pixels)
{
    IntPtr ptrLparam = new IntPtr(0);
    IntPtr ptrWparam;
    // Get current scroller posion

    SCROLLINFO si = new SCROLLINFO();
    si.cbSize = (uint)Marshal.SizeOf(si);
    si.fMask = (uint)ScrollInfoMask.SIF_ALL;
    GetScrollInfo(handle, (int)ScrollBarDirection.SB_VERT, ref si);

    // Increase posion by pixles
    if (si.nPos < (si.nMax - si.nPage))
        si.nPos += pixels;
    else // No more pixels left...
    {
        ptrWparam = new IntPtr(SB_ENDSCROLL); // End reached.
        t.Enabled = false; // Disable the Timer.
        SendMessage(handle, WM_VSCROLL, ptrWparam, ptrLparam);
    }

    // Reposition scroller
    SetScrollInfo(handle, (int)ScrollBarDirection.SB_VERT, ref si, true);

    ptrWparam = new IntPtr(SB_THUMBTRACK + 0x10000 * si.nPos);
    SendMessage(handle, WM_VSCROLL, ptrWparam, ptrLparam);

    // I added this to loop the scrolling.
    if (t.Enabled == false) // If Timer is disabled...
    {
        // Send scroller back to the top.
        SendMessage(handle, WM_VSCROLL, (IntPtr)SB_TOP, IntPtr.Zero);
        t.Enabled = true; // Enable timer again.
    }
} 

As we can't interact with the richTextBox anyways, it would be great if we could move around the application by dragging the richTextBox. I've found some code online that enabled moving the whole Form by dragging a control on it:

C#
        // These Events help to drag the Whole Form by dragging our richTextBox.
        private void richTextBox1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                dragging = true;
                pointClicked = new Point(e.X, e.Y);
            }
            else
            { dragging = false; }
            pictureBox1.Focus();
        }
        private void richTextBox1_MouseUp(object sender, MouseEventArgs e)
        {
            dragging = false;
            pictureBox1.Focus();
        }
        private void richTextBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (dragging)
            {
                Point pointMoveTo;
                pointMoveTo = this.PointToScreen(new Point(e.X, e.Y));
                pointMoveTo.Offset(-pointClicked.X, -pointClicked.Y);
                this.Location = pointMoveTo;
            }  
        }
// I've used Focus() method to prevent entering the richTextbox using certain ClickEvents.

This should be it, you should have automatic scrolling and looping text that you load from a .nfo text file (also in resource), convert and view in the richTextBox, with optional color changing code. You can move the Form around by dragging this control as well.

6) Another PICTUREBOX [Disabled]

Refer to 4) The Picturebox [Clickable] But don't add any (click)Event and set the Property Enabled to False. This will do, without any code, you can drag around any disabled objects.

7) Buttons/KeyPress for Speed options [Pause, Slower, Faster] {Limited}

7.1) BUTTONS: Add some buttons you want, change the Text to P, - and + for the functions. For each Button: add the Event Click. Within these methods we put the actions to create this new functionality. I created these: buttonp (PAUSE), buttonmin (SLOWER) and buttonplus (FASTER).
Note the t.Interval, which we've set in 'Set the speed and enable Timer to send messages'
from 5) The RICHTEXTBOX. The setting that I use as default speed is t.Interval = 40;

C#
// The Interval needs to be smaller to send it's messages faster (faster speed).
private void buttonplus_Click(object sender, EventArgs e)
{
    if (t.Interval > 10) // Not highest Speed.
    {
        t.Interval = t.Interval - 15; // Increase Speed with 15ms.
        if (t.Interval <= 10) // When this reaches highest speed after calculation...
        { buttonplus.Enabled = false; } // Disable the speedbutton.
        buttonmin.Enabled = true; // Enable the opposite speedbutton.
    }
}

private void buttonmin_Click(object sender, EventArgs e)
{
    if (t.Interval < 70)
    {
        t.Interval = t.Interval + 15;
        if (t.Interval >= 70)
        { buttonmin.Enabled = false; }
        buttonplus.Enabled = true;
    }
}

private void buttonp_Click(object sender, EventArgs e)
{
    if (t.Enabled == true) // First check if timer is running.
    {
        t.Enabled = false; // If so, disable it.
    }
    else // (t.Enabled == false)
    {
        t.Enabled = true; // Otherwise do the opposite.
    }
}
//If you can count, you'll see you can push both the + & - 2x if you have the default speed[40].

7.2) KEYPRESS Event:

Determine where you want to have the ability to press your keyboard key. I decided my form was the best choice, but the focus just wan't there. I've used the following steps:

  • I set the Form Propery KeyPreview = True;
  • I changed the TabIndex from all the Buttons to high(er) values;
  • In the Form1.Designer.cs I added this.Focus(); to the Form, just to be sure.

Then, time for the KeyPress Events. Go to the Form Properties and select the Event options. Add KeyPress. For this one method, we can add all the keyboard keys we want.

If you want the old code with button option, check the v1.1 source release.
In v1.4 I used the following situation:

C#
// KEYBOARD KEYS THAT PROVIDE FORM-FUNCTIONS FOR USERS.
// Note you can't use 'command' keys, just input keys that actually print to screen.
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
    if (e.KeyChar == 'm') // Toggle Music.
    {
        if (checkBox2.CheckState == CheckState.Checked)
        { checkBox2.CheckState = CheckState.Unchecked; }
        else // Unchecked state.
        { checkBox2.CheckState = CheckState.Checked; }
    }
    if (e.KeyChar == 'p') // Pause Scroll.
    {
        if (ScrollEnabled == "true")
        { ScrollEnabled = "false";}
        else { ScrollEnabled = "true"; }
    }
    if (e.KeyChar == '=' || e.KeyChar == '+') // Speed up Scroll, Values are fixed!
    {   if (t.Interval == 40)
        { t.Interval = t.Interval - 30; }
        else if (t.Interval == 80)
        { t.Interval = t.Interval - 40; }
    }
    if (e.KeyChar == '-') // Slow down Scroll.
    {   if (t.Interval == 40) { t.Interval = t.Interval + 40; }
        else if (t.Interval == 10) { t.Interval = t.Interval + 30; }   }
}

8) Custom Icon (No Code)

Refer to the Form Properties of 1) The FORM [MAINFRAME]. In this section you can add an Icon for the application IN RUNNING STATE.

The .exe file itself still has it's default window Icon. To change this to the same/another Icon, open the Solution Explorer. Rightclick the name of your project (almost top in bold) and open the Properties. If the tab isn't set on Application, select that tab. You'll find the option 'Icon and manifest', where you can browse for the same .ico file. When you save this, your .exe file will also contain your selected icon.

9) 'About' Window

A new Form that opens when you click on the corresponding Question Mark PictureBox.
When you hover over the box, the Question Mark will glow. I added those 2 pictures as resource.
The next block of code shows how that Question Mark works:

C#
// QUESTION-MARK BUTTON ['About' POPUP]
void buttonQ_MouseEnter(object sender, EventArgs e)
{ this.buttonQ.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.QMarkNeonGlow)); }

void buttonQ_MouseLeave(object sender, EventArgs e)
{ this.buttonQ.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.QMarkNeonLessGlow)); }

private void buttonQ_Click(object sender, EventArgs e)
{
    f2.TopMost = false; // DisAble SHIELD ON TOP
    Form f3 = new Form3(); // CREATE 'About' POPUP
    f3.ShowDialog(); // BLOCK INTERACTION WITH APPLICATION untill popup closed.
}

By using the MouseEnter and MouseLeave Events you can change the appearance of the picture when the mouse hovers over the PictureBox. I have to disable the shield's TopMost, otherwise it will prevent users from closing the popup. When users click the richTextBox, I make sure that the TopMost of the shield (f2) is activated. It's not the best solution, but I'm satisfied with it for now. To see the complete setup, the source is your friend!

10) Music (mod format)

I wanted to have small music files (at least compared to mp3), so I've chosen the mod format[.it/.xm/.s3m/.mod]. Those can be big too, but I just download tracks < 1MB, to keep my application small. There are no simple ways to code playing music, only when you want to run .mp3/.wav using WMP. I've chosen irrKlang modplayer BASS to play my mod music files. [For more info, click the modplayer link] It was hard to find out how this would work all by myself, but I succeeded. Steps I've done for irrKlang are stated below as reference:

In the extracted irrKlang folder:

  • Copy the 'Include' folder to your project folder on the system.
  • Copy the correct dotNET version dll to your project folder (in my case: irrKlang-1.4.0\bin\dotnet-4\irrKlang.NET4.dll and also ikpFlac.dll and ikpMP3.dll if you want to play MP3 files.
  • Copy the .exp and .lib file from this folder 'irrKlang-1.4.0\lib\Win32-visualStudio' to your project.

In your Visual Studio Project, do the following: In the Solution Explorer, rightclick 'References' and select Add Reference... Select the Browse tab, search and select your .NET dll (irrKlang.NET4.dll in my case) and add it.

Add this line to the top of your project:

C#
using IrrKlang;

Then we can go to the actual code that loads and plays our mod music file. Refer to the first point (view a .nfo file correctly) of 5) The RICHTEXTBOX. We've used the Form1_Load( ) method there to read and convert the .nfo file and display it when the Form loads. The same thing we'll do with our music when the application starts. Paste the following line just before the Form1_Load( ) method:

C#
IrrKlang.ISoundEngine engine = new IrrKlang.ISoundEngine();

The reason I use it before the Form loads, is because I need this variable in more methods (also to pause it)! In the Form1_Load( ) method, we add the following line:

C#
engine.Play2D("C:\\Test\\Xaser-Aeolus.it", true);

This means we play a file on the computer, so as long as I can't include it in the project, you have to send it with the application and make sure it copies/extracts to the correct folder. Otherwise the application runs, but without music and possibly NFO file from the same folder.

Steps I've done for BASS:
I'm able to play my music from resource now, so this is easier and always works.
Download the BASS and Bass.Net dlls and add the files to the project, or copy them from my source. In Solution Explorer, go to references and add Bass.Net.dll as a reference. Unless you add them to resource, you have to put them with the final .exe as well. When the dlls are added and the reference is made, add the following line to the top:

C#
using Un4seen.Bass;

I have a directory 'Resources' in my project and rightclick -> added my mod music file. Set properties of it: Build Action: Embedded Resource.
Using the following code in Form1_Load( ) I can play that track from resource using BASS on startup:

C#
// LOAD MUSIC
BassNet.Registration("xxxxxxxx@xxxxxxxx.xx", "XXXXXXXXXXXXXXX"); // Source activated.
Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
// "Projectname.(OptionalFolder.)ResourceFileName.Extension"
using (var manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("WindowsFormsApplication1.Resources.Saga Musix - Heaven.it"))
// use //string[] names = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames(); in debug to test the proper path to resource.
{
    if (manifestResourceStream != null)
    {
       int length = (int)manifestResourceStream.Length;
       byte[] buffer = new byte[length];
       manifestResourceStream.Read(buffer, 0, length);

       int load = Bass.BASS_MusicLoad(buffer, 0, length, BASSFlag.BASS_SAMPLE_LOOP, 0);

       Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_GVOL_MUSIC, vol);
       Bass.BASS_ChannelPlay(load, false);
    }
}

Refer to 3) The CHECKBOX [Pause Music] to see how to pause the running mod music and continue it.

11) Additional Settings

Here I place the things I've changed to let it appear nicely on other places on the computer.

Default .exe Filename: We go to the Solution Explorer and rightclick our project and then Properties. Select the 'Application' tab and change the Assembly Name to whatever you want for the exe.
As I'm in BETA, it doesn't really matter, I change it to character name to see a difference ('Angel').
If you set this, you don't have to change the name of the exe manually after you've debugged (exported) the .exe with the default 'TestApplication.exe' name.

Process Description: I noticed when running my program, that the description in Taskmanager is WindowsFormsApplication1? That's not what I want, I want something like (Argaï) NFO Viewer! To change the Process Description, go to the Solution Explorer, under YourProjectName you see the directory 'Properties'. In that directory, rightclick the AssemblyInfo.cs and click 'View Code'. [assembly: AssemblyTitle("WindowsFormsApplication1")], change the Title in what you want and it will show that title as the Description when your Process is running!

Taskbar and Taskmanager appearance: As informed before, changing the Property Text of the Form will create the 'program name' which appears when you hover over the running icon on the taskbar. The Assembly Name that is changed will present the .exe name that will be shown as process in Taskmanager.

Points of Interest

In just a few weeks I created this. The basic stuff was easy to do, but to make my richTextBox autoscroll and the way I wanted it (looped) was hard, even as changing the colors with it. But also disabling all interaction with it, without disabling the richTextBox itself was kind of hard to find out. I worked using trial and error and still do. Using some code samples from people online to achief this was really hard, as I always got errors of 'missing references' etc... I'm happy I got that all working now!

History

Changes after first upload:

Update 1.1:

General changes:

- Assembly Name changed;
- Process description changed [See 11) Additional Settings];
- Tabindex of controls changed;
- Focus added to Form (for general KeyPress option);

Functionality:

- Added 3 buttons for autoscroll speedoptions [See 7) Buttons/KeyPress];
- Added 3 KeyPress options to do the same as the buttons [See 7) Buttons/KeyPress];
I prefer the keypress, but had to test with buttons first and fix the focus etc...

Update 1.2:

Functionality:

- Added the .NFO text file as a resource to the project so people don't need to extract it to specific location anymore. I still try to add the music and dll file as a resource as well. (See the 'use a .nfo file as a resource' part of 5) The RICHTEXTBOX);

BugFixes:

- Pressing arrow keys won't allow you to enter richTextBox anymore. (See 1) The FORM);

Update 1.3:

General changes:

- Made Icon rounder (used circle shape instead of manual removing all around the circle);
- Better documented and ordened the Source Code for own reference;

Functionality:

- Changed ModPlayer 'irrKlang' to 'BASS', which supports all tracks that first didn't work and it uses lighter DLLs which make my application easier to run on more systems (See 'Steps I've done for BASS' of 10) Music (mod format);
- Removed the close button and added more KeyPresses (Escape to close application) (See move around of 1) The FORM);
- Added a fade effect when closing the application, this also fades the music with it to create a smooth closing (See Fade Effect of music and app of 1) The FORM);
- The Music is now Resource! NO need to put it all on C:\Test anymore, it runs and works everywhere (See 'Steps I've done for BASS' of 10) Music (mod format));
- Changed the default startlocation, now the application always starts in center of screen (See Properties of 1) The FORM);
- Added a questionmark button which opens a simple 'About Window'. This displays the options of the application. While this window is active, you can't interact with the application itself. If you close the application, the questionmarkbutton will be disabled while fading (See 9) 'About' Window);
- The richTextBox now has changing color functionality. It remains same speed, even if you change scrollspeed or pause the scrolling. I added a rough pattern of strong colors (See Create the 2 methods t_Tick( ) and scroll( ) of 5) The RICHTEXTBOX);
- Finally I added both DLLs as resource. One can be read internally, the other one has to be written to disk. Now you can run my application anywhere without copying the DLLs with it (Refer to my source and the link about DLLs in the References at the bottom of this Article);

BugFixes:

- Added a new Form as 'Shield' which prevents interaction with the richTextBox. Now the clickbug of v1.1/1.2 is solved. It does however take the focus of the application away, so KeyPresses won't work untill you click the application again. The shield also remains on top of any other application you run, even if my app is in background! If there's another solution I'll look into that;
- Flickering application when dragging outside of the screen has been solved! (See Properties of 1) The FORM);
- 'Line Jumping Bug' fixed, text now remains on same position instead of jumping to last passed line while updating colors when users pause the scroller;

Update 1.4:

General changes:

- Better documented and ordened the Source Code for own reference;
- Changed Project Name, so all my different designs also have different names!

Functionality:
- Added KeyPress '+' so both Numeric and Alphabetic + work. (See 7.2) KEYPRESS Event)
- Added KeyPress 'M' to Mute Music by Keyboard Key when Application is active. (same as above)
- Added a ToolTip on the picture to show info about site you go to after click and on the questionmark button for info. (See put ToolTips on PictureBox of 4) The PICTUREBOX [Clickable])
- Added ability to move Form around by dragging richTextBox. (See move around the application by dragging the richTextBox of 5) The RICHTEXTBOX);
- Updated my About Window: [New Form with functions used in Main Form, see source for code]
+ Now has an animated .GIF with text on it, Custom colored Border, ability to move by dragging, custom closebutton with same mouseover gloweffect as Questionmarkbutton.
+ Window isn't on top anymore (removed ShowDialog()), can be opened once and you can still interact with the Main Form.
+ As I made App interactive while About window is open,
I added code that closes About window when you activate close button of Main Form.
+ As it has a custom Border, the Application won't 'hang' anymore, as it would when you click and hold a normal Windows Form Border.
+ As ShowDialog was disabled, CenterParent as StartLocation didn't work anymore.
So I've added code to manually create the new CenterParent StartLocation function.
+ New Link in About Window to my Digital HobbiesForum;
+ FadeOut of About Window on Close.
BugFixes:
- Removed blocking Shield and substituted it with blocking mouseclick and force Focus. Now the application won't be on top even if it is in background! (See disable all interaction with the richTextBox of 5) The RICHTEXTBOX);


Files:

Added the first result [Top of Page];
Added the Source Code [Top of Page];
Update 1.1:
- Updated Picture in Article;
- Added v1.1 TestApplication [Top of Page];
- Added v1.1 Source Code [Top of Page];
Update 1.3:
- Updated Picture in Article;
- Added v1.3 TestApplication [Top of Page];
- Added v1.3 Source Code [Top of Page];
Update 1.4:
- Updated Picture in Article;
- Added v1.4 TestApplication [Top of Page];
- Added v1.4 Source Code [Top of Page];
[After updating pictures I added link to older pictures for reference]
<code>
<h2>Bugs</h2>

<p>- Windows 8 (always?) contains empty background of <code>checkBox
and/or Close Button.
- When the Application Renders (partially) outside of the screen, it is cut off when it doesn't fit on the resolution of screen. Way/option to fix this?

References

Link to original code for custom Form without any Border and default Buttons:
http://www.codeproject.com/Articles/8056/Creating-Custom-Shaped-Windows-Forms-in-NET

Link to original autoscroll code which I used and changed:
http://www.codeproject.com/Articles/23363/Scrolling-a-Rich-Textbox-Automatically.
Link to my Question 'how to use .nfo as resource':
http://www.codeproject.com/Questions/519140/Usingplusaplus-NFO-plustextplusfileplusasplusresou
Link to the 'add DLL as resource' which I implemented partly:
http://www.codeproject.com/Articles/528178/Load-DLL-From-Embedded-Resource

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Student
Netherlands Netherlands
Studied System management, used Vbscript in past for automation (now using autoIT) and learned basics of CMD/Batch.. I use C# in free time to create personal projects and I have a course to make this a more professional side as well.

Comments and Discussions

 
QuestionNo Downloads ? Pin
Member 1284644911-Nov-16 21:27
Member 1284644911-Nov-16 21:27 
QuestionWhy don't move to a complete text interface rendering? Pin
oburi-buri13-Jan-14 10:46
oburi-buri13-Jan-14 10:46 
AnswerRe: Why don't move to a complete text interface rendering? Pin
DarkTyranno13-Jan-14 10:59
DarkTyranno13-Jan-14 10:59 
GeneralMy vote of 3 Pin
oburi-buri13-Jan-14 10:37
oburi-buri13-Jan-14 10:37 
GeneralRe: My vote of 3 Pin
DarkTyranno13-Jan-14 10:40
DarkTyranno13-Jan-14 10:40 
GeneralMy vote of 5 Pin
Michael Haephrati7-Jan-13 5:24
professionalMichael Haephrati7-Jan-13 5:24 
QuestionSource? Pin
fjdiewornncalwe10-Dec-12 5:20
professionalfjdiewornncalwe10-Dec-12 5:20 
AnswerRe: Source? Pin
DarkTyranno10-Dec-12 5:25
DarkTyranno10-Dec-12 5:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.