Ejemplo n.º 1
0
    def send_keys_to_input(
        self,
        keys_to_type: str,
        with_enter: bool = True,
        send_delay: float = 0.5,
        enter_delay: float = 1.5,
    ) -> None:
        """Send keys to windows and add ENTER if `with_enter` is True

        At the end of send_keys there is by default 1.0 second delay.
        At the end of ENTER there is by default 3.5 second delay.

        :param keys_to_type: keys to type into Windows
        :param with_enter: send ENTER if `with_enter` is True
        :param send_delay: delay after send_keys
        :param enter_delay: delay after ENTER
        """
        # Set keyboard layout for Windows platform
        if platform.system() == "Windows":
            win32api.LoadKeyboardLayout("00000409", 1)

        self.send_keys(keys_to_type)
        delay(send_delay)
        if with_enter:
            self.send_keys("{ENTER}")
            delay(enter_delay)
Ejemplo n.º 2
0
    def switch_to_application(self, app_id: int) -> None:
        """Switch to application by id.

        :param app_id: application's id
        :raises ValueError: if application is not found by given id
        """
        if app_id and app_id in self._apps.keys():
            app = self.get_app(app_id)
            self._active_app_instance = app_id
            self.app = app["app"]
            self.open_dialog(app["windowtitle"])
            delay(0.5)
            self.restore_dialog(app["windowtitle"])
        else:
            raise ValueError(f"No open application with id '{app_id}'")
Ejemplo n.º 3
0
    def mouse_click_coords(self,
                           x: int,
                           y: int,
                           ctype: str = "click",
                           delay_time: float = None) -> None:
        """Click at coordinates on desktop

        :param x: horizontal coordinate on the windows to click
        :param y: vertical coordinate on the windows to click
        :param ctype: click type "click", "right" or "double", defaults to "click"
        :param delay: delay in seconds after, default is no delay
        """
        self.click_type(x, y, ctype)
        if delay_time:
            delay(delay_time)
Ejemplo n.º 4
0
    def open_using_run_dialog(self, executable: str, windowtitle: str) -> int:
        """Open application using Windows run dialog.
        Window title name is required to get handle on the application.

        :param executable: name of the executable
        :param windowtitle: name of the window
        :return: application instance id
        """
        self.send_keys("{VK_LWIN down}r{VK_LWIN up}")
        delay(1)

        self.send_keys_to_input(executable)

        params = {"windowtitle": windowtitle, "executable": executable}
        return self._add_app_instance(params=params, dialog=True)
Ejemplo n.º 5
0
    def open_from_search(self, executable: str, windowtitle: str) -> int:
        """Open application using Windows search dialog.
        Window title name is required to get handle on the application.

        :param executable: name of the executable
        :param windowtitle: name of the window
        :return: application instance id
        """
        self.logger.info("Run from start menu: %s", executable)
        self.send_keys("{LWIN}")
        delay(1)

        self.send_keys_to_input(executable)

        params = {"windowtitle": windowtitle, "executable": executable}
        return self._add_app_instance(params=params, dialog=True)
Ejemplo n.º 6
0
    def get_window_elements(
        self,
        screenshot: bool = False,
        element_json: bool = False,
        outline: bool = False,
    ) -> Any:
        """Get element information about all window dialog controls
        and their descendants.

        :param screenshot: save element screenshot if True, defaults to False
        :param element_json: save element json if True, defaults to False
        :param outline: highlight elements if True, defaults to False
        :return: all controls and all elements
        """
        self.logger.debug("get window elements")
        # Create a list of this control and all its descendants
        all_ctrls = [self.dlg]
        if hasattr(self.dlg, "descendants"):
            all_ctrls += self.dlg.descendants()
        # self.logger.debug(type(self.dlg))
        # self.logger.debug(dir(self.dlg))
        all_elements = []
        for _, ctrl in enumerate(all_ctrls):
            if hasattr(ctrl, "element_info"):
                cleaned_filename = clean_filename(
                    f"locator_{self.windowtitle}_ctrl_{ctrl.element_info.name}"
                )
                if screenshot and len(ctrl.element_info.name) > 0:
                    self.screenshot(cleaned_filename, ctrl=ctrl)
                if outline:
                    ctrl.draw_outline(colour="red", thickness=4)
                    delay(0.2)
                    ctrl.draw_outline(colour=0x000000, thickness=4)
                element = self._parse_element_attributes(element=ctrl)
                if element_json:
                    write_element_info_as_json(element, cleaned_filename)
                all_elements.append(element)
        if element_json:
            write_element_info_as_json(
                all_elements,
                clean_filename(f"locator_{self.windowtitle}_all_elements"))
        # self.logger.info(self.dlg.print_control_identifiers())
        return all_ctrls, all_elements
Ejemplo n.º 7
0
    def drag_and_drop(
        self,
        src: Any,
        target: Any,
        src_locator: str,
        target_locator: str = None,
        handle_ctrl_key: bool = False,
        drop_delay: float = 2.0,
    ) -> None:
        """Drag elements from source and drop them on target.

        Please note that if CTRL is not pressed down during drag and drop then
        operation is MOVE operation, on CTRL down the operation is COPY operation.

        There will be also overwrite notification if dropping over existing files.

        :param src: application object or instance id
        :param target: application object or instance id
        :param ssrc_locator: elements to move
        :param target_locator: target element to drop source elements into
        :param handle_ctrl_key: True if keyword should press CTRL down dragging
        :param drop_delay: how many seconds to wait until releasing mouse drop,
            default 2.0
        :raises ValueError: on validation errors
        """
        if isinstance(src, int):
            src = self.get_app(src)
        if isinstance(target, int):
            target = self.get_app(target)

        selections, source_x, source_y = self._select_elements_for_drag(
            src, src_locator)
        target_x, target_y = self._validate_target(target, target_locator)

        self.logger.info(
            "Dragging %d elements from (%d,%d) to (%d,%d)",
            len(selections),
            source_x,
            source_y,
            target_x,
            target_y,
        )

        if handle_ctrl_key:
            self.send_keys("{VK_LCONTROL down}")
            delay(0.5)
        # Select elements by mouse clicking

        for idx, selection in enumerate(selections):
            self.logger.debug("Selecting item %d by mouse_click", idx)
            pywinauto.mouse.click(coords=(selection[0], selection[1]))

        # Start drag from the last item
        pywinauto.mouse.press(coords=(source_x, source_y))
        delay(1)
        pywinauto.mouse.move(coords=(target_x, target_y))

        self.logger.debug("Cursor position: %s", win32api.GetCursorPos())
        delay(drop_delay)
        pywinauto.mouse.click(coords=(target_x, target_y))
        pywinauto.mouse.release(coords=(target_x, target_y))

        if handle_ctrl_key:
            self.send_keys("{VK_LCONTROL up}")
            delay(0.5)
        # Deselect elements by mouse clicking
        for selection in selections:
            self.logger.debug("Deselecting item by mouse_click")
            self.mouse_click_coords(selection[0], selection[1])