Example #1
0
        private MediaAndCoreWindows GetMediaAndCoreWindowsInternal(JwLibAppTypes appType, string caption)
        {
            var candidates = _cachedDesktopElement.FindAll(
                TreeScope.Children,
                new PropertyCondition(AutomationElement.NameProperty, caption));

            if (candidates.Count == 0)
            {
                return(null);
            }

            foreach (AutomationElement candidate in candidates)
            {
                if (IsWindowTopMost(candidate))
                {
                    var coreWindow = GetJwlCoreWindow(candidate, caption);
                    if (coreWindow != null)
                    {
                        if (IsCorrectCoreWindow(appType, coreWindow))
                        {
                            return(new MediaAndCoreWindows
                            {
                                CoreWindow = coreWindow,
                                MediaWindow = candidate
                            });
                        }
                    }
                }
            }

            return(null);
        }
Example #2
0
        private FindWindowResult GetMediaAndCoreWindow(
            JwLibAppTypes appType, string processName, string caption)
        {
            var result = new FindWindowResult();

            if (!Process.GetProcessesByName(processName).Any())
            {
                return(result);
            }

            result.JwlRunning = true;

            CacheDesktopElement();
            if (_cachedDesktopElement == null)
            {
                return(result);
            }

            result.FoundDesktop = true;

            if (_cachedWindowElements == null)
            {
                _cachedWindowElements = GetMediaAndCoreWindowsInternal(appType, caption);
            }

            if (_cachedWindowElements != null)
            {
                result.FoundMediaWindow = true;

                result.CoreMediaWindow = _cachedWindowElements.CoreWindow;
                result.MainMediaWindow = _cachedWindowElements.MediaWindow;

                try
                {
                    // note that the transform property is not available in
                    // the original window; only in one that has been "fixed"
                    if (HasTransformPattern(_cachedWindowElements.MediaWindow))
                    {
                        // already fixed
                        result.IsAlreadyFixed = true;
                    }
                }
                catch (ElementNotAvailableException)
                {
                    // one of the windows has gone away so purge the cache...
                    _cachedWindowElements = null;
                    _cachedDesktopElement = null;

                    return(new FindWindowResult
                    {
                        FoundDesktop = true,
                        JwlRunning = true
                    });
                }
            }

            return(result);
        }
Example #3
0
        private static bool IsCorrectCoreWindow(JwLibAppTypes appType, AutomationElement coreMediaWindow)
        {
            switch (appType)
            {
            default:
            // ReSharper disable once RedundantCaseLabel
            case JwLibAppTypes.None:
                return(false);

            case JwLibAppTypes.JwLibrary:
                return(GetWebView(coreMediaWindow) != null);

            case JwLibAppTypes.JwLibrarySignLanguage:
                return(GetImageControl(coreMediaWindow) != null);
            }
        }
Example #4
0
        /// <summary>
        /// Executes the "fixer". Finds the JWL media window and fixes it.
        /// </summary>
        /// <param name="appType">JWL application type.</param>
        /// <param name="topMost">Whether the media window should always be on top.</param>
        /// <returns><see cref="FixerStatus"/></returns>
        /// <exception cref="Exception">Expected app type!</exception>
        // ReSharper disable once UnusedMember.Global
        public FixerStatus Execute(JwLibAppTypes appType, bool topMost)
        {
            try
            {
                string processName;
                string caption;

                switch (appType)
                {
                case JwLibAppTypes.None:
                    throw new Exception("Expected app type!");

                default:
                // ReSharper disable once RedundantCaseLabel
                case JwLibAppTypes.JwLibrary:
                    processName = JwLibProcessName;
                    caption     = JwLibCaption;
                    break;

                case JwLibAppTypes.JwLibrarySignLanguage:
                    processName = JwLibSignLanguageProcessName;
                    caption     = JwLibSignLanguageCaption;
                    break;
                }

                return(ExecuteInternal(appType, topMost, processName, caption));
            }
            catch (ElementNotAvailableException)
            {
                return(new FixerStatus {
                    ErrorIsTransitioning = true
                });
            }
            catch (Exception)
            {
                return(new FixerStatus {
                    ErrorUnknown = true
                });
            }
        }
