Thursday, October 4, 2012

Where to keep Android application files

If you need to store configuration data, some resources, etc. in Android SDK, you should use assets folder for so. To access anything from it use AssetManager:


Activity.getAssets().open("resource.bmp");

Also, take a note that assets are read-only.

Prevent form to blink when gets activate

In my previous post, I was telling you how to run one instance of the application and how to capture command line parameters from next runs. There were one problem, though - on every run, form was getting activate message and window started to blink. To resolve this, you need to handle WM_NCACTIVATE message to ignore Activate message:


protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_NCACTIVATE)
    {
        // Use this to make it always look inactive:
        m.WParam = (IntPtr)0;

        // Alternately, use this to make it always look active:
        m.WParam = (IntPtr)1;
    }

    base.WndProc(ref m);
}

[C#] How to run single instance application and to allow other instances to notify them

Today I wrote simple timer module for 3rd party application. Problem was that 3rd party application allowed only running other executables and, optionally, passing it command line arguments. I've designed simple timer interface in C# and I got an idea that I would allow only one application instance (I only need one timer) and for controls (start/stop) I will use other instances which will notify running instance before they close itself. I've found first solution on CodeProject that worked very well, but for some reason it kept failing on Marshal.Copy call due AccessViolationException. I didn't had time to check why is that, so I've grabbed next snippet of code, and it worked! This solution is using Microsoft.VisualBasic .NET library and WindowsFormsApplicationBase class. Apparently, this approach is using Mutexes and TCP channels internally to implement this, so if you are interested, there is a link on the CodeProject article which explains this (you should read this, btw).

Ok, here is some sample code:

Running 
Your main class needs to extend WindowsFormsApplicationBase class, and you need to call Run(); method of it in Main() function:

/// 
/// We inherit from the VB.NET WindowsFormApplicationBase class, which has the 
/// single-instance functionality.
/// 
class App : WindowsFormsApplicationBase
{
 public App()
 {
  // Make this a single-instance application
  this.IsSingleInstance = true; 
  this.EnableVisualStyles = true;
  
  // There are some other things available in the VB application model, for
  // instance the shutdown style:
  this.ShutdownStyle = Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFormCloses; 

  // Add StartupNextInstance handler
  this.StartupNextInstance += new StartupNextInstanceEventHandler(this.SIApp_StartupNextInstance);
 }
 
 static void Main(string[] args)
 {
  App myApp = new App();
  myApp.Run(args);
 }

Now, we need to override OnCreateMainForm() function to create our MainForm:

protected override void OnCreateMainForm()
{
 // Create an instance of the main form and set it in the application; 
 // but don't try to run it.
 this.MainForm = new MainForm();

 // We want to pass along the command-line arguments to this first instance

 // Allocate room in our string array
 ((MainForm)this.MainForm).Args = new string[this.CommandLineArgs.Count];

 // And copy the arguments over to our form
 this.CommandLineArgs.CopyTo(((MainForm)this.MainForm).Args, 0);
}

Last thing is setting application to pass command line arguments to our form when second instance is run:

protected void SIApp_StartupNextInstance(object sender, 
                StartupNextInstanceEventArgs eventArgs)
{
 // Copy the arguments to a string array
 string[] args = new string[eventArgs.CommandLine.Count];
 eventArgs.CommandLine.CopyTo(args, 0);

 // Create an argument array for the Invoke method
 object[] parameters = new object[2];
 parameters[0] = this.MainForm;
 parameters[1] = args;

 // Need to use invoke to b/c this is being called from another thread.
 this.MainForm.Invoke(new MainForm.ProcessParametersDelegate(
  ((MainForm)this.MainForm).ProcessParameters), 
  parameters );
}

Of course, you need to have proper delegate type in your form declared, and implemented target function for processing parameters:



public delegate void ProcessParametersDelegate(object sender, string[] args);
public void ProcessParameters(object sender, string[] args){ /* ... */ }

Wednesday, October 3, 2012

[C#]Remove HTML tags from string

As discussed in the comments, this approach is wrong:
  1. System.Text.RegularExpressions.Regex regHtml = new System.Text.RegularExpressions.Regex("<[^>]*>");
  2. string s = regHtml.Replace(InputString,"");
Best option here is to use proper parser to extract the text from HTML. In the past I've worked with Html Agility Pack, so you could give it a try! I will probably small snippet of code to show you how to use it in the morning!

Good night for now!

[WinForm] Panel with dock "Fill" value is under "Top" docked panel

If you have header panel which should dock to the Top in the form and if you want to add new panel which will fill the rest of the form, you can get into problem because docking is calculated only by previous siblings in the document, and you can get document structure like this:

You can see that main panel (red border) is filled the whole form, not just remaining space. Easy fix is to right click main panel and click "Bring to front" or to move it before in document hierarchy (you can get this window in View - Other Windows - Document Outline.

An error occurred creating the form. See Exception.InnerException for details. The error is: Object reference not set to an instance of an object

If you get this error while launching VB.NET program, and if debugger points to nowhere, possible cause is that you are referring  to uninitialized control somewhere in constructor. To fix this error, you should disable Just My Code "feature" in Tools - Options - General - Debugging


VB.NET equivalent of typeof() operator

Instead of C#'s typeof() operator, VB.NET uses GetType operator. Please note that there is TypeOf() operator in VB.NET, but it is used in conjunction with Is keyword to check at runtime for checking if object is of particular type.

For more information, you could check Joacim's blog

C# static methods in VB.NET

I was suprised by the lack of class (static) methods in VB.NET. Quick Google search pointed that class methods are called Shared in VB.NET:


Private Class BackupHistory
        Public BottomText() As String
        Public LastInserted, CurrentlyVisible As Integer

        Public Shared Sub Serialize(ByVal history As BackupHistory)
            '...
        End Sub
End Class

Multiline label in WinForms

To create multiline label in WinForms, all you need is to in press arrow near to the Text property Property Box and you can write multiline text there. There is no need for "Multiline" property, as in TextBox controls.