6
\$\begingroup\$

I am capturing a window of my own choice, and taking a screenshot of it constantly in a loop. Latency and speed is everything.

It's very capable, but I hope it can be improved.

var proc = Process.GetProcessesByName(prcname)[0];
IntPtr hwnd = proc.MainWindowHandle;
RECT rc;  
NativeMethods.GetWindowRect(hwnd, out rc);
Bitmap bmp = new Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr hdcBitmap = gfxBmp.GetHdc();
NativeMethods.PrintWindow(hwnd, hdcBitmap, 0);
gfxBmp.ReleaseHdc(hdcBitmap);
gfxBmp.Dispose();
MemoryStream ms = new MemoryStream();
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);

return new MemoryStream(Lz4.CompressBytes(ms.GetBuffer()));

I will set a name prcname which will be the name of a process, for example, Internet Explorer. It will then hook on to that and save it as a bitmap and then .bmp (or other).

I then return the memory stream , and then I can do what I want with it (lz4 is used here to compress, which is very fast and lossless so it works pretty well).

Here are the Imports used:

[DllImport("user32.dll")]
internal static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
internal static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, int nFlags);

Then there is the RECT class, which is enormous, and I did not write it. I took it and reused this code for my own purposes, but RECT has been untouched, as I don't feel safe messing around with it.

Now, is there a way to improve the speed? Preferably I would like to improve the latency, meaning the frame it lags behind.

I am willing to try something else if user32 is not enough for this, so I'm open for suggestions and examples on that.

Can this code be improved?

NetSerializer.Serializer.Serialize(tcpcap.GetStream(), PrintWindow(process));
PrintWindow(process).Dispose();


panel1.BackgroundImage = Image.FromStream(new Lz4DecompressionStream((MemoryStream)NetSerializer.Serializer.Deserialize(tt1.GetStream())));
\$\endgroup\$
5
\$\begingroup\$

Well, yes, you're holding on to a bunch of IDisposable objects which should be dealt with by employing the using statement:

IntPtr hwnd;

using (var proc = Process.GetProcessesByName(prcname)[0])
{
    hwnd = proc.MainWindowHandle;
}

RECT rc;
NativeMethods.GetWindowRect(hwnd, out rc);
using (Bitmap bmp = new Bitmap(rc.Width, rc.Height, System.Drawing.Imaging.PixelFormat.Format32bppPArgb))
{
    using (Graphics gfxBmp = Graphics.FromImage(bmp))
    {
        IntPtr hdcBitmap = gfxBmp.GetHdc();
        try
        {
            NativeMethods.PrintWindow(hwnd, hdcBitmap, 0);
        }
        finally
        {
            gfxBmp.ReleaseHdc(hdcBitmap);
        }
    }

    using (MemoryStream ms = new MemoryStream())
    {
        bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
        return new MemoryStream(Lz4.CompressBytes(ms.GetBuffer()));
    }
}

Plus, the MemoryStream you return should be Dispose()'d be the calling code.

\$\endgroup\$
5
  • \$\begingroup\$ Not quite familiar what´s going on there. Why will "Using" be faster then just using variables around the place? (New to this). And how can i dispose the last memory stream in the calling code? Thanks \$\endgroup\$
    – Zerowalker
    Aug 4 '13 at 19:49
  • \$\begingroup\$ I updated the code to show where i use it, tell me if it´s correct. \$\endgroup\$
    – Zerowalker
    Aug 4 '13 at 19:56
  • 2
    \$\begingroup\$ @Zerowalker My understanding is by using the using statements you are guaranteed even on failure (within the code block) that the Dispose method will be called thus releasing resources. \$\endgroup\$
    – dreza
    Aug 4 '13 at 20:28
  • \$\begingroup\$ Ah well that sounds good. I am a bit lacking when it comes to properly use and dispose. But i don´t get how i am supposed to dispose the Memory Stream i am using, as disposing it like i put above, didn´t do anything but slow it down. \$\endgroup\$
    – Zerowalker
    Aug 4 '13 at 20:43
  • \$\begingroup\$ @Zerowalker well, to be fair, I never claimed it would be faster :) You asked if the code could be improved and here's the improvement. However, using the using deterministic disposal pattern, you're probably relieving memory pressure. \$\endgroup\$ Aug 5 '13 at 0:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.