Some notes on software development... RSS 2.0
# Wednesday, 18 February 2009

I had an issue with a compact framework project where I needed to add a shortcut on the desktop that pointed to my application whose location was \Program Files\MyApplication\.
You need to create a .lnk text file and place it on the device's desktop. However, .lnk files are a bit tricky to use with Visual Studio 2008 because it thinks it is an actual shortcut to a file on your actual desktop machine.

Mike Hall has a blog article that further covers Windows CE shortcuts.

Here are my steps on how to overcome the .lnk issue when using a Smart Device CAB project from within Visual Studio 2008.

My application is called MyApplication.exe and it's full path, once installed on Windows CE, is \Program Files\MyApplication\MyApplication.exe
All my application does is show 'Hello World' in a label on the form.
My Windows CE installer project is called MyWindowsCEInstaller.

First I create the application and installer projects and added the project output of MyApplication to the MyWindowsCEInstaller project. Here is what my solution looks like so far:

image

Next step is to create the shortcut file that will eventually be placed on the device desktop. To do this I created a new text file within the MyApplication project called MyApplication.lnkx
It's 'Build Action' property should be set to None and 'Copy to Output Directory' property set to Do Not Copy.
It is a lot easier to work with the file having the extension as .lnkx so that Windows doesn't think it is an actual shortcut file.

The MyApplication.lnkx file will contain the command line text and the command line character count separated by a hash (#).
So my Windows CE application full path is \Program Files\MyApplication\MyApplication.exe making the character count 48, below is my MyApplication.lnkx file:

image

Note:- If the path contains a space it must be enclosed in quotes and they get included in the command character count!!!

Next step is to add our MyApplication.lnkx file to the correct folder in the MyWindowsCEInstaller project.

From the root of the Primary Output File System view of the MyWindowsCEInstaller project add the Windows Special Folder.
Under the Windows folder create a new folder called Desktop

Add the MyApplication.lnkx file to the newly created Desktop folder.

image

Next, select the MyApplication.lnkx file from the MyWindowsCEInstaller project and change the TargetName to be MyApplication.lnk
This will change the extension off the shortcut file on the target device to be .lnk while on the development machine it will stay as .lnkx

The final files should look like this:

image image


Build the solution, copy the CAB file to the device, install it and now there should be desktop shortcut that points to the MyApplication application ;-)

image image

Note that the shortcut will also use the application icon as it's image once this has been set in the application properties, here it is the default image.


Links
Mike Hall Windows CE Shortcuts Blog Article

Wednesday, 18 February 2009 17:31:35 (GMT Standard Time, UTC+00:00)  #    -
CF | CE Devices
# Thursday, 11 September 2008

You cannot arbitrarily change the Target Framework in Smart Device Projects like you can for standard .NET projects.
You need to upgrade the project via the Project->Upgrade Project option like so:

image

image 

The project will then be compiled against the latest version of Compact Framework, here it is 3.5 for my machine.

Note:- you may need to change the available devices/emulators by choosing 'Change Target Platform' from the same menu.

Thursday, 11 September 2008 11:11:38 (GMT Standard Time, UTC+00:00)  #    -
CF | Visual Studio
# Wednesday, 19 March 2008

Note:- the code for this article is directly taken from Chris Tacke's Blog, see footer link.

If there is a process that you need to kill that does not have a running window i.e. an app that sits in the CE system tray you need to use the Kill method from the ProcessEntry class when using Smart Device Framework.

First you need to get a list of running processes. Then you compare each running process name to the name of the process you want to kill.
Then simply call the Kill method.

image

Warning: Calling the kill method will immediately shutdown the process. You could lose any unsaved data when killing a process this way.
If the process has a graphical window it is better to close the application gracefully by sending a close window message to the application, which in turn will close down correctly and save any data if it has been coded correctly ;)
To do that look here: Kill a process with SendMessage in Compact Framework

Links
Chris Tacke blog article

Wednesday, 19 March 2008 16:23:42 (GMT Standard Time, UTC+00:00)  #    -
CF
# Friday, 14 March 2008

With the full .NET library you can call Application.ProductVersion to get the version number of your running application.
This method is not available for Compact Framework so we have to use reflection to help us interrogate the running assembly.

The info we need is held in the AssemblyName class and which we can populate by calling GetExecutingAssembly static method from the Assembly class in the System.Reflection namespace.
The code:

AssemblyName currentAssemblyName = Assembly.GetExecutingAssembly().GetName();
string version = currentAssemblyName.Version.ToString();
 
Friday, 14 March 2008 11:54:42 (GMT Standard Time, UTC+00:00)  #    -
CF
# Thursday, 28 February 2008

