Mostrando entradas con la etiqueta Windows Mobile. Mostrar todas las entradas
Mostrando entradas con la etiqueta Windows Mobile. Mostrar todas las entradas

Boot time comparison: All generations of iPhone vs Nokia Lumia 800

This video completes the boot time comparison made by iClarified with an additional contender: the Nokia Lumia 800 with Windows Phone 7.5, which beats even the very last iPhone 5 in terms of boot time.

 

Please note: This video is a second version of another one published 3 days ago. It has been remade to fix a small fps conversion error present in the previous version (the iPhone part was treated as if it was 30 fps, when it was 24 fps). That involved it being displayed faster than it should, and therefore showing a wrong boot time measurement for the Lumia (which was displayed correctly, at 30 fps). Nokia Lumia 800 boots in 18 seconds, not 22.

Results

The boot time results are awesome:

          • Nokia Lumia 800: 18.17 secs
          • iPhone 5: 24.88 secs (6.5 seconds slower !!)

I ♥ Nokia        -        I ♥ Windows Phone

Como agregar tus contactos de Outlook a Windows Phone 7, sin Exchange, sin aplicaciones ni cuentas de correo adicionales

Como ya sabréis, por el momento Windows Phone 7 no se sincroniza localmente con OutLook. Si no tenéis un servidor de correo compatible con Exchange (ese es el modo recomendado de sincronización para WP7), podéis realizar la sincronización con el dispositivo de varias formas, descritas en detalle aqui.

Companion Link ha sacado una aplicación que supuestamente realiza la sincronización, pero me parece un pufo, ya que necesita de una cuenta de correo de Google para funcionar. O sea, más de lo mismo, y encima te cobran 39 $ por la broma. Podéis descargar la versión trial aqui.

En fin, que a falta de que salga algo mejor, por ahora la mejor manera de añadir (que no sincronizar), tus contactos (solo tus contactos, ni tus citas, ni ná) a tu WP7 es utilizando uno de los métodos sugeridos en el enlace de arriba: a través de un fichero CSV.

Requiere tener un Windows Live ID (que no una cuenta de HotMail), pero mucha gente ya tiene uno, aunque solo sea para jugar a la XBox, así que no es una solución tan mala. Lo que haremos es subir nuestros contactos a la cuenta de Windows Live, con la que el Windows Phone sí se sincroniza.

1.- Preparar tus contactos

Como descubrirás más abajo, el proceso de importación de contactos de Windows Live es bastante puñetero. Falla por un montón de motivos, y algunas veces simplemente ni te dice por qué.

Por mi propia experiencia, para evitar que el proceso falle, revista en OutLook tus contactos, sobre todo los números de teléfono almacenados, ya que al parecer no pueden contener caracteres distintos de a-z A-Z y 0-9.

Así que elimina cualquier aparición de cosas como:

  • Espacios
  • Prefijos de países con formato +34 y similares. Substitúyelos por “0034”.

2.- Exportando tus contactos a un fichero CSV

Si tiene Outlook 2010

  1. Empiece por abrir Microsoft Outlook 2010 en el equipo.
  2. Haga clic en Archivo y, a continuación, en Opciones. Haga clic en Avanzadas y, en la sección Exportación, en Exportar.
  3. En el Asistente para importar y exportar, seleccione Exportar a un archivo y haga clic en Siguiente.
  4. Seleccione Valores separados por comas (Windows) y haga clic en Siguiente.
  5. Seleccione Contactos como la carpeta de origen de la exportación y haga clic en Siguiente.
  6. Elija una ubicación de archivo y un nombre de archivo, y haga clic en Siguiente.
  7. Haga clic en Finalizar. Los contactos deben haberse exportado como archivo CSV.
  8. Siga las instrucciones indicadas a continuación en Importar el archivo CSV de Outlook a Windows Live.

Si tiene Outlook 2007
  1. Abra Microsoft Outlook 2007 en el equipo.
  2. Haga clic en Archivo y, a continuación, en Importar y exportar.
  3. En el Asistente para importar y exportar, seleccione Exportar a un archivo y haga clic en Siguiente.
  4. Seleccione Valores separados por comas (Windows) y haga clic en Siguiente.
  5. Seleccione Contactos como la carpeta de origen de la exportación y haga clic en Siguiente.
  6. Elija una ubicación de archivo y un nombre de archivo, y haga clic en Siguiente.
  7. Haga clic en Finalizar. Los contactos deben haberse exportado como archivo CSV.
  8. Siga las instrucciones indicadas a continuación en Importar el archivo CSV de Outlook a Windows Live.

