Thursday, January 31, 2008

My Windows Mobile does not sound alarms / my Windows Mobile alerts whenever it want to alert

Many of Windows Mobile users are suffering from different problems, related to clocks, alarms and reminders. This problem exists almost in all Windows Mobile systems (Windows Mobile 2003, WM5, WM6, etc).  Why this happens and how to take care on it?

There root of this problem is something called "Notification Queue". The main propose of it is to run tasks and activate alarms and reminders at scheduled times, particularly when the device is in standby or low power mode.  There are a lot of problems with this module - troubles with alarm and reminders, which not working, or, alternatively, playing not in time after device reboot.

There are some bugs, reported to Microsoft and one of topmost requests from the next version of Windows Mobile is to produce more reliable alarm clock. 

For some reason, there is very little information about working with notifications queue in internet. There is absolutely no information about it in MSDN. And a lot of misinformation all over the network. I gathered up all I can from anywhere and now, I know what the cause for problems with alarms, alerts, notifications and reminders in Windows Mobile systems. I also learned how to fix it.

The root problem of notification queue is duplicate entries, produced by different applications, such as clock, ActiveSync, Alert, missed calls notifies and more. Windows mobile has no tools to treat this problem.

I build such tool and called it AlarmFixWM. It scans your Windows Mobile system for duplicate entries in notification queue and eliminate them. All you have to do, is do download it, put it into one of directories inside your mobile device (no installation), then run and hit Scan button. The program will do all the rest.

image

If you are not suffering from problem, related to Windows Mobile alerts, do not use this application.

I'd be happy to hear your feedbacks (also, if you want to learn more about this problem, you can ask me). And don't forget to backup your device before using this program!

Are there other tools, doing the same work? Yes, there are two: MemMaid and SKTools. Both are commercial and doing much more (cleaning your device inside). If all you want, is to get rid of wrong or not occurred alarms, AlarmFixWM is all you need.

Download AlarmFixWM (12.1k) >>

Tuesday, January 29, 2008

Microsoft almost never paying their presenters, so why we're coming?

In most cases, presenters, participate in TechEd, DevAcademy, open houses or other public sessions, arranged by Microsoft, are not get paid. However, we're still coming and presenting. Preparation of even small session takes at least a couple of days and costs us a lot of money, but we're still coming and presenting. Why?

The answer is not simple. So, in order to make it clearer to me, I created decision chart, that helps me to answer "yes" or "no" for next request to attend an event as presenter. Here it comes

image

Let me explain it for you. My hour costs at about 100$. To present at small event, I should prepare in ratio of 1/3 - for one hour session, I have to work at least three hours + arrangements, travel time, accommodations etc. Other words, one small session should costs about 1000$. Can they pay me what I'm worth? Probably they can, but there are other factors - what am I earn for example.

If I'm interested within attendees, I can generate more revenue from business opportunities, then from one time payment. Thus I wont ask to be paid. But sometimes, I might me unable to get such revenue. In this case, I'm asking another question: maybe inviters really need my help and I can allow myself to publish some charity? In this case I'll attend too.

So should Microsoft pay their presenters? Probably it should, but there are other factors should be took into account.

See me at TechEd '08 in Eilat :)

Printing more then one page, creation in memory XPS document and DocumentViewer customization

Today, we'll answer number of questions, regarding DocumentViewer, XPSDocument, FlowDocument and more

First question: I'm trying to display FlowDocument, by using DocumentViewer and I'm getting "FlowDocument' object cannot be added to 'DocumentViewer'. DocumentViewer supports only FixedDocument or FixedDocumentSequence documents". What to do?

First answer: DocumentViewer supports only fixed document source (one, which implements IDocumentPaginatorSource - other words supports pagination). In order to do it, we have to convert FlowDocument into FixedDocument and we can do it, by using XpsDocument and it's GetFixedDocumentSequence() method to create the page sequence.

Second question: But I do not want to save anything, I want to do it in memory. What to do?

Second answer: First load your FlowDocument by using XamlReader into IDocumentPaginatorSource (that's what we'll need for DocumentViewer)