Example #5
0
        private FixerStatus ExecuteInternal(
            JwLibAppTypes appType,
            bool topMost,
            string processName,
            string caption)
        {
            var result = new FixerStatus {
                FindWindowResult = GetMediaAndCoreWindow(appType, processName, caption)
            };

            if (!result.FindWindowResult.FoundMediaWindow ||
                result.FindWindowResult.IsAlreadyFixed)
            {
                return(result);
            }

            var mainHandle = (IntPtr)result.FindWindowResult.MainMediaWindow.Current.NativeWindowHandle;
            var coreHandle = (IntPtr)result.FindWindowResult.CoreMediaWindow.Current.NativeWindowHandle;

            // this Sleep is probably not needed
            Thread.Sleep(1000);

            NativeMethods.SetForegroundWindow(coreHandle);

            var rect = result.FindWindowResult.MainMediaWindow.Current.BoundingRectangle;

            result.FindWindowResult.CoreMediaWindow.SetFocus();

            if (!result.FindWindowResult.CoreMediaWindow.Current.HasKeyboardFocus)
            {
                return(result);
            }

            result.CoreWindowFocused = true;

            // convert the window using Win+Shift+Return
            if (!ConvertMediaWindow(result.FindWindowResult.MainMediaWindow))
            {
                return(result);
            }

            var insertAfterValue = topMost
                ? new IntPtr(-1)
                : new IntPtr(0);

            const uint ShowWindowFlag     = 0x0040;
            const uint NoCopyBitsFlag     = 0x0100;
            const uint NoSendChangingFlag = 0x0400;

            // the window used to have a non-transparent titlebar so we could
            // just remove it by trimming the top margin...
            // const int adjustment = 34; // adjustment for titlebar
            // const int border = 8; // adjustment for borders

            // ... but in Jan 2021 the title bar became transparent and so
            // it needed to be retained. However, the command buttons top right
            // can be 'removed' (see below)
            const int adjustment = 1; // adjustment for titlebar
            const int border     = 8; // adjustment for borders

            // this Sleep is definitely required. Without it, the media window may remain
            // on the primary display (i.e. the SetWindowPos call is ineffective). See #5
            Thread.Sleep(500);

            NativeMethods.SetWindowPos(
                mainHandle,
                insertAfterValue,
                (int)rect.Left - border,
                (int)rect.Top - adjustment,
                (int)rect.Width + (border * 2),
                (int)rect.Height + adjustment + border,
                (int)(NoCopyBitsFlag | NoSendChangingFlag | ShowWindowFlag));

            result.IsFixed = true;

            EnsureWindowIsNonSizeable(mainHandle);

            // to 'remove' the command buttons from the transparent title bar
            // we move focus to the main JWL window and then disable the media
            // window meaning it can no longer gain focus via mouse click. This
            // doesn't prevent the button being displayed if you alt-tab to the
            // media window but it is a small change that is generally helpful.

            NativeMethods.SetForegroundWindow(coreHandle);
            NativeMethods.EnableWindow(mainHandle, false);

            return(result);
        }