3.- Importando tus contactos en tu Windows Live

  • Importar el archivo CSV de Outlook a Windows Live
    1. Abra un explorador web, vaya a http://contacts.live.com (http://contacts.live.com) e inicie sesión en su cuenta de Windows Live.
    2. Haga clic en Administrar y, a continuación, en Importar.
    3. En la página "Agregar personas", haga clic en Outlook.
    4. Seleccione el botón de radio "Microsoft Outlook (usando CSV)".
    5. Vaya al archivo CSV que exportó a su equipo [pasos 1-7]. 
    6. Haga clic en Importar contactos. Si ya ha agregado la cuenta de Windows Live Hotmail al teléfono, ha terminado. Los contactos se sincronizarán automáticamente con el teléfono cuando inicie sesión en Windows Live desde el teléfono.
      Nota Windows Live tiene un límite de tamaño para carga de archivos CSV de 500 KB. Si su archivo CSV supera los 500 KB, no se cargará y se mostrará el siguiente error: 

      El archivo que deseas importar es demasiado grande. Elimina algunos contactos e intenta importarlo de nuevo.

      Para solucionar este problema, abra el archivo CSV en Excel y divídalo en varios archivos. De esta forma podrá cargar los archivos en Windows Live siempre que el tamaño total de cada archivo no supere el límite de 500 KB.
      Nota Windows Live tiene un límite de almacenamiento de 6500 contactos por usuario.

  • Si no ha agregado la cuenta de Windows Live Hotmail al teléfono, siga estos pasos:
    1. En Inicio, vaya a la izquierda en la lista Aplicación, puntee Configuración y, a continuación, Correo electrónico y cuentas.
    2. Puntee Agregar una cuenta y, a continuación, Windows Live.
    3. Escriba la dirección de correo electrónico y la contraseña, y puntee Iniciar sesión.
    4. Una vez iniciada la sesión, los contactos de Windows Live Hotmail se sincronizarán con el teléfono.

Ultimo consejo

Es muy probable que a pesar de las precauciones del punto 1, el proceso te falle en algún punto. Que sepas que Windows Live habrá importado todos los contactos que haya podido hasta que se haya producido el fallo, así que te recomiendo ir a revisar tus contactos, y mirar cual es el último que se añadió.

Una vez sepas cual es, abre el fichero CSV. Te recomiendo hacerlo con WordPad –desactivando el ajuste de línea-, ya que si lo salvas con Excel le cambiará el formato o la distribución de caracteres y no podrás volver a utilizarlo para importar (simplemente te dirá que el fichero está vacío).

Una vez lo tengas en WordPad, borra todas las líneas de los contactos ya agregados, y ve al contacto siguiente al último que se agregó. En él, busca algún carácter extraño que pudiera haber producido el error (si no encuentras nada raro, simplemente borra la línea de ese contacto). Salva el fichero, y vuelve a repetir el proceso.

Así sucesivamente hasta que completes la importación.

Es un rollo, lo sé, pero al menos te permitirá tener todos tus contactos en el móvil.

Creating shortcuts to .Exe files in Windows Mobile 6.5

Many people asks how to do this exactly, when you have an exe file, not an installed application (through .CAB or whatever), and you want to have it in the Programs menu, to be able to add as shortcuts, widgets, etc.

It´s easy:

1.- Open Windows Explorer and go to the folder where the EXE file is

2.- Select the file and and click on “copy” it

3.- Click on Menu->Edit->Paste as shortcut. This will create a shortcut to your exe file

4.- Select the shortcut and “cut” it

5.- Go to “YourDevice\Windows\Start Menu\Programs” and paste the shortcut there.

Now, your exe file will be available through the “Programs” menu option, so it will be visible for any "skin” or “today” application you have installed.

Cheers!

Best video player for Windows Mobile PocketPC

After testing CorePlayer and some others, I have to say that I moved back to TCPMP again. CorePlayer is great, and it´s greatly optimized for handheld devices, but lacks AC3 audio support.

TCPMP on the other hand, although it has been deprecated, perfectly supports AC3 and many other formats, and is still the best player for WM devices.

There is a recomp version specifically compiled for Windows Mobile 6.1 that works flawlessly, and includes most of the plugins available.

You can download from here:

http://www.htcmania.com/showthread.php?t=51241

Don´t worry, it´s free.

Oriented Button in Windows Forms

imageThe following class is a button which can be oriented both horizontally and vertically (like in the picture of your left). Text and image react properly to this orientation and so do their Alignments. The control also includes customizable margins for the text and image inside the button and a SizePercent property for the Image. Please keep in mind that if Orientation is set to “Horizontal”, the normal Draw methods from the base class are called, so all of this properties are ignored. However, you can change this behavior or add any other property very easily if you need it.
The whole thing has been designed to use as less resources as possible (accept suggestions on this of course ;), but you can very easily add other features, like a PictureBox for the image rendering (re-using all the PictureBox features as: BorderStyle, SizeMode, etc).
You can just copy-paste the following parts of code into a class which inherits from Button, and you´ll have it. Something like this:
public class OrientedButton : Button
Hope it helps:

Declaration of variables and props

        private Orientation mOrientation = Orientation.Horizontal;
        private int mTextMargin = 5;
        private int mImageMargin = 5;
        private int mImageScalingPercent = 100;
        private System.Windows.Forms.VisualStyles.PushButtonState mState = System.Windows.Forms.VisualStyles.PushButtonState.Normal;
 
        #region Props
        [Category("Appearance")]
        [DefaultValue(5)]
        public int TextMargin
        {
            get { return mTextMargin; }
            set { mTextMargin = value; }
        }
        [Category("Appearance")]
        [DefaultValue(5)]
        public int ImageMargin
        {
            get { return mImageMargin; }
            set { mImageMargin = value; }
        }    
        [Category("Appearance")]
        [DefaultValue(Orientation.Horizontal)]
        public Orientation Orientation
        {
            get { return mOrientation; }
            set { mOrientation = value; }
        }
        [Category("Appearance")]
        [DefaultValue(100)]      
        public int ImageScalingPercent
        {
            get { return mImageScalingPercent; }
            set { mImageScalingPercent = value; }
        }
        #endregion

Mouse Events Handling

       #region Mouse Events
        /// <summary>
        ///
        /// </summary>
        /// <param name="mevent"></param>
        protected override void OnMouseDown(MouseEventArgs mevent)
        {
            base.OnMouseDown(mevent);
            mState = System.Windows.Forms.VisualStyles.PushButtonState.Pressed;
            Invalidate();
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="mevent"></param>
        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            base.OnMouseUp(mevent);
            mState = System.Windows.Forms.VisualStyles.PushButtonState.Hot;
            Invalidate();
        }       
        /// <summary>
        ///
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            mState = System.Windows.Forms.VisualStyles.PushButtonState.Normal;
            Invalidate();
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            mState = System.Windows.Forms.VisualStyles.PushButtonState.Hot;
            Invalidate();
        }
        #endregion

OnPaint Method

        /// <summary>
        /// Some code parts were taken from here: http://msdn.microsoft.com/es-es/library/f0ys5025.aspx
        /// </summary>
        /// <param name="pevent"></param>
        protected override void OnPaint(PaintEventArgs pevent)
        {
            base.OnPaint(pevent);
 
            if (mOrientation == Orientation.Horizontal)
                return;
 
            // Base Button Draw
            if (mState == System.Windows.Forms.VisualStyles.PushButtonState.Pressed)
            {
                // Set the background color to the parent if visual styles 
                // are disabled, because DrawParentBackground will only paint 
                // over the control background if visual styles are enabled.
                this.BackColor = Application.RenderWithVisualStyles ?
                    Color.Azure : this.Parent.BackColor;
 
                // If you comment out the call to DrawParentBackground,
                // the background of the control will still be visible
                // outside the pressed button, if visual styles are enabled.
                ButtonRenderer.DrawParentBackground(pevent.Graphics,
                    ClientRectangle, this);
                ButtonRenderer.DrawButton(pevent.Graphics, this.ClientRectangle,
                    "", this.Font, true, mState);
            }
            else
            {
                // Draw the bigger unpressed button image.
                ButtonRenderer.DrawButton(pevent.Graphics, ClientRectangle,
                    "", this.Font, false, mState);
            }
 
            // Draw Text
            if (this.Text != "")
                this.DrawText(pevent.Graphics);
 
            // Draw Image
            if (this.Image != null)
                this.DrawImage(pevent.Graphics);
        }

The DrawText method

        /// <summary>
        ///
        /// </summary>
        private void DrawText(System.Drawing.Graphics pGraphics)
        {
            // Calc size of text (la func devuelve el size horizontal)
            SizeF sizeOfText = pGraphics.MeasureString(this.Text, this.Font);
            float temp = sizeOfText.Width;
            sizeOfText.Width = sizeOfText.Height;
            sizeOfText.Height = temp;
 
            // Calc X coord of Text           
            float x = mTextMargin;
            switch (this.TextAlign)
            {
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.TopCenter:
                case ContentAlignment.BottomCenter:
                    x = (this.Width / 2) - (sizeOfText.Width / 2);
                    break;
                case ContentAlignment.MiddleRight:
                case ContentAlignment.BottomRight:
                case ContentAlignment.TopRight:
                    x = this.Width - mTextMargin - sizeOfText.Width;
                    break;
            }
 
            // Calc Y coord of Text
            float y = mTextMargin;
            switch (this.TextAlign)
            {
                case ContentAlignment.BottomCenter:
                case ContentAlignment.BottomLeft:
                case ContentAlignment.BottomRight:
                    y = this.Height - mTextMargin - sizeOfText.Height;
                    break;
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.MiddleLeft:
                case ContentAlignment.MiddleRight:
                    y = (this.Height / 2) - (sizeOfText.Height / 2);
                    break;
            }
 
            // Draw text
            System.Drawing.SolidBrush drawBrush = new System.Drawing.SolidBrush(this.ForeColor);
            System.Drawing.StringFormat drawFormat = new System.Drawing.StringFormat();
            drawFormat.FormatFlags = StringFormatFlags.DirectionVertical;
            pGraphics.DrawString(this.Text, this.Font, drawBrush, x, y, drawFormat);
            drawBrush.Dispose();
        }