<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">

    <Paragraph>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam urna augue, semper ut, condimentum et, pharetra ac, massa. Cras tellus lacus, tristique eget, tincidunt vitae, mattis at, eros. Quisque pretium, ante at porttitor accumsan, ipsum enim laoreet tellus, sit amet aliquet felis tortor et lorem. Nullam sodales viverra sapien. Morbi leo magna, dignissim a, sollicitudin at, lacinia posuere, dui. Sed vestibulum elit a ante. Vivamus pellentesque augue sit amet enim. Pellentesque dignissim, lectus at congue elementum, augue felis vulputate ante, eu bibendum dui mauris sed magna. Cras metus dui, ullamcorper id, fermentum ornare, hendrerit non, libero. Donec blandit lorem sit amet velit. Phasellus aliquam. In vel urna sit amet lorem molestie tristique. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nulla aliquam urna sit amet enim. Integer vulputate mauris non diam. Vestibulum ac mauris. Proin porttitor adipiscing nibh. Phasellus neque. Sed sollicitudin eros in diam. Quisque accumsan, neque non volutpat semper, lectus nunc porttitor libero, at pretium purus velit eget mauris.</Paragraph>

    <Paragraph>Sed ac mauris. Nulla eu augue ut est pellentesque blandit. Phasellus non quam ac neque suscipit vehicula. Donec mauris augue, pulvinar at, vestibulum quis, vulputate et, nunc. Sed ut pede. Praesent ut justo id justo nonummy porttitor. Vivamus vitae massa sit amet massa scelerisque aliquam. Nullam ligula justo, suscipit id, sollicitudin at, pretium a, lorem. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. In hac habitasse platea dictumst. In quam dui, gravida quis, congue ac, rhoncus ac, mi. Donec mattis tempor orci. Mauris ullamcorper. Donec non sem vel tortor imperdiet euismod. Morbi nec eros. Maecenas quis turpis at lorem semper ullamcorper.</Paragraph>

</FlowDocument>

using (Stream io = Assembly.GetExecutingAssembly().GetManifestResourceStream("PagePrint.text.xaml"))
            {
                IDocumentPaginatorSource text = XamlReader.Load(io) as IDocumentPaginatorSource;
                io.Close();
            }

Now, let's create Xps document in memory and load our text into it

ms = new MemoryStream();
pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);

doc = new XpsDocument(pkg, CompressionOption.SuperFast);
XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(doc), false);
DocumentPaginator pgn = text.DocumentPaginator;
rsm.SaveAsXaml(pgn);
viewer.Document = doc.GetFixedDocumentSequence();

We got an exception: "XpsDocument URI is null. Use XpsDocument constructor that takes URI parameter." But we have no URI, we are working in memory!

Third question: What to do?

Third answer: All you have to do is to add another package with URI, that identifies our document and create XPS document, by using the new identifier. We'll add it into current code and now it'll looks as following:

ms = new MemoryStream();
pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);

string pack = "pack://temp.xps";
PackageStore.AddPackage(new Uri(pack), pkg);

doc = new XpsDocument(pkg, CompressionOption.SuperFast,pack);
XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(doc), false);
DocumentPaginator pgn = text.DocumentPaginator;
rsm.SaveAsXaml(pgn);
viewer.Document = doc.GetFixedDocumentSequence();

Well, now it works, but we still have another questions

Forth question: How to set the page size for my document?

Forth answer: You already have DocumentPaginator, why not to use it?

ms = new MemoryStream();
pkg = Package.Open(ms, FileMode.Create, FileAccess.ReadWrite);

string pack = "pack://temp.xps";
PackageStore.AddPackage(new Uri(pack), pkg);

doc = new XpsDocument(pkg, CompressionOption.SuperFast,pack);
XpsSerializationManager rsm = new XpsSerializationManager(new XpsPackagingPolicy(doc), false);
DocumentPaginator pgn = text.DocumentPaginator;

pgn.PageSize = new Size(768, 676);

rsm.SaveAsXaml(pgn);
viewer.Document = doc.GetFixedDocumentSequence();

Well done. Now our page is 8"x6" (1 inch = 96px in default resolution). Now it almost ok, but I want to customize DocumentViewer, used to present our document

Fifth question: How to remove search field ("Type text to find...") or how to customize buttons?

Fifth answer: DocumentViewer is regular WPF control, thus in order to customize it, you should override it's default template

By default the controls looks

image

But if you'll remove <ContentControl Grid.Row="2" x:Name="PART_FindToolBarHost"/> line from the control template, you'll get rid of the search bar. Of couse, you can customize anything you want within the control template of any WPF control.

image

We done. Have a nice XPS/WPF programming.

Source code for this article

Monday, January 28, 2008

Weird bug in Windows Vista

