22

My code enumerates a metafile:

private void Parse()
{
    Graphics graphics = Graphics.FromHwnd(IntPtr.Zero);
    PointF pointf = new PointF();
    graphics.EnumerateMetafile(_metafile, pointf, ParseCallback);
}

private bool ParseCallback(EmfPlusRecordType recordType, 
    int flags, int dataSize, IntPtr data, PlayRecordCallback callbackData)
{
    // do stuff
}

My development machine is Windows 7 VirtualBox guest on Ubuntu host.

The code used to work fine. However, when I turned off Aero, the code stopped working: The ParseCallback would never be called.

Only when I turned Aero back on, ParseCallback was executed again.

Why and how can I make this code work on non-Aero-enabled machines?

Bharath theorare
  • 524
  • 7
  • 27
bovender
  • 1,838
  • 15
  • 31
  • That's a very obscure problem. You'll surely have to make that metafile available for anybody to have a shot at diagnosing the problem. – Hans Passant Jul 31 '14 at 12:41
  • The problem occurs with various EMF+ files. Here's one (a simple diagonal line): http://xltoolbox.sf.net/files/test.emf -- But you are right, the problem is obscure, and I've come to think that I'd rather implement my own metafile reader to enumerate the records. – bovender Aug 01 '14 at 10:03
  • I recommend adding graphics.Dispose() to the end of your Parse method, but I have doubts on it being the main issue. – Jason Ausborn Mar 05 '15 at 21:52
  • @Aron Nice! But in fact I made a deliberate decision not to enable Aero -- I dislike the Glass design. Plus, I guess I would have difficulties executing `pc.Install(GeForce.FromStore());` on a virtual machine ;-) – bovender Mar 18 '15 at 18:16
  • @bovender Surely you meant `pc.Install(nVidiaFactory.BuildLatestGfxCard());` – Aron Mar 19 '15 at 01:12
  • Have you tried under Windows 8 and/or 8.1? – Simon Mourier Mar 23 '15 at 20:57
  • @SimonMourier desktop composition/"Aero" **cannot be disabled** on Windows 8 and the method works just fine on my 8.1 machine. – cbr Mar 24 '15 at 15:59
  • @GrawCube - yep I know it cannot be disabled (some would say its always disabled, dead). The question was precisely whether it works or not. – Simon Mourier Mar 24 '15 at 18:20

1 Answers1

1

I don't have a full answer to the "why?" question, but it does not work because you're getting the Graphics GDI+ object from the Window handle. Instead, you want to get it from a GDI DC, like this:

private void Parse()
{
    IntPtr hdc = GetDC(IntPtr.Zero); // get entire screen dc
    Graphics graphics = Graphics.FromHdc(hdc));
    PointF pointf = new PointF();
    graphics.EnumerateMetafile(_metafile, pointf, ParseCallback);
    ReleaseDC(IntPtr.Zero, hdc);
}

[DllImport("user32.dll")]
static extern IntPtr GetDC(IntPtr hWnd);

[DllImport("user32.dll")]
static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);

Note you could also use the Graphics object from the Form OnPaint(PaintEventArgs e) method, it should also work, just like in the official sample code for EnumerateMetafile method here: Graphics.EnumerateMetafile Method

Simon Mourier
  • 132,049
  • 21
  • 248
  • 298