The DrawImage Method

        /// <summary>
        ///
        /// </summary>
        /// <param name="pGraphics"></param>
        private void DrawImage(System.Drawing.Graphics pGraphics)
        {
            float imageScaling = (float)mImageScalingPercent / 100f;
            float finalWidth = (float)this.Image.Width * imageScaling;
            float finalHeight = (float)this.Image.Height * imageScaling;
            float halfFinalWidth = finalWidth / 2f;
            float halfFinalHeight = finalHeight / 2f;
 
            float x = mImageMargin;
            float y = mImageMargin;
            switch (this.ImageAlign)
            {
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.TopCenter:
                case ContentAlignment.BottomCenter:
                    x = (this.Width / 2f) - halfFinalWidth;
                    break;
                case ContentAlignment.MiddleRight:
                case ContentAlignment.BottomRight:
                case ContentAlignment.TopRight:
                    x = this.Width - mImageMargin - finalWidth;
                    break;
            }
            switch (this.ImageAlign)
            {
                case ContentAlignment.BottomCenter:
                case ContentAlignment.BottomLeft:
                case ContentAlignment.BottomRight:
                    y = this.Height - mImageMargin - finalHeight;
                    break;
                case ContentAlignment.MiddleCenter:
                case ContentAlignment.MiddleLeft:
                case ContentAlignment.MiddleRight:
                    y = (this.Height / 2f) - halfFinalHeight;
                    break;
            }
            System.Drawing.Drawing2D.Matrix rotMat = new System.Drawing.Drawing2D.Matrix();
            PointF rotationCenter = new PointF(x + halfFinalWidth, y + halfFinalHeight);           
            rotMat.RotateAt(90, rotationCenter);
            pGraphics.Transform = rotMat;
 
            System.Drawing.Rectangle destRect = new Rectangle((int)x, (int)y, (int)finalWidth, (int)finalHeight);
            System.Drawing.Rectangle srcRect = new Rectangle(0, 0, this.Image.Width, this.Image.Height);
            pGraphics.DrawImage(this.Image, destRect, srcRect, GraphicsUnit.Pixel);
        }

References

http://msdn.microsoft.com/es-es/library/f0ys5025.aspx

Detecting if a piece of code is running in Design Time

Sometimes, you will want to distinguish if a certain piece of your code is being executed at run-time or as a part of the Visual Studio Design-Time calls.

A very easy way of checking this is:

bool isDesignTime = (this.Site != null && this.Site.DesignMode == true);

Why to explain this?

This is something quite obvious, but some people ask in the forums why they are receiving an exception when trying to open the design view of a form, in Visual Studio. Those exceptions can be caused by many things, but the one explained here is one of the frequent reasons.

Use case

Imagine you have developed a custom UserControl class, which needs to do something everything it´s made visible. You will probably override the OnVisibleChanged event to perform that operation. Now, imagine that operation can only be done at runtime. For example, if you need in that operation some data to be loaded, data that won´t be available at Design-Time. Now, imagine that you insert that UserControl into one of your forms.

As you can probably imagine, each time you open that form in the Design View of VisualStudio, the overriden OnVisibleChanged event will be fired, and as that data is not available, you will receive an exception, ruining the initialization of the DesignView, and banning you from editing anything at design time in your form.

In such cases, using the above check will save you from this behavior. Just put that check in the OnVisibleChanged event, and use the mentioned data only if not in Design Time. Et voilá. You have design view operative again.

Cheers!

Cómo desactivar el molesto lector de SMS en modo conversación en tu Samsung Omnia

Desde que lo compré, estoy bastante contento con mi Samsung Omnia, aunque siempre me molestó algo que traía configurado de serie: el lector de SMS en modo conversación.