On a CE device, when a touch screen is pressed, the running application will receive a mouse click message. This message then gets filtered down through the application and eventually arrives at where it is supposed to be in the application level, i.e. click on a button control.

So to completely disable the touch screen on a Windows CE device you can suppress any mouse button messages that get sent from the device thus preventing them from getting dispatched to you application.

To do this you can add a filter object (that implements IMessageFilter) to the application's message pump, check the message type, if the message is a mouse click message then cancel it.

Unfortunately message filtering with CF 2.0 is not supported out of the box however, luckily for us the clever chaps at OpenNETCF have provided us with the classes we need to complete the task with their excellent Smart Device Framework library.

On to some code...here is my DisableTouchScreenFilter class that implements the IMessageFilter:

using System;
 
using Microsoft.WindowsCE.Forms;
using OpenNETCF.Windows.Forms;
 
public class DisableTouchScreenFilter : IMessageFilter
{
    private const int WM_MBUTTONDBLCLK = 0x0203;
    private const int WM_LBUTTONDOWN = 0x0201;
    private const int WM_LBUTTONUP = 0x0202;
 
    public bool PreFilterMessage(ref Message message)
    {
        bool result = false;
 
        if (message.Msg == WM_LBUTTONUP ||
            message.Msg == WM_MBUTTONDBLCLK ||
            message.Msg == WM_LBUTTONDOWN)
        {
            result = true;
        }
 
        return result;
    }
}


You can actually check any Windows message that arrives at the PreFilterMessage method, however I have only defined the message constants that are required for handling the mouse click message.
For a full list of what all the Windows message are you can check out Windows Message (Enums).

To plumb in the filter to the application message pump you need to call the static AddMessageFilter method on the Application2 object. To remove the filter call the RemoveMessageFilter method passing in the same filter object.

An example of adding the message filter to the Application message pump:

Application2.AddMessageFilter(new DisableTouchScreenFilter());


Notes
You need to run your application using the Application2 class from the Smart Device Framework library.
The mouse message gets completely cancelled before it gets to any forms or controls. This means that absolutely no mouse click events will fire at all.
There may be a slight performance hit with the application due to the message filter evaluating ever message that gets passed to the application.



Thursday, 28 February 2008 18:01:41 (GMT Standard Time, UTC+00:00)  #    -
CF
# Tuesday, 19 February 2008

To close a process correctly you should send a close message to the application rather than just killing it, this way the application can close down gracefully.
With Compact Framework you can use the excellent OpenNETCF Smart Device Framework to send a CLOSE windows message to a window handle.
To get the correct window handle you need to use the Win32Window class from the OpenNETCF.Win32 namespace. You need to know 2 pieces of info for this - the process class id and the window name.


Finding the process Class Id and Window Name

To find the process class Id you can use handy Remote Spy application which is part of the Visual Studio 200x installation.
Start the application you want to shutdown on the CE device and connect to the device with Remote Spy.
When Remote Spy has connected it will load up a list of running processes. Find the process for your running application. Here the application I want to shutdown is called S3 Client. Double clicking the list item will bring up the Window Property dialog.
From this dialog I can get the Class Id (#NETCF_AGL_BASE_) and the Window Name (S3 Client). The Window Name is actually the form caption so you might already know that info ;)


Sending the CLOSE message to the Window

Pass in the Class Id and Window Name to the Win32Window.FindWindow method. This will return a reference to the Win32Window object. We can now use this object to get the handle to pass in to the Win32Window.SendMesage method as shown below:

Win32Window theWindow = Win32Window.FindWindow("#NETCF_AGL_BASE_", "S3 Client");

if (theWindow != null)
    Win32Window.SendMessage(theWindow.Handle, (int)WM.CLOSE, 0, 0);

Tuesday, 19 February 2008 09:27:44 (GMT Standard Time, UTC+00:00)  #    -
CF
# Thursday, 14 February 2008

To convert an Icon to be used as a Bitmap you can use this function:

   
private Bitmap IconToBitmap(Icon icon)
{
    Bitmap bmp = new Bitmap(icon.Width, icon.Height);

    using (Graphics g = Graphics.FromImage(bmp))
    {
        g.DrawIcon(icon, 0, 0);
    }

    return bmp;
}

Thursday, 14 February 2008 11:49:30 (GMT Standard Time, UTC+00:00)  #    -
CF
Navigation

Sign In
Extras
Statistics
Total Posts: 116
This Year: 0
This Month: 0
This Week: 0
Comments: 36
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2017
Hadrian Phillips

All Content © 2017, Hadrian Phillips
DasBlog theme 'Business' created by Christoph De Baene (delarou)