Question

When during the constructor of a Form I touch specific properties (ie. the Width property), it immediately invokes OnActivated(). I only notice this behavior on my device running Windows Embedded 7 and the .NET 3.5 that comes with it.

Here's the code I use to reproduce the issue:

static class Program
{
    [MTAThread]
    static void Main()
    {
        new MyForm();
    }
}

public class MyForm : Form
{
    public MyForm()
    {
        Width = 100;
    }

    protected override void OnActivated(EventArgs e)
    {
        MessageBox.Show("Activated!");
    }
}

(Notice that I'm not Show()ing the form nor using Application.Run())

Running the above code on my desktop or WinCE 5 device does not show the MessageBox. On my Windows Embedded 7 device, the MessageBox appears, and after clicking "OK" it re-appears because OnActivated() is being invoked again.

The device manufacturer told me this is an OS specific issue, can anyone confirm that this is how Windows Embedded 7 should "treat his forms"?

Was it helpful?

Solution

I tried this on my Windows CE 5.0 device with .NET CF 3.5 to see if I experienced the same behavior as you. With the exact same code, I did not have OnActivated get called. Setting the Width did not cause OnActivated to be called even when Application.Run() was used instead. In fact, it appeared that the Form had to have been shown to allow Activate to fire because I tried calling Activate() explicitly.

So it appears to be something that Windows Embedded 7 does versus previous versions of Windows CE. I also tried to look into the CompactFramework .NET .dlls using Reflector, but I did not find any code in .NET that would Activate a Form when its width was changed. The Width is not a property of Form (it is a property of Control), and Form did not appear to handle the resize event in anyway that would allow it to call its Activate method.

I do have a suggestion for you as a possible workaround. The following code prevented Activate from occuring completely even when I explicitly called Activate();

Give this a try:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        DisableActivate();
        Activate(); // No call is made to OnActivated
        EnableActivate();
    }

    protected override void OnActivated(EventArgs e)
    {
        Debug.WriteLine("Activated");
    }

    private void DisableActivate()
    {
        WindowStyles style = GetWindowLong(Handle, GWL_EX_STYLE);
        style |= WindowStyles.WS_EX_NOACTIVATE;
        SetWindowLong(Handle, GWL_EX_STYLE, style);
    }

    private void EnableActivate()
    {
        WindowStyles style = GetWindowLong(Handle, GWL_EX_STYLE);
        style &= ~WindowStyles.WS_EX_NOACTIVATE;
        SetWindowLong(Handle, GWL_EX_STYLE, style);
    }

    public const int GWL_EX_STYLE = -20;

    [DllImport("coredll.dll", SetLastError = true)]
    public static extern WindowStyles GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("Coredll.dll", SetLastError = true)]
    public static extern int SetWindowLong(IntPtr hWnd, int nIndex, WindowStyles dwNewLong);

    [Flags]
    public enum WindowStyles : uint
    {
        WS_CHILD = 0x40000000,
        WS_VISIBLE = 0x10000000,
        WS_DISABLED = 0x08000000,
        WS_GROUP = 0x00020000,
        WS_TABSTOP = 0x00010000,
        WS_OVERLAPPED = WS_BORDER | WS_CAPTION,
        WS_CLIPSIBLINGS = 0x04000000,
        WS_CLIPCHILDREN = 0x02000000,
        WS_CAPTION = 0x00C00000,    /* WS_BORDER | WS_DLGFRAME  */
        WS_BORDER = 0x00800000,
        WS_DLGFRAME = 0x00400000,
        WS_VSCROLL = 0x00200000,
        WS_HSCROLL = 0x00100000,
        WS_SYSMENU = 0x00080000,
        WS_THICKFRAME = 0x00040000,
        WS_MAXIMIZEBOX = 0x00020000,
        WS_MINIMIZEBOX = 0x00010000,
        WS_SIZEBOX = WS_THICKFRAME,
        WS_POPUP = 0x80000000,
        WS_EX_NOACTIVATE = 0x08000000,
        WS_EX_DLGMODALFRAME = 0x00000001,
        WS_EX_TOPMOST = 0x00000008,
        WS_EX_TOOLWINDOW = 0x00000080,
        WS_EX_WINDOWEDGE = 0x00000100,
        WS_EX_CLIENTEDGE = 0x00000200,
        WS_EX_CONTEXTHELP = 0x00000400,
        WS_EX_RIGHT = 0x00001000,
        WS_EX_RTLREADING = 0x00002000,
        WS_EX_LEFTSCROLLBAR = 0x00004000,
        WS_EX_STATICEDGE = 0x00020000,
        WS_EX_NOINHERITLAYOUT = 0x00100000, // Disable inheritence of mirroring by children
        WS_EX_LAYOUTRTL = 0x00400000, // Right to left mirroring
        WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE),
        WS_EX_CAPTIONOKBTN = 0x80000000,
        WS_EX_NODRAG = 0x40000000,
        WS_EX_ABOVESTARTUP = 0x20000000,
        WS_EX_INK = 0x10000000,
        WS_EX_NOANIMATION = 0x04000000
    }
}

So basically, with your code do:

public MyForm()
{
    DisableActivate();
    Width = 100;
    EnableActivate();
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top