3

I'm supporting a winforms application using dotnet 3.5 and ComponentFactory Krypton v4.4.0.0, I recently implemented the AppDomain.CurrentDomain.UnhandledException and Application.ThreadException handlers to notify me of exceptions happening on the clients, and found lot of errors showing up in the logs. This one is doing my head in at the moment:

System.ArgumentException: Parameter is not valid.
 at System.Drawing.Font.GetHeight(Graphics graphics)
 at System.Drawing.Font.GetHeight()
 at System.Drawing.Font.get_Height()
 at System.Windows.Forms.Control.set_Font(Font value)
 at System.Windows.Forms.DataGridViewComboBoxEditingControl.ApplyCellStyleToEditingControl(DataGridViewCellStyledataGridViewCellStyle)
 at System.Windows.Forms.DataGridView.BeginEditInternal(Boolean selectAll)
 at System.Windows.Forms.DataGridView.ProcessKeyEventArgs(Message& m)
 at System.Windows.Forms.Control.ProcessKeyMessage(Message& m)
 at System.Windows.Forms.Control.WmKeyChar(Message& m)
 at System.Windows.Forms.Control.WndProc(Message& m)
 at System.Windows.Forms.DataGridView.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)

Note that the stacktrace is entirely in Windows code. There's another that passes through one of my classes:

System.ArgumentException: Parameter is not valid.
  at System.Drawing.Font.GetHeight(Graphics graphics)
  at System.Drawing.Font.GetHeight()
  at System.Drawing.Font.get_Height()
  at System.Windows.Forms.Control.set_Font(Font value)
  at MyOrg.MyApp.WindowsClient.GuiControls.MaskedTextBoxEditingControl.ApplyCellStyleToEditingControl(DataGridViewCellStyledataGridViewCellStyle)
  at System.Windows.Forms.DataGridView.BeginEditInternal(Boolean selectAll)
  at System.Windows.Forms.DataGridView.ProcessKeyEventArgs(Message& m)
  at System.Windows.Forms.Control.ProcessKeyMessage(Message& m)
  at System.Windows.Forms.Control.WmKeyChar(Message& m)
  at System.Windows.Forms.Control.WndProc(Message& m)
  at System.Windows.Forms.DataGridView.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)

Here's the code for that snippet:

public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
{
  this.Font = dataGridViewCellStyle.Font;
  this.ForeColor = dataGridViewCellStyle.ForeColor;
  this.BackColor = dataGridViewCellStyle.BackColor;
  this.TextAlign = translateAlignment(dataGridViewCellStyle.Alignment);
}

which doesn't tell me much.

The "System.ArgumentException: Parameter is not valid." error is pretty woeful and gives me very little to go on, but using dotPeek I looked at the code for Font.Get_Height(Graphics g) and discovered it's a GDI+ error, specifically GetFontHeight:

public float GetHeight(Graphics graphics)
{
  if (graphics == null)
  {
    throw new ArgumentNullException("graphics");
  }
  else
  {
    float size;
    int fontHeight = SafeNativeMethods.Gdip.GdipGetFontHeight(new HandleRef((object) this, this.NativeFont), new HandleRef((object) graphics, graphics.NativeGraphics), out size);
    if (fontHeight != 0)
      throw SafeNativeMethods.Gdip.StatusException(fontHeight);
    else
      return size;
  }
}

which is this GDI+ method: http://www.jose.it-berater.org/gdiplus/reference/flatapi/font/gdipgetfontheight.htm

and my status error is Invalidparameter, as documented here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms534175(v=vs.85).aspx

Unfortunately none of this helps me to resolve what's wrong with the Graphics object. This is coming from unhandled exceptions from users in the field. I recently had a memory leak that was caused by a leaking EventHandler and consuming all the available GDI handles, but I've fixed that, so now I'm not sure whether this is a memory leak, a GDI handle leak, or just bad config somewhere that's triggered by users doing something out of the ordinary.

anyone have any ideas? Help much appreciated!

matao
  • 636
  • 3
  • 14
  • 22

4 Answers4

7

I just ran into this very issue and took me a few hours to figure out, I traced it down to some other part of the codebase getting a reference to a Font from a control, but then performing a Dispose() on that Font. I was able to reproduce this by creating a Windows Form project, adding a TreeView and a DataGridView and executing this on the TreeView

treeView.Font.Dispose();

Hopefully, what I found is helpful for anyone running into this issue.