Lo que hace este modo es guardar relaciones entre SMS, de forma que el teléfono identifica (más o menos) conversaciones enteras. Así, cuando abres un SMS, no solo muestra éste, sino que muestra también los anteriores y sus posibles respuestas.

La idea no es mala, pero lo cierto es que en cuanto tu número de SMS crece un poquito, la cosa se ralentiza mucho. Y si ya de por sí el Omnia (o su relación con Windows Mobile) es lento (no entiendo cómo puede serlo con semejante pepino de procesador), con este modo abrir un SMS podía llegar a costar unos interminables 2 o 3 segundos. No obstante, he de reconocer que hasta ahora nunca había borrado mis SMS, y ya acumulaba más de 800 (entre enviados y recibidos).

En fin, a lo que vamos: cómo desactivar este modo, y leer los mensajes como toda la vida.

Aunque he encontrado más de un método (algunos de ellos editando el registro), parece ser que con algunos de ellos aparece algún efecto colateral, como la pérdida del aviso sonoro en la recepción de un SMS. Así que de entre los métodos encontrados, me he quedado con el siguiente (a mi me ha funcionado a la perfección).

  1. Descárgate la aplicación: SK Tools. Aunque es un magnífico producto que te recomiendo compres para mantener al día tu móvil, con la versión TRIAL te bastará para lo que vamos a hacer hoy. En esta página tienes los links de descarga. Escoge la opción para WM5 o WM6, en el formato que prefieras (Zip o CAB).
  2. Instálala en tu Omnia (te recomiendo resolución VGA) y lanzala
  3. Ve a la sección “Tune Up” en el menú principal
  4. Una vez allí, navega con las pestañas de la parte inferior, moviéndote hacia la derecha hasta que encuentres la opción llamada: PIM
  5. De entre todas las opciones, en la parte baja encontrarás una llamada: “Disable threaded conversation view (SMS)”
  6. Pulsa sobre ella para cambiar su valor (en la parte superior aparecerá un combo de selección). Pon el valor YES.
  7. Resetea tu Omnia

Et voilá, threaded conversation is off.

Writing a correct Main Loop for your application

Have you ever wondered how can Windows run more than one application at a time, even in a single-processor machine? The answer is easy. It doesn’t. The point is that it switches from one application to another so fast that you don´t notice the change, and it seems both applications are running in parallel.
To allow this, running Windows applications should not always be running.
It´d be a waste of resources to massively use the processor just to find out that nothing had to be done, don’t you think?. That´d be kind of a psychotic behavior. Windows has it´s protocols and procedures to avoid this, letting applications or threads enter idle states, even for a few milliseconds, and giving then priority to other, non-idling processes.
So, what would happen if your application never enters idle mode? It would bring down the multi-tasking capability of Windows, slowing down every other application than yours. That´s why I say that running applications should not always be running.
Under this point of view, applications can be divided into three groups:
  1. Psychotic applications that should be updated always, i.e. intense computing applications (not so frequent, nowadays)
  2. Applications that should be updated only as a response to some user interaction (most Windows Forms applications)
  3. Applications that sometimes need to be “always updated”, and sometimes not (like a video-game)
As you know, when an application is run, the Main method is invoked, and the O.S gives the application access to the processor and some memory. Apart from thread priority policies, application´s behavior will be one or another depending on what we do in this Main() method:

Case # 1. Compute, compute, compute

The Main method structure is simple: update as fast as you can, and consume as much processor as possible. The Main() method in pseudo-code:
            while (Application is Alive)
            {
                Compute()
            }
This is the typical behavior of old applications in non multi-tasking environments. They consume as much processing power as is available.

Case # 2. Don´t disturb unless absolutely necessary

What should be done here is easy: if events are pending, process them (DoEvents). If not, just relax and sleep, yielding processor to other threads or applications. The exact implementation of such a procedure can be more complex, as we should decide when to enter sleep modes and when not. Luckily, .Net does that for us. The C# implementation you should use is:
            System.Windows.Forms.Application.Run(mForm);
The Run() method takes care of all the things above mentioned (yielding and many other things), and it does it using the standard .Net procedures and protocols.

Case # 3: The mixed approach

Other situations need a mixed solution. For example, a Windows Forms application that sometimes needs to enter a “running” state, where everything has to be updated, like a Windows Forms-based video-game, or a 3D editor where you want to run an animation. Here, updates will be applied when the application is in Running state, but not when it´s not, saving this way CPU (and batteries, if running in a laptop).
So, we want to combine the efficiency of Case # 2, with the possibility of switching to Case # 1 when needed. The correct implementation for this, in C#, is:
       ...
            System.Windows.Forms.Application.Idle += new EventHandler(Application_Idle);
            System.Windows.Forms.Application.Run(mForm);
        }
        static void Application_Idle(object sender, EventArgs e)
        {
            if(Application.RunningState)
            {
                 while(ApplicationStillIdle)
                      Compute();
            }
        }
