D'oh! Net Compact Framework Weblog
D'oh!, the grunt made popular by Homer Simpson. When originally created, the word didn't have an official spelling. Instead, it is written as "annoyed grunt". D'oh! Microsoft Net Compact Framework has many limitations! Mostly copy-paste notes with original source about development on Microsoft Windows Embedded CE.
Wednesday, July 13, 2011
GC.WaitForPendingFinalizers();
Wednesday, September 3, 2008
Get Name of Executing *.EXE
The Compact Framework doesn't support Assembly.GetEntryAssembly to determine the launching .exe. You can instead P/Invoke the native GetModuleFileName function like so:-
byte[] buffer = new byte[MAX_PATH * 2];
int chars = GetModuleFileName(IntPtr.Zero, buffer, MAX_PATH);
if (chars > 0)
{
string assemblyPath = System.Text.Encoding.Unicode.GetString(buffer, 0, chars * 2);
}
Where MAX_PATH is defined in the Windows CE headers as 260. The P/Invoke declaration for GetModuleFileName looks like this:-
[DllImport("coredll.dll", SetLastError = true)]
private static extern int GetModuleFileName(IntPtr hModule, byte[] lpFilename, int nSize);
The function expects a HMODULE - a handle to a native module. However passing IntPtr.Zero here indicates we want the module which created the process which is our .exe. This code will always return the path of the calling .exe regardless of if it is in a utility dll, or even a GAC assembly located in the \Windows folder.
Source: Peter Foot
Friday, August 22, 2008
Creation Of NK.NB0 File
Manual generation of an nb0 :
Platform builder environment provide two tools for the generation of the nb0 files. The first one Viewbin used to see the properties of the bin file, the second one Cvrtbin used to convert the bin file into an nb0 file using the information provided by viewbin.
So open your OSDesign and go to Build -> Open Release Directory in Build Window, it will show up a command line window setup for your project.
Use : viewbin nk.bin
Image Start = 0x00220000, length = 0x00AC136C
Start address = 0x0023D618
Checking record #72 for potential TOC (ROMOFFSET = 0x80000000)
Found pTOC = 0x80ce02c0
ROMOFFSET = 0x80000000
Done.
cvrtbin -r -a 00220000 -l 00ac136c -w 32 nk.bin
Values may vary for your nk.bin as those information are related to the settings of your BSP and OSDesign.
Source: Nicolas Besson
Tuesday, April 22, 2008
Microsoft Visual Studio & Microsoft Windows CE Development
Developers building Windows CE based devices fall into one of two groups, you are either an operating system developer, or an application developer (and yes, you could be both).
1. Operating System Developer.
For the operating system developer, the CE 6.0 development tools are a plug in to Visual Studio 2005 - the Full CE 6.0 product ships with a full version of Visual Studio 2005 - The CE 6.0 development tool (Platform Builder) gives you the ability to configure, build, download, and debug your custom operating system image. Platform Builder also gives you the ability to write Win32 (C/C++) applications, or DLLs (where the DLL can export functions shared between applications, resource only DLLs, or the DLL could be a device driver in the operating system image).
Operating system developers need Visual Studio 2005, and the CE 6.0 development tools.
2. Application Developer.
Application developers typically don't need access to the underlying operating system development tools, the application developer codes against a "platform". For native code developers (Win32, MFC, *TL), this means that you code against a Windows CE Platform SDK - since you are a native code developer this means that you are calling the Win32 APIs on the operating system directly (MFC is a thin wrapper over Win32) - Since Windows CE is a componentized operating system the exact APIs exposed from a customized "platform" are determined by the embedded operating system developer.
Once a Windows CE configuration is complete, the embedded o/s developer builds a custom SDK (Software Development Kit) that defines the exposed APIs for that specific platform (through header files and libraries). This SDK can then be shared with application developers who install the SDK into Visual Studio 2005 and/or Visual Studio 2008.
The native code developer codes against the custom platform SDK.
Managed code developers have a slightly easier time - the .NET Compact Framework *defines* the underlying platform APIs, when you add the compact framework to a platform configuration a set of operating system dependencies automatically gets added to the platform - as a managed application developer you know that the .NET class libraries are there - if you want to escape the box (platform invoke) then you need to know which native code APIs exist for your specific platform.
Application developers can choose to develop using Visual Studio 2005 OR Visual Studio 2008.
Source: Mike Hall
Detect Windows Mobile Version – Adaptation Kit Update (A.K.U.)
If you want to know which version of known Adaptation Kit Update (AKU) releases you have in your device, check out this link.
To see the AKU of your device, you can :
type : Start / Settings / System Tab / About
Using a C# application, the OSVersion.Version method returns build information.
Using the Registry : HKLM\SYSTEM\Versions\Aku
Source: Fabien Decret
Create Custom Animated Cursor
Creating a custom cursor
Recent versions of the Windows CE operating system (and hence Windows Mobile) support an OS API called LoadAnimatedCursor. This API enables you to specify a sequence of individual bitmap frames and will convert them into an animated cursor. For example an animated cursor of a rotating monkey could be made up of the following 4 bitmaps, for example, bitmap value 101, 102, 103 and 104.
The more frames the cursor consists of the smoother the animation will be. Individual frames within the animation should be 48×48 pixel bitmap resources within a *.dll or *.exe file. The bitmap resources are identified by a numeric ID and must be in sequential order (such as the values 101, 102, 103 and 104 used in the example above).
The id of the first bitmap, the total number of frames and the period of time to delay between frames is then passed into the LoadAnimatedCursor API which will return a handle to the newly created cursor (an HCURSOR). Passing this handle to the SetCursor API will then make the cursor visible on the screen.
Unfortunately the LoadAnimatedCursor function is not as easy to use from managed code as it should be. The API expects the bitmap images to be native bitmap resources meaning you can not store them within a *.resx resource file within your .NET Compact Framework application. The easiest way to store the bitmaps in the correct format is to create a native C++ DLL project. You can then remove all the C++ source files, leaving a sole Win32 *.rc resource file to which you can add the bitmaps to (as will be demonstrated later).
Sample Application
[Download animatedcursortest.zip - 37KB]
The sample application available for download consists of two projects. The first (called AnimatedCursors) demonstrates how to create a resource only DLL that contains the bitmap images required for the two custom cursors shown above.
The second project is a C# example demonstrating how to use Platform Invoke to access theLoadAnimatedCursor and SetCursor APIs to display the custom cursors. This second project loads the custom cursors from the AnimatedCursors.dll file built by the first project.
The C# sample wraps up the required Platform Invoke code within a class called AnimatedWaitCursor. This class implements the IDisposable interface so that the following syntax can be used to display a custom cursor. This code structure should be familiar to anyone who has used MFC's CWaitCursor class.
// Use the animated cursor that has 4 frames starting with
// bitmap id 101, delaying 125 milliseconds between each frame.
string dll = @"\path\to\some.dll";
using (AnimatedWaitCursor cursor = new AnimatedWaitCursor(dll, 101, 4, 125))
{
// do some long running task
}
Using Delegates (i.e. Function Pointers)
Ever since learning how to use function pointers in C, I've always been a fan of using them to help make code a bit more usable, especially when you've got a state machine. Today, as I'm working on a Wizard UI for a desktop application I came across a typical scenario for using a function pointer. Depending on the stage of the Wizard you're in, a button will have to do separate things.
That got me to thinking that most managed developers simply don't understand the power and utility of delegates, but instead simply consider them a necessity when using Control.Invoke or creating custom events. Sure, in my case I could have a switch statement in the click handler and do logic there, or I could unhook the click handler from one method and hook it to another, but those all seem ugly and a pain in the ass to me. A simple function pointer change is all you need. So I decided I'd throw together a really simple example of how you would use a delegate to change the behavior of a Button click.
Let's assume that we have a button that we want to click, and when it's clicked it will do one of 4 things, depending on the state of our application. We'll just use a messagebox here to give you the idea - what it does is up to you- it's a function after all.
public
void FunctionA()
{
MessageBox.Show("FunctionA");
}
public
void FunctionB()
{
MessageBox.Show("FunctionB");
}
public
void FunctionC()
{
MessageBox.Show("FunctionC");
}
public
void FunctionD()
{
MessageBox.Show("FunctionD");
}
To simulate the different "states" I simply added a ListBox (called functionList) to the Form and manually added the function names to it in the Form's constructor. Sure, I could have used Reflection to be clever and populate the list, but I'm tryiong to keep it simple and show delegates.
functionList.Items.Add("FunctionA");
functionList.Items.Add("FunctionB");
functionList.Items.Add("FunctionC");
functionList.Items.Add("FunctionD");
Alright, so now we know that depending on which item is selected, we want to call one of our four functions. Since they all have the same interface (and they have to to use a delegate) we simply define a delegate that matches them. This delegate can be privately scoped inside your class.
delegate
void FunctionDelegate();
And then we create an instance variable to hold the current function pointer we want to use:
private FunctionDelegate m_functionPointer =
null;
We add an event handler for the SelectedIndexChanged event of the ListBox (in the Form constructor)
functionList.SelectedIndexChanged += new EventHandler(functionList_SelectedIndexChanged);
And implement the event handler. It simply looks at the newly selected index in the list and changes the value stored in m_functionPointer appropriately.
void functionList_SelectedIndexChanged(object sender, EventArgs e)
{
// determine which function pointer to store based on selection
switch (functionList.SelectedIndex)
{
case 0:
m_functionPointer = FunctionA;
break;
case 1:
m_functionPointer = FunctionB;
break;
case 2:
m_functionPointer = FunctionC;
break;
case 3:
m_functionPointer = FunctionD;
break;
default:
m_functionPointer =
null;
break;
}
}
Next we wire up an event handler for our button (again the the Form constructor):
callButton.Click += new EventHandler(callButton_Click);
And finally the magic and simplicity of the state-dependent call
void callButton_Click(object sender, EventArgs e)
{
// call our function (as long as it's not null)
if (m_functionPointer !=
null)
{
m_functionPointer();
}
}
That's all there is to it. Run the application, select a function and click the button.
Source: Chris Tacke