Well, there are some (ghm) bugs in Windows Vista. Most of those bugs are not harmful for your system, however there are some, that ready are. Here the little bug, I experienced today. Follow those steps to repro (don't do it on files you need)

  • Select multiple files
  • Right click on those files and choose rename and change the name of one of those files
  • Hit enter
    • Expected result: all selected files renamed (name (0),name (1), name (2) etc)
    • Actual result: all selected files renamed (name (0),name (1), name (2) etc)
  • Hit Ctrl-Z (Undo)
    • Expected result: all renamed files undo to it's original names
    • Actual result: all renamed files undo to it's original names
  • Hit Ctrl-Y (Redo)
    • Expected result: all undid files redo to it's new names
    • Actual result: all files, except the first one, disappeared.

They are really disappear, they did not removed or deleted. They just disappear.

Workaround: Don't redo multiple rename action.

 

Have a nice day

Friday, January 25, 2008

RTFM - Not only software needs manual, kids need it too - How to care your child (visual instructions)

For all my friends, become fathers and mothers within last couple of months. Please, read it before using your kids!

kidcare kidcare (2) kidcare (3) kidcare (4) kidcare (5) kidcare (6) kidcare (7) kidcare (8) kidcare (9) kidcare (10) kidcare (11) kidcare (12) kidcare (13) kidcare (14) kidcare (15) kidcare (16) kidcare (17) kidcare (18) kidcare (19) kidcare (20) kidcare (21) kidcare (22) kidcare (23) kidcare (24) kidcare (25) kidcare (26) kidcare (27) kidcare (28)

Stop subclassing and using Helpers - start Extension Methods

How many classes, named Helper, you have on your hard disk? I counted, and I have 320. What is "Helper"? Helper - is static class, that consists of static methods, that provide simple services to your program. Good examples for such methods are

public static string FormatTime(TimeSpan time)
        {
            return time.Hours.ToString("00") + ":" + time.Minutes.ToString("00") + ":" + time.Seconds.ToString("00");
        }

or

public static byte[] ConvertObjectToByteArray(object obj)
        {
            byte[] _resp = null;
            BinaryFormatter formatter = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream())
            {
                formatter.Serialize(ms, obj);
                _resp = ms.ToArray();
            }

            return _resp;
        }

or, even

public static byte[] Compress(byte[] buffer)
       {
           MemoryStream ms = new MemoryStream();
           GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true);
           zip.Write(buffer, 0, buffer.Length);
           zip.Close();
           ms.Position = 0;

           MemoryStream outStream = new MemoryStream();

           byte[] compressed = new byte[ms.Length];
           ms.Read(compressed, 0, compressed.Length);

           byte[] gzBuffer = new byte[compressed.Length + 4];
           Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
           Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
           return gzBuffer;
       }

Those stand-alone methods are in use all over the application and provide small, frequent services.

What are disadvantages of such approach?

  • Another class = wider maintenance
  • You never know where it in use (even after searching)
  • You should remember all services provided
  • Sometimes, you have a number of overloads for those methods in order to make it's using simpler.
  • If you are working on shared project, someone can harm all your project, by changing "something small" in Helper class.

Can we do something else? Yes, we can. We can subclass our objects and hide those methods inside it. This approach is even worse. In spite of easiness of intellisense, provided with this method, you'll have large number of almost the same classes with little changes. Also, we cannot do anything with sealed classes.

What to do? In C# 3.0 (not only WPF), Extension Methods were introduced. What is it? The same "Helper", with only one difference - this keyword before the first argument. So, when changing our code to following:

public static string FormatTime(this TimeSpan time)
        {
            return time.Hours.ToString("00") + ":" + time.Minutes.ToString("00") + ":" + time.Seconds.ToString("00");
        }

or

public static object ConvertByteArrayToObject(this byte[] data)
        {
            object[] _resp = null;

            BinaryFormatter formatter = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream(data, 0, data.Length))
            {
                try
                {
                    object _tmp = formatter.Deserialize(ms);
                    _resp = _tmp as object[];
                }
                catch
                {
                    _resp = new object[1];
                }
            }

            return _resp;
        }

or, even

public static byte[] Decompress(this byte[] gzBuffer)
        {
            MemoryStream ms = new MemoryStream();
            int msgLength = BitConverter.ToInt32(gzBuffer, 0);
            ms.Write(gzBuffer, 4, gzBuffer.Length - 4);

            byte[] buffer = new byte[msgLength];

            ms.Position = 0;
            GZipStream zip = new GZipStream(ms, CompressionMode.Decompress);
            zip.Read(buffer, 0, buffer.Length);

            return buffer;
        }

We will able to use all those methods within regular classes of argument type. Full intellisense support and very easy syntax. Like this.

image

But, do not go to extreme with extension methods, 'cos you likely face with the problem, exists now with arrays and Linq - too much extensions. You'll never know what are the original class methods (except icons :)). See yourself

image

Have a nice day. I had not time (as always) to review this post before publishing :)

Thursday, January 24, 2008

SVG vs. Silverlight head-to-head fight