The Application_Idle event will be fired each time the application is about to enter in Idle state (where all the pending messages for the windows has been processed).
This way, interaction between our application and others (running at the same time) will be correct: when we decide it (activate running state), we will have all the computing power for ourselves, but when it´s not needed (RunningState is off), we will yield it.

How to check if application is still Idle

The Application_Idle event is fired only once, when the application is about to enter idle state. Here, we will have to update computations while it is still Idle, giving priority to Windows Messages if there are some. How to check if the application is still Idle? Easy, we can use a property like the following:
        /// <summary>Checks to see if the application is still idle</summary>
        private bool AppStillIdle
        {
            get
            {
                NativeMethods.Message msg;
                return !NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);
            }
        }

An extra option to make things even better

We have seen how to activate/deactivate the psychotic (processor consuming) behavior of an application, basing on a state variable, but sometimes it is interesting to also deactivate it when our application does not have the focus (it is not the active application in the O.S.).
Windows controls and forms have a “Focused” property, but that doesn’t help much in this case, as we want to check if the entire application has focus, not an specific form (the main form of the application will loose focus often, when we open a child window, for instance).
Then, how to check if our application is the active application in Windows? Unfortunately, it seems that there is no C# managed code to check that, but we can easily use DLLImport to invoke the “GetForegroundWindow” method, comparing its result to our main form handle:
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
 
public bool MyAppFocused
{
    get { return GetForegroundWindow() == this.Handle; }
}
This way, we can put an additional condition to the Compute method, deactivating it also when the application is not focused:
static void Application_Idle(object sender, EventArgs e)
{
   if(Application.RunningState && MyAppFocused)
   {
       while(ApplicationStillIdle)
            Compute();
   }
     }

What should not be done

Some people tend to write the following code when need the mixed solution mentioned:
while (mForm.Created)
{
      System.Windows.Forms.Application.DoEvents();
 
      if(Application.RunningState)
             Compute();
}

Though it works, this approach is not correct, as it doesn’t yield processor to other threads (your application won´t enter idle mode). Use the above Idle event approach instead.

Conclusion

Quality software use the processor when really need it. Adding a few extra lines of code, you software will better share resources with other applications, and will improve laptop or handheld device´s battery life.
Take Care!

My ListView won´t show groups! Why?

This is a well documented issue, but just in case it helps someone.

If your ListView doesn't show groups, ensure the following (starting with the most obvious, and ending with the probable cause):

  1. Ensure your ListView has, at least, one column
  2. Ensure you have created Groups correctly
  3. Properly assign a group to each Item, through their “Group” property
  4. Set listView.ShowGroups property = True
  5. Ensure you have called System.Windows.Forms.Application.EnableVisualStyles() method at the beginning of your application

ListView groups rely on VisualStyles of the application, what is only available on Windows XP systems and above. So, groups won´t work on anything below Windows XP.

Here, you can find some explanations, like the following:

“ListView groups are available only on Windows XP and Windows Server 2003 when your application calls the Application.EnableVisualStyles method. On earlier operating systems, any code relating to groups has no effect and the groups will not appear. As a result, any code that depends on the grouping feature might not work correctly.”

Cheers!

Collision detection in XNA

[This article continues the prelude about collision detection published here. It refreshes and completes the older Collision detection in XNA posts –parts I, II and III-, written a long time ago and which were demanded to be completed many times. Finally, here it is]

Simple Collision Detection

XNA includes simple intersection tests for shapes like: Bounding Spheres, AABB (Axis Aligned Bound Box), Planes, Rays, Rectangles, Frustums, etc, and any combination of them. And what is even more useful, 3D models already have bounding spheres for their parts.
Using those tests, almost any kind of game-like intersection can be achieved. You must remember that a Mesh-Whatever intersection is expensive (depending in the number of polygons, of course), and should be left for special cases in which a very high intersection accuracy is needed. So, it’s usually preferred to approximate a complex geometry by a bunch of spheres or boxes, than using the real triangles (see Part 1).
There´s a very good post at Sharky´s blog about XNA collisions, specially focused in approximating generic shapes with bounding spheres. You can find it here.

Accurate collision detectionDespacho_2_Low


As commented earlier, sometimes a more accurate intersection method is needed. For example, for lighting calculations (where tracing rays are the best and more usual approach to modeling lights –see pic on your right-), the Ray-Mesh intersection test seems to be the best option. In D3D, there´s a Mesh.Intersect method ready for you, that performs the desired intersection test, but in XNA, there´s not such a method, and we will have to do it on our own.
To do it, we will need a system-memory copy of the geometry. Unfortunately, meshes are usually created with the ReadOnly flag in XNA (to make their management fast), what won´t allow us to access their geometry at runtime. To do so, we´ll have to deal with Custom Content Processing.
Note: Here you will find and introduction to Custom Content Processing.

