tags:

views:

167

answers:

1

I am receiving this weird exception through automated crash reports, and I cannot figure out what causes it:

V2009.3.0.0 - System.NullReferenceException - :System.Drawing.Rectangle get_ImageRectangle():0
Version: MaxTo2009.3.0.0
Exception: System.NullReferenceException
Error message: Object reference not set to an instance of an object.
Stack trace: 
  at System.Windows.Forms.ToolStripMenuItemInternalLayout.get_ImageRectangle()
  at System.Windows.Forms.ToolStripMenuItem.OnPaint(PaintEventArgs e)
  at System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
  at System.Windows.Forms.ToolStrip.OnPaint(PaintEventArgs e)
  at System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
  at System.Windows.Forms.Control.WmPaint(Message& m)
  at System.Windows.Forms.Control.WndProc(Message& m)
  at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
  at System.Windows.Forms.ToolStrip.WndProc(Message& m)
  at System.Windows.Forms.ToolStripDropDown.WndProc(Message& m)
  at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
  at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
  at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

This seems to happen to a lot of people, but I cannot reproduce it. The clues I found on Google (basically just one post, which is in German, and I don't understand much of that) tells me this is related to the checked state of menu items. Since I haven't seen this error in earlier versions, and I've only changed one menu item in this version, this is likely to be the culprit:

private void toolStripMenuItemPassiveMode_CheckedChanged(object sender, EventArgs e)
{
    // Calls into an unmanaged DLL and uses PostMessage
    SetPassiveMode(toolStripMenuItemPassiveMode.Checked);
    String title;
    String text;
    if (toolStripMenuItemPassiveMode.Checked && !Settings.PassiveMode)
    {
        title = "Temporarily passive";
        text = "You have temporarily put MaxTo into passive mode. MaxTo will only intercept maximizations while you are holding the modifier key.\n\nIf you want passive mode to be the default, you have to set it in the options.";
        notifyIcon.ShowBalloonTip(10000, title, text, ToolTipIcon.Info);
    }
    else if (!toolStripMenuItemPassiveMode.Checked && Settings.PassiveMode)
    {
        title = "Temporarily active";
        text = "You have temporarily put MaxTo into active mode. MaxTo will now intercept all window maximizations.\n\nIf you want active mode to be the default, you have to set it in the options.";
        notifyIcon.ShowBalloonTip(10000, title, text, ToolTipIcon.Info);
    }
}

The menu item's Checked property is modified at two places throughout the code, yet nothing suspicious about them, as far as I can tell.

From .designer.cs:

this.toolStripMenuItemPassiveMode.CheckOnClick = true;
this.toolStripMenuItemPassiveMode.ImageScaling = System.Windows.Forms.ToolStripItemImageScaling.None;
this.toolStripMenuItemPassiveMode.Name = "toolStripMenuItemPassiveMode";
this.toolStripMenuItemPassiveMode.Size = new System.Drawing.Size(172, 28);
this.toolStripMenuItemPassiveMode.Text = "&Passive mode";
this.toolStripMenuItemPassiveMode.CheckedChanged += new System.EventHandler(this.toolStripMenuItemPassiveMode_CheckedChanged);
+1  A: 

Haivng looked at the framework code in reflector it might be that your Interop to the unmanaged dll is modifying the checked state while/before the OnPaint is happening. The CheckedImage property is used in get_ImageRectangle but returns null if the button is not checked. Normally I would imagine this wouldn't be a problem as the state of the item isn't changing mid-paint.

perhaps instead of passing toolStripMenuItemPassiveMode.Checked into your SetPassive() method read it into a method scope bool first and pass that in?

Short of actually messing about with the code myself this is just a semi-guess.

SeanG
The boolean is only read in the unmanaged DLL. I've done as you say, but since I cannot reproduce this, it is really hard to debug. I really cannot tell if this actually solves the problem.
Vegard Larsen