Adobe stops supporting SVG next year, thus there are some SVG consumers are looking for the replacement of this technology, by other, that will be supported. The only technology, can actually replace SVG is Silverlight. Yes, Flex, too, but it's too complicated to perform transitions. Today, we'll look into those two technologies and try to understand how to perform migration easily. Let's start from SVG (Adobe SVG 3.x) vs SL (Silverlight 1.0) syntax

SVG

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/SVG/DTD/svg10.dtd">
<svg width="200" height="100">
</svg>

SL

<Canvas  xmlns="http://schemas.microsoft.com/client/2007"
  Width="200" Height="100">
</Canvas>

Looks pretty the same, no? At least, very similar. Let's see what's going with text.

SVG

<text x="10" y="15" font-size="12">
  Hello World!
  <tspan x="10" dy="1.6em" font-size="8">This is</tspan>
  <tspan x="10" dy="1.6em" font-size="20">SVG text</tspan>
</text>

SL

<TextBlock Canvas.Left="10" Canvas.Top="15" >
  <Run Text="Hello World!" FontSize="12"/>
  <LineBreak/>
  <Run Text="This is" FontSize="8"/>
  <LineBreak/>
  <Run Text="Silverlight text"  FontSize="20"/>
</TextBlock>

Similar too, but what's about rendering? From now and on, you'll need Silverlight 1.0 and SVG 3.x plugins in order to see working samples.

Let's look closer

image

And even more closer

image

Silverlight renders small and large text much better, then SVG do.

Our next station is splines and simple geometry.

SVG

<rect width="100" height="50" fill="blue" stroke="black"  stroke-width="3" x="0" y="0"/>

SL

<Rectangle Width="100" Height="50" Fill="Blue" Stroke="Black" StrokeThickness="3" Canvas.Left="0" Canvas.Top="150" />

That's look very similar. What's about lines?

SVG

<path fill="white" stroke="black" stroke-width="2" d="M20,140 Q100,20 100,140 Q100,220 180,140" />

SL

<Path Fill="White" Stretch="Fill" Stroke="Black" StrokeThickness="2" Data="M20,140 Q100,20 100,140 Q100,220 180,140"/>

That's the same. Even coordinates and tangents are equal. So, how it renders?

image

Well. There are some differences here.

Never mind, let's go on into animations

SVG

<circle cx="200" cy="150" r="40" fill="red">
    <animate attributeName="cy" dur="5s" repeatCount="indefinite" keySplines="0.5 0.1 0.9 0.5;0.1 0.5 0.5 0.9" calcMode="spline" keyTimes="0;2.5;5" values="150;350;150"/>
  </circle>

SL

<Ellipse Width="80" Height="80" Fill="Red" Canvas.Left="160" Canvas.Top="-91" x:Name="ellipse">
    <Ellipse.Triggers>
        <EventTrigger RoutedEvent="Canvas.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.Y)" RepeatBehavior="Forever">
                        <SplineDoubleKeyFrame KeyTime="00:00:02.5" Value="200" KeySpline="0.5 0.1 0.9 0.5"/>
                        <SplineDoubleKeyFrame KeyTime="00:00:05" Value="0" KeySpline="0.1 0.5 0.5 0.9"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Ellipse.Triggers>
    <Ellipse.RenderTransform>
        <TransformGroup>
            <TranslateTransform/>
        </TransformGroup>
    </Ellipse.RenderTransform>
</Ellipse>

Here, it looks like a lot of differences, however, if you'll look into code, you'll see, that there are no difference between the methods. Even key splines are the same. Let's look deeper into code.

SVG SL
circle Ellipse
animate DoubleAnimationUsingKeyFrames
cx,cy Width, Height
attributeName TargetName+TargetProperty
dur KeyTime
repeatCount RepeatBehavior
keySplines KeySpline+KeySpline
calcMode SplineDoubleKeyFrame
keyTimes KeyTime+KeyTime
values (absolute) Value (relative)

 

That's all. After all, there are very similar methods and objects are in use. The only difference, that Silverlight is much more flexible, then SVG in animation. Let's see the result (if the ball is breaking on the edge, just reload internal page - this is load time issue)

So, after all if you know SVG, you can start developing Silverlight (don't go back :) ).

All this nice, but what's the problems? Well, there are some. In Silverlight 1.0, there is no Tile or Visual brushes, thus you can not create following effect (this is checker board)

SVG

<defs>
<pattern id="P01" width="10" height="10" patternUnits="userSpaceOnUse">
    <rect width="10" height="10" fill="#FFFFFF" stroke="#000000" stroke-width="0.1"/>
</pattern>
</defs>
<rect x="0" y="0" width="400" height="400" fill="url(#P01)"/>

But no worry, you probably, will have all you need and much more in Silverlight 2.0 :)

Have a nice day.