Implementing a Custom Content Processor for collision detection

The solution to the previous problem is to make a custom content processor that stores a copy of the geometry information at build time, where there´s still access to it. All the information needed will be stored in a new class we will name MeshData.
 public class MeshData
{
     public VertexPositionNormalTexture[] Vertices;
     public int[] Indices;
     public Vector3[] FaceNormals;
 
     public MeshData(VertexPositionNormalTexture[] Vertices, int[] Indices, Vector3[] pFaceNormals)
     {
         this.Vertices = Vertices;
         this.Indices = Indices;
         this.FaceNormals = pFaceNormals;
     }
}
 
You can put in here all the information you need. By the moment, it will be enough to store the vertices, indices and face normals.
When VisualStudio processes each model with our ContentProcessor, it will write the model´s data to an XNB file. When it finds a MeshData object, will search for a writer that is able to serialize it, so we have to write our custom ContentTypeWriter for the MeshData class:
[ContentTypeWriter]
public class ModelVertexDataWriter : ContentTypeWriter<MeshData>
{
    protected override void Write(ContentWriter output, MeshData value)
    {
        output.Write((int)value.Vertices.Length);
        for (int x = 0; x < value.Vertices.Length; x++)
        {
            output.Write(value.Vertices[x].Position);
            output.Write(value.Vertices[x].Normal);
            output.Write(value.Vertices[x].TextureCoordinate);
        }
 
        output.Write(value.Indices.Length);
        for (int x = 0; x < value.Indices.Length; x++)
            output.Write(value.Indices[x]);
 
        output.Write(value.FaceNormals.Length);
        for (int x = 0; x < value.FaceNormals.Length; x++)
            output.Write(value.FaceNormals[x]);
    }
 
    public override string GetRuntimeType(TargetPlatform targetPlatform)
    {
        return typeof(MeshData).AssemblyQualifiedName;
    }
    public override string GetRuntimeReader(TargetPlatform targetPlatform)
    {
        return "ContentProcessors.ModelVertexDataReader, ContentProcessors, Version=1.0.0.0, Culture=neutral";
    }
}
 
In a similar way, when the ContentPipeline tries to read back the XNB file, it will search for a deserializer for the type MeshData, so we have to write our own ContentTypeReader:
 public class ModelVertexDataReader : ContentTypeReader<MeshData>
{
     protected override MeshData Read(ContentReader input, MeshData existingInstance)
     {
         int i = input.ReadInt32();
         VertexPositionNormalTexture[] vb = new VertexPositionNormalTexture[i];
         for (int x = 0; x < i; x++)
         {
             vb[x].Position = input.ReadVector3();
             vb[x].Normal = input.ReadVector3();
             vb[x].TextureCoordinate = input.ReadVector2();
         }
 
         i = input.ReadInt32();
         int[] ib = new int[i];
         for (int x = 0; x < i; x++)
             ib[x] = input.ReadInt32();
 
         i = input.ReadInt32();
         Vector3[] normals = new Vector3[i];
         for (int x = 0; x < i; x++)
             normals[x] = input.ReadVector3();
 
         return new MeshData(vb, ib, normals);
     }
}
Finally, our Custom Content Processor that fills up the MeshData objects for each model that goes through it. Note: some parts taken from ZiggyWare
    [ContentProcessor(DisplayName = "Custom Mesh Processor")]
    public class PositionNormalTexture : ModelProcessor
    {
        public override ModelContent Process(NodeContent input, ContentProcessorContext context)
        {
            ModelContent model = base.Process(input, context);
            foreach (ModelMeshContent mesh in model.Meshes)
            {
                // Put the data in the tag.
                VertexPositionNormalTexture[] vb;
                MemoryStream ms = new MemoryStream(mesh.VertexBuffer.VertexData);
                BinaryReader reader = new BinaryReader(ms);
 
                VertexElement[] elems = mesh.MeshParts[0].GetVertexDeclaration();
                int num = mesh.VertexBuffer.VertexData.Length / VertexDeclaration.GetVertexStrideSize(elems, 0);
 
                vb = new VertexPositionNormalTexture[num];
                for (int i = 0; i < num; i++)
                {
                    foreach (VertexElement e in elems)
                    {
                        switch (e.VertexElementUsage)
                        {
                            case VertexElementUsage.Position:
                                vb[i].Position.X = reader.ReadSingle();
                                vb[i].Position.Y = reader.ReadSingle();
                                vb[i].Position.Z = reader.ReadSingle();
                                break;
                            case VertexElementUsage.Normal:
                                vb[i].Normal.X = reader.ReadSingle();
                                vb[i].Normal.Y = reader.ReadSingle();
                                vb[i].Normal.Z = reader.ReadSingle();
                                break;
                            case VertexElementUsage.TextureCoordinate:
                                if (e.UsageIndex != 0)
                                    continue;
                                vb[i].TextureCoordinate.X = reader.ReadSingle();
                                vb[i].TextureCoordinate.Y = reader.ReadSingle();
                                break;
                            default:
                                Console.WriteLine(e.VertexElementFormat.ToString());
                                switch (e.VertexElementFormat)
                                {
                                    case VertexElementFormat.Color:
                                        reader.ReadUInt32();
                                        break;
                                    case VertexElementFormat.Vector3:
                                        reader.ReadSingle();
                                        reader.ReadSingle();
                                        reader.ReadSingle();
                                        break;
                                    case VertexElementFormat.Vector2:
                                        reader.ReadSingle();
                                        reader.ReadSingle();
                                        break;
 
                                }
                                break;
                        }
                    }
                } // for i < num
 
                reader.Close();
 
                int[] ib = new int[mesh.IndexBuffer.Count];
                mesh.IndexBuffer.CopyTo(ib, 0);
                Vector3[] normals = new Vector3[mesh.IndexBuffer.Count / 3];
                for (int i = 0, conta = 0; i < mesh.IndexBuffer.Count; i += 3, conta++)
                {
                    Vector3 v0 = vb[mesh.IndexBuffer[i]].Position;
                    Vector3 v1 = vb[mesh.IndexBuffer[i + 1]].Position;
                    Vector3 v2 = vb[mesh.IndexBuffer[i + 2]].Position;
                    Vector3 edge1 = v1 - v0;
                    Vector3 edge2 = v2 - v0;
                    Vector3 normal = Vector3.Cross(edge1, edge2);
                    normal.Normalize();
                    normals[conta] = normal;
                }
 
                mesh.Tag = new MeshData(vb, ib, normals);
 
            } // foreach mesh
            return model;
        }
    }
