private void CaptureLoop()
        {
            IntPtr wnd;

            try
            {
                wnd = HearthstoneHelper.GetHearthstoneWindow();
            }
            catch (Exception ex)
            {
                Log.Error(ex);
                OnWindowLost();
                return;
            }

            // Verify window exists
            if (wnd == IntPtr.Zero)
            {
                OnWindowLost();
                return;
            }

            ScreenshotResource img = null;

            try
            {
                if (currentCaptureMethod == null)
                {
                    currentCaptureMethod = CaptureMethod;
                }

                if (preferredCaptureMethod != CaptureMethod)
                {
                    // user changed capture method in settings
                    currentCaptureMethod   = CaptureMethod;
                    preferredCaptureMethod = CaptureMethod;
                }

                if (dontUseDirectX && currentCaptureMethod.Value == CaptureMethod.DirectX)
                {
                    Log.Info("DirectX gave too much errors, switching to Wdm.");
                    currentCaptureMethod = CaptureMethod.Wdm;
                }

                switch (currentCaptureMethod)
                {
                case CaptureMethod.AutoDetect:
                    var detectedMethod = DetectCaptureMethod(wnd, out img);
                    if (detectedMethod == null)
                    {
                        OnWindowMinimized();
                        extraDelay = 200;     // small delay, just enough to not be noticable, but less cpu
                        Thread.Sleep(extraDelay);
                        return;
                    }
                    currentCaptureMethod = detectedMethod.Value;
                    break;

                case CaptureMethod.DirectX:
                    img = CaptureDirectX(wnd);
                    break;

                case CaptureMethod.Wdm:
                    img = CaptureWdm(wnd);
                    break;

                case CaptureMethod.BitBlt:
                    img = CaptureWdm(wnd, false, true);
                    break;
                }

                if (lastCaptureMethod != currentCaptureMethod.Value)
                {
                    Log.Debug("Capture method changed from {0} to {1}", lastCaptureMethod, currentCaptureMethod.Value);
                    // Do not detach hook, so we can quickly switch again
                    //if (lastCaptureMethod == CaptureMethod.DirectX)
                    //{
                    //    DettachHookFromProcess();
                    //}
                    lastCaptureMethod = currentCaptureMethod.Value;
                }

                if (img == null || img.Bitmap == null)
                {
                    TraceLog.Log("No image data found.");
                    OnWindowMinimized();
                    extraDelay = 200; // small delay, just enough to not be noticable, but less cpu
                    Thread.Sleep(extraDelay);
                    return;
                }

                if (CaptureMethod == CaptureMethod.AutoDetect)
                {
                    if (lastImageHeight > 0 && lastImageHeight != img.Bitmap.Height)
                    {
                        // reset capture method so we detect again on next run
                        Log.Debug("Auto-detect: Image resolution changed from {0} to {1}, reset auto-detect.", lastImageHeight, img.Bitmap.Height);
                        currentCaptureMethod = null;
                    }

                    lastImageHeight = img.Bitmap.Height;
                }

                extraDelay = 0;
                OnWindowFound();

                if (this.PublishCapturedWindow)
                {
                    // Log.Diag("Window captured");
                    var bmpcpy = new Bitmap(img.Bitmap);
                    this.Publish(new WindowCaptured(bmpcpy), log: false);
                }

                var start = DateTime.Now.Ticks;

                try
                {
                    // scan areas, publish events;
                    foreach (var scanner in this.imageScanners)
                    {
                        scanner.Run(img.Bitmap, null);
                    }
                }
                finally
                {
                    try
                    {
                        if (img != null)
                        {
                            img.Dispose();
                        }
                    }
                    catch { }

                    var stop = DateTime.Now.Ticks;
                    var proc = TimeSpan.FromTicks(stop - start).Milliseconds;
                    TraceLog.Log("Scanner speed: {0}", proc);
                }
                // wait with passing next capture to scanner and signal scanner thread to process
                //this.captureWaitHandle.Wait();
                //this.captureWaitHandle.Reset();
                //if (this.currentImage != null)
                //{
                //    this.currentImage.Dispose();
                //    this.currentImage = null;
                //}
                //this.currentImage = img;
                //this.scannerWaitHandle.Set();
            }
            catch (ScreenshotCaptureException ex)
            {
                Log.Debug(ex.ToString());
                OnWindowLost();
                extraDelay = 2000;
                Thread.Sleep(extraDelay);
            }
            catch (Exception ex)
            {
                Log.Error(ex);
            }
        }