PeskyGnat
  • 2,454
  • 19
  • 22
  • thanks! I'm now going to go through my entire project and try to find any places where we're disposing of Fonts. hmm, no references outside the usual designer files (that I can find!), bugger :-/ – matao Aug 20 '14 at 05:38
  • where we using `Dispose()` function? – PurTahan Jul 11 '17 at 11:21
  • I can confirm that this issue was caused by my attempting to use a Font that had been previously disposed. In my case, it entailed setting the Font property of a ComboBox to a disposed font. – user3324937 Feb 15 '19 at 16:28
  • I had the same issue when I changed the font in a datagridview. I, unfortunately was disposing the font with using (Font font = new Font( "Microsoft Sans Serif", 9, FontStyle.Regular)) – Chris Patterson May 28 '19 at 00:56
2

I'm using Krypton 4.4 and .NET 4.0 and was experiencing the same behavior, but it dealt with the KryptonComboBox. Like matao, the error appeared to not be passing through my code at all, but rather through the Krypton framework and .NET itself.

After some investigation into the Krypton source code and looking at the stack trace when this error was thrown, I noticed that the KryptonComboBox (or a part of the Krypton framework) was attaching to the Microsoft.Win32.SystemEvents.OnUserPreferenceChanged event which got me thinking. Perhaps the reason this wasn't going through my code was that this event was being triggered from the OS at some point. It still didn't explain why the error was being thrown, but I started thinking about this problem in a different manner.

Now, whenever this error happened, it always traversed through the KryptonComboBox, but it wasn't consistent in any manner. It was actually very difficult to invoke. However, because of the OnUserPreferenceChanged event firing, I started looking at things like Global Policy changes or something that would trigger that event. Through some luck I noticed that if I had my WinForms app running and launched Internet Explorer, I could reliably get this exception to pop up. Don't ask me why this happens, but apparently launching IE somehow fires the OnUserPreferenceChanged event.

Now that I had a reliable way to trigger the exception, I started looking at KryptonComboBox instances in my code and commenting out entire modules to see if I could get this exception to come back. Eventually, I found the error and it turned out to be an error in how code in my WinForms app was being wired up. Specifically, here is the error:

    KryptonComboBox detailView = new KryptonComboBox();
    detailView.Sorted = true;
    detailView.Text = "View";
    detailView.Items.Add(new KryptonListItem("Details", "Detail View"));
    detailView.Items.Add(new KryptonListItem("List", "List"));
    detailView.Items.Add(new KryptonListItem("Tile", "Tiles"));

    ToolStripMenuItem mItem = new ToolStripMenuItem();
    mItem.Tag = detailView;
    mItem.Text = detailView.Text;
    mItem.Click += new EventHandler(contextItem_Click);

My guess is that because detailView is not wired up to the Control pipeline the, the Krypton framework has some issues attempting to update the Palette of the KryptonCombBox control.

One weird nuance that I noticed is that after the first exception was thrown within the Krypton framework, it appeared to corrupt the Graphics object. Subsequent calls to update the Palette (to switch colors of the Krypton controls), the error would always throw but through a different area in the call stack (always initiated from somewhere within my source code).

Matao, I'm not sure this answers your question, but I believe you may have some issue with how you're wiring up your Controls within the DataGridView. Perhaps you're associating a control with the Tag property on something within the DataGridView?

I hope this gives you some insight into your problem.

* Edit *

Per Matao's question, I fixed the problem by removing the code that was adding the KryptonComboBox to the Tag property of the ToolStripMenuItem. Instead, to get the functionality I wanted, I simply added some additional ToolStripMenuItems to the DropDownItems property of mItem.

I would look into your source code for any dynamically created controls that aren't being added to the Control pipeline.

bertoman
  • 46
  • 4
  • phew! I'd honestly given up on this one, thanks for your answer! I'm actually working on another project at the moment, but I'll mark your answer as accepted. Your theory sounds good, it's quite likely I made a mistake in my DataGridViews somewhere. what should I be looking for, Controls that I've created dynamically that may not be part of the Control pipeline? I have a TooStripMenuItem on one of my screens, but not the one that I usually see this error on. How did you fix the bug? – matao Feb 10 '14 at 00:41
  • 1
    "Controls that I've created dynamically that may not be part of the Control pipeline?"...Yes. I believe this was the main cause of my problem. – bertoman Feb 10 '14 at 13:48
1

For me it was because of the Dispose() of DefaultFont

-3

Do not dock DataGrid view to the parent layout