Example #6
0
        private FixerStatus ExecuteInternal(
            JwLibAppTypes appType,
            bool topMost,
            string processName,
            string caption)
        {
            var result = new FixerStatus {
                FindWindowResult = GetMediaAndCoreWindow(appType, processName, caption)
            };

            if (!result.FindWindowResult.FoundMediaWindow ||
                result.FindWindowResult.IsAlreadyFixed)
            {
                return(result);
            }

            var mainHandle = (IntPtr)result.FindWindowResult.MainMediaWindow.Current.NativeWindowHandle;
            var coreHandle = (IntPtr)result.FindWindowResult.CoreMediaWindow.Current.NativeWindowHandle;

            // The Sleep is an attempt to fix #5 (where media window is shown on primary display).
            // My assumption is that the media window appears first on the same
            // display as JWL and is then moved to the secondary display, and the "rect = "
            // call below retrieves this initial position!
            Thread.Sleep(1000);

            NativeMethods.SetForegroundWindow(coreHandle);

            var rect = result.FindWindowResult.MainMediaWindow.Current.BoundingRectangle;

            result.FindWindowResult.CoreMediaWindow.SetFocus();

            if (!result.FindWindowResult.CoreMediaWindow.Current.HasKeyboardFocus)
            {
                return(result);
            }

            result.CoreWindowFocused = true;

            // convert the window using Win+Shift+Return
            if (!ConvertMediaWindow(result.FindWindowResult.MainMediaWindow))
            {
                return(result);
            }

            var insertAfterValue = topMost
                ? new IntPtr(-1)
                : new IntPtr(0);

            const uint ShowWindowFlag     = 0x0040;
            const uint NoCopyBitsFlag     = 0x0100;
            const uint NoSendChangingFlag = 0x0400;

            const int adjustment = 34;
            const int border     = 8;

            NativeMethods.SetWindowPos(
                mainHandle,
                insertAfterValue,
                (int)rect.Left - border,
                (int)rect.Top - adjustment,
                (int)rect.Width + (border * 2),
                (int)rect.Height + adjustment + border,
                (int)(NoCopyBitsFlag | NoSendChangingFlag | ShowWindowFlag));

            result.IsFixed = true;

            return(result);
        }
Example #7
0
        private FixerStatus ExecuteInternal(
            JwLibAppTypes appType,
            bool topMost,
            string processName,
            string caption)
        {
            var result = new FixerStatus {
                FindWindowResult = GetMediaAndCoreWindow(appType, processName, caption)
            };

            if (!result.FindWindowResult.FoundMediaWindow ||
                result.FindWindowResult.IsAlreadyFixed)
            {
                return(result);
            }

            var mainHandle = (IntPtr)result.FindWindowResult.MainMediaWindow.Current.NativeWindowHandle;
            var coreHandle = (IntPtr)result.FindWindowResult.CoreMediaWindow.Current.NativeWindowHandle;

            // this Sleep is probably not needed
            Thread.Sleep(1000);

            NativeMethods.SetForegroundWindow(coreHandle);

            var rect = result.FindWindowResult.MainMediaWindow.Current.BoundingRectangle;

            result.FindWindowResult.CoreMediaWindow.SetFocus();

            if (!result.FindWindowResult.CoreMediaWindow.Current.HasKeyboardFocus)
            {
                return(result);
            }

            result.CoreWindowFocused = true;

            // convert the window using Win+Shift+Return
            if (!ConvertMediaWindow(result.FindWindowResult.MainMediaWindow))
            {
                return(result);
            }

            var insertAfterValue = topMost
                ? new IntPtr(-1)
                : new IntPtr(0);

            const uint ShowWindowFlag     = 0x0040;
            const uint NoCopyBitsFlag     = 0x0100;
            const uint NoSendChangingFlag = 0x0400;

            const int adjustment = 34;
            const int border     = 8;

            // this Sleep is definitely required. Without it, the media window may remain
            // on the primary display (i.e. the SetWindowPos call is ineffective). See #5
            Thread.Sleep(500);

            NativeMethods.SetWindowPos(
                mainHandle,
                insertAfterValue,
                (int)rect.Left - border,
                (int)rect.Top - adjustment,
                (int)rect.Width + (border * 2),
                (int)rect.Height + adjustment + border,
                (int)(NoCopyBitsFlag | NoSendChangingFlag | ShowWindowFlag));

            result.IsFixed = true;

            return(result);
        }