Now that we have all the information needed, we will focus in the Collision Detection implementation itself.

Implementing the Ray-Mesh test using the MeshData

Many people thinks that the D3D Mesh.Intersect method does some kind of optimized "magic" to test for intersection, but in fact it just loops through all the triangles of the mesh doing a triangle-ray intersection test, and keeping track of the closest collision point (or all of them, depending on the overloaded version you use). Of course it applies some well known optimizations, like quick discarding polygons, back faces, and so on. That is exactly what we have to do now with the info generated at the Content Processor.
The following method performs a Ray-Mesh test getting as parameter a MeshData object generated by the previous content processor. Note that a lot of optimization can be done here, quick discarding triangles. Just google a bit for it.
public static bool RayMesh(Vector3 orig, Vector3 dir, MeshData pMesh, ref Vector3 pContactPoint, ref float pDist, ref int pFaceIdx)
{
       Vector3 maxContactPoint = Vector3.Zero;
       int maxFaceIdx = -1;
       float minT = float.MaxValue;
       for (int i = 0, countFace = 0; i < pMesh.Indices.Length; i += 3, countFace++)
       {
           int ia = pMesh.Indices[i];
           int ib = pMesh.Indices[i + 1];
           int ic = pMesh.Indices[i + 2];
           Vector3 v0 = pMesh.Vertices[ia].Position;
           Vector3 v1 = pMesh.Vertices[ib].Position;
           Vector3 v2 = pMesh.Vertices[ic].Position;
 
           double t = 0f;
           double u = 0f;
           double v = 0f;
           if (RayTriangle(orig, dir, v0, v1, v2, ref t, ref u, ref v))
           {
               Vector3 appPoint = orig + (dir * (float)t);
               if (t < minT)
               {
                   minT = (float)t;
                   maxFaceIdx = countFace;
                   maxContactPoint = appPoint;
               }
           }
       }
       pContactPoint = maxContactPoint;
       pFaceIdx = maxFaceIdx;
       pDist = minT;
       return (minT < float.MaxValue);
}
The only part left is the Ray-Triangle intersection test, but there is so much information around the net about this issue that I´ll just leave it for you. However, you can check the following links:
http://www.devmaster.net/wiki/Ray-triangle_intersection
http://www.graphics.cornell.edu/pubs/1997/MT97.html
http://www.graphics.cornell.edu/pubs/1997/MT97.pdf
http://www.acm.org/pubs/tog/editors/erich/ptinpoly/
Hope with 4 references is enough, and that you liked the post.
Enjoy!