<commit_before># GUI Application automation and testing library
# Copyright (C) 2006 <NAME>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation; either version 2.1
# of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
#    Free Software Foundation, Inc.,
#    59 Temple Place,
#    Suite 330,
#    Boston, MA 02111-1307 USA

"Basic wrapping of Windows controls"

__revision__ = "$Revision$"

# pylint:  disable-msg=W0611

#from pprint import pprint

import time

import ctypes

# the wrappers may be used in an environment that does not need
# the actions - as such I don't want to require sendkeys - so
# the following makes the import optional.
try:
    import SendKeys
except ImportError:
    pass


# I leave this optional because PIL is a large dependency
try:
    import PIL.ImageGrab
except ImportError:
    pass

from pywinauto import win32defines
from pywinauto import win32functions
from pywinauto import win32structures

#from pywinauto import findbestmatch
from pywinauto import handleprops

# also import MenuItemNotEnabled so that it is
# accessible from HwndWrapper module
from menuwrapper import Menu, MenuItemNotEnabled

delay_after_click = 0.0 #5
delay_after_menuselect = 0#0.05
delay_after_sendkeys_key = .01
delay_after_button_click = 0#.1
delay_before_after_close_click = .2


#====================================================================
class ControlNotEnabled(RuntimeError):
    "Raised when a control is not enabled"
    pass

#====================================================================
class ControlNotVisible(RuntimeError):
    "Raised when a control is nto visible"
    pass



#====================================================================
class InvalidWindowHandle(RuntimeError):
    "Raised when an invalid handle is passed to HwndWrapper "
    def __init__(self, hwnd):
        "Initialise the RuntimError parent with the mesage"
        RuntimeError.__init__(self,
            "Handle 0x%d is not a vaild window handle"% hwnd)


#====================================================================
# just wrap the importing of WrapHandle - because it imports us
# and we import it - it can't be at the global level
def WrapHandle(hwnd):
    """Wrap a window handle

    * **hwnd** the handle of the window to wrap

    This is a simple wrapper around wraphandle.WrapHandle
    that we need to have due to import cross dependencies."""
    import wraphandle
    return wraphandle.WrapHandle(hwnd)

#
#    # Optimization - check if the control name matches exactly
#    # before trying a re.match
#    if class_name in _HwndWrappers:
#        return _HwndWrappers[class_name][1](hwnd)
#
#    for wrapper_name, (regex, class_) in _HwndWrappers.items():
#        if regex.match(class_name):
#            #print wrapper_name
#            return class_(hwnd)
#
#    # so it is not one of the 'known' classes - just wrap it with
#    # hwnd wrapper
#    wrapped_hwnd = HwndWrapper(hwnd)
#
#    # if it's not a dialog -
#    #if not isDialog:
#    #	wrapped_hwnd._NeedsImageProp = True
#
#    return wrapped_hwnd


#====================================================================
class HwndWrapper(object):
    """Default wrapper for controls.

    All other wrappers are derived from this.

    This class wraps a lot of functionality of underlying windows API
    features for working with windows.

    Most of the methods apply to every single window type. For example
    you can Click() on any window.

    Most of the methods of this class are simple wrappers around
    API calls and as such they try do the simplest thing possible.

    A HwndWrapper object can be passed directly to a ctypes wrapped
    C function - and it will get converted to a Long with the value of
    it's handle (see ctypes, _as_parameter_)"""

    friendlyclassname = ''
    handle = None

    #-----------------------------------------------------------
    def __init__(self, hwnd):
        """Initialize the control

        * **hwnd** is either a valid window handle or it can be an
          instance or subclass of HwndWrapper.

        If the handle is not valid then an InvalidWindowHandle error
        is raised.
        """
        # handle if hwnd is actually a HwndWrapper
        try:
            self.handle = hwnd.handle
        except AttributeError:
            self.handle = hwnd

        # verify that we have been passed in a valid windows handle
        if not win32functions.IsWindow(hwnd):
            raise InvalidWindowHandle(hwnd)

        # make it so that ctypes conversion happens correctly
        self._as_parameter_ = self.handle

        # specify whether we need to grab an image of ourselves
        # when asked for properties
        self._NeedsImageProp = False

        # default to not having a reference control added
        self.ref = None

        self.appdata = None

        # build the list of default properties to be written
        # Derived classes can either modify this list or override
        # GetProperties depending on how much control they need.
        self.writable_props = [
            'Class',
            'FriendlyClassName',
            'Texts',
            'Style',
            'ExStyle',
            'ControlID',
            'UserData',
            'ContextHelpID',
            'Fonts',
            'ClientRects',
            'Rectangle',
            'IsVisible',
            'IsUnicode',
            'IsEnabled',
            'MenuItems',
            'ControlCount',
            ]


    #-----------------------------------------------------------
    def FriendlyClassName(self):
        """Return the friendly class name for the control

        This differs from the class of the control in some cases.
        Class() is the actual 'Registered' window class of the control
        while FriendlyClassName() is hopefully something that will make
        more sense to the user.

        For example Checkboxes are implemented as Buttons - so the class
        of a CheckBox is "Button" - but the friendly class is "CheckBox"
        """
        if not self.friendlyclassname:
            return handleprops.classname(self)
        else:
            return self.friendlyclassname

    #-----------------------------------------------------------
    def Class(self):
        """Return the class name of the window"""
        return handleprops.classname(self)

    #-----------------------------------------------------------
    def WindowText(self):
        """Window text of the control

        Quite  a few contorls have other text that is visible, for example
        Edit controls usually have an empty string for WindowText but still
        have text displayed in the edit window.
        """
        return handleprops.text(self)

    #-----------------------------------------------------------
    def Style(self):
        """Returns the style of window

        Return value is a long.

        Combination of WS_* and specific control specific styles.
        See HwndWrapper.HasStyle() to easily check if the window has a
        particular style.
        """
        return handleprops.style(self)

    #-----------------------------------------------------------
    def ExStyle(self):
        """Returns the Extended style of window

        Return value is a long.

        Combination of WS_* and specific control specific styles.
        See HwndWrapper.HasStyle() to easily check if the window has a
        particular style.
        """
        return handleprops.exstyle(self)

    #-----------------------------------------------------------
    def ControlID(self):
        """Return the ID of the window

        Only controls have a valid ID - dialogs usually have no ID assigned.

        The ID usually identified the control in the window - but there can
        be duplicate ID's for example lables in a dialog may have duplicate
        ID's.
        """
        return handleprops.controlid(self)

    #-----------------------------------------------------------
    def UserData(self):
        """Extra data associted with the window

        This value is a long value that has been associated with the window
        and rarely has useful data (or at least data that you know the use
        of).
        """
        return handleprops.userdata(self)

    #-----------------------------------------------------------
    def ContextHelpID(self):
        "Return the Context Help ID of the window"
        return handleprops.contexthelpid(self)

    #-----------------------------------------------------------
    def IsUnicode(self):
        """Whether the window is unicode or not

        A window is Unicode if it was registered by the Wide char version
        of RegisterClass(Ex).
        """
        return handleprops.isunicode(self)


    #-----------------------------------------------------------
    def IsVisible(self):
        """Whether the window is visible or not

        Checks that both the Top Level Parent (probably dialog) that
        owns this window and the window itself are both visible.

        If you want to wait for a control to become visible (or wait
        for it to become hidden) use ``Application.Wait('visible')`` or
        ``Application.WaitNot('visible')``.

        If you want to raise an exception immediately if a window is
        not visible then you can use the HwndWrapper.VerifyVisible().
        HwndWrapper.VerifyActionable() raises if the window is not both
        visible and enabled.
        """

        return handleprops.isvisible(self.TopLevelParent()) and \
            handleprops.isvisible(self)

    #-----------------------------------------------------------
    def IsEnabled(self):
        """Whether the window is enabled or not

        Checks that both the Top Level Parent (probably dialog) that
        owns this window and the window itself are both enabled.

        If you want to wait for a control to become enabled (or wait
        for it to become disabled) use ``Application.Wait('visible')`` or
        ``Application.WaitNot('visible')``.

        If you want to raise an exception immediately if a window is
        not enabled then you can use the HwndWrapper.VerifyEnabled().
        HwndWrapper.VerifyReady() raises if the window is not both
        visible and enabled.
        """
        return handleprops.isenabled(self.TopLevelParent()) and \
            handleprops.isenabled(self)

    #-----------------------------------------------------------
    def Rectangle(self):
        """Return the rectangle of window

        The rectangle is the rectangle of the control on the screen,
        coordinates are given from the top left of the screen.

        This method returns a RECT structure, Which has attributes - top,
        left, right, bottom. and has methods width() and height().
        See win32structures.RECT for more information.
        """
        return handleprops.rectangle(self)

    #-----------------------------------------------------------
    def ClientRect(self):
        """Returns the client rectangle of window

        The client rectangle is the window rectangle minus any borders that
        are not available to the control for drawing.

        Both top and left are always 0 for this method.

        This method returns a RECT structure, Which has attributes - top,
        left, right, bottom. and has methods width() and height().
        See win32structures.RECT for more information.
        """
        return handleprops.clientrect(self)

    #-----------------------------------------------------------
    def Font(self):
        """Return the font of the window

        The font of the window is used to draw the text of that window.
        It is a structure which has attributes for Font name, height, width
        etc.

        See win32structures.LOGFONTW for more information.
        """
        return handleprops.font(self)

    #-----------------------------------------------------------
    def ProcessID(self):
        """Return the ID of process that owns this window"""
        return handleprops.processid(self)

    #-----------------------------------------------------------
    def HasStyle(self, style):
        "Return True if the control has the specified sytle"
        return handleprops.has_style(self, style)

    #-----------------------------------------------------------
    def HasExStyle(self, exstyle):
        "Return True if the control has the specified extended sytle"
        return handleprops.has_exstyle(self, exstyle)

    #-----------------------------------------------------------
    def IsDialog(self):
        "Return true if the control is a top level window"
        return handleprops.is_toplevel_window(self)

    #-----------------------------------------------------------
    def Parent(self):
        """Return the parent of this control

        Note that the parent of a control is not necesarily a dialog or
        other main window. A group box may be the parent of some radio
        buttons for example.

        To get the main (or top level) window then use
        HwndWrapper.TopLevelParent().
        """
        parent_hwnd = handleprops.parent(self)

        if parent_hwnd:
            return WrapHandle(parent_hwnd)
        else:
            return None

    #-----------------------------------------------------------
    def TopLevelParent(self):
        """Return the top level window of this control

        The TopLevel parent is different from the parent in that the Parent
        is the window that owns this window - but it may not be a dialog/main
        window. For example most Comboboxes have an Edit. The ComboBox is the
        parent of the Edit control.

        This will always return a valid window handle (if the control has
        no top level parent then the control itself is returned - as it is
        a top level window already!)
        """
        if self.IsDialog():
            return self

        parent = self.Parent()

        if not parent:
            return self

        if not parent.IsDialog():
            return parent.TopLevelParent()
        else:
            return parent

    #-----------------------------------------------------------
    def Texts(self):
        """Return the text for each item of this control"

        It is a list of strings for the control. It is frequently over-ridden
        to extract all strings from a control with multiple items.

        It is always a list with one or more strings:

          * First elemtent is the window text of the control
          * Subsequent elements contain the text of any items of the
            control (e.g. items in a listbox/combobox, tabs in a tabcontrol)
        """
        texts = [self.WindowText(), ]
        return texts

    #-----------------------------------------------------------
    def ClientRects(self):
        """Return the client rect for each item in this control

        It is a list of rectangles for the control. It is frequently over-ridden
        to extract all rectangles from a control with multiple items.

        It is always a list with one or more rectangles:

          * First elemtent is the client rectangle of the control
          * Subsequent elements contain the client rectangle of any items of
            the control (e.g. items in a listbox/combobox, tabs in a
            tabcontrol)
        """

        return [self.ClientRect(), ]

    #-----------------------------------------------------------
    def Fonts(self):
        """Return the font for each item in this control

        It is a list of fonts for the control. It is frequently over-ridden
        to extract all fonts from a control with multiple items.

        It is always a list with one or more fonts:

          * First elemtent is the control font
          * Subsequent elements contain the font of any items of
            the control (e.g. items in a listbox/combobox, tabs in a
            tabcontrol)
        """
        return [self.Font(), ]

    #-----------------------------------------------------------
    def Children(self):
        """Return the children of this control as a list

        It returns a list of HwndWrapper (or subclass) instances, it
        returns an empty list if there are no children.
        """

        child_windows = handleprops.children(self)
        return [WrapHandle(hwnd) for hwnd in child_windows]

    #-----------------------------------------------------------
    def ControlCount(self):
        "Return the number of children of this control"

        return len(handleprops.children(self))

    #-----------------------------------------------------------
    def IsChild(self, parent):
        """Return True if this window is a child of 'parent'.

        A window is a child of another window when it is a direct of the
        other window. A window is a direct descendant of a given
        window if the parent window is the the chain of parent windows
        for the child window.
        """

        # Call the IsChild API funciton and convert the result
        # to True/False
        return win32functions.IsChild(parent, self.handle) != 0

    #-----------------------------------------------------------
    def SendMessage(self, message, wparam = 0 , lparam = 0):
        "Send a message to the control and wait for it to return"
        return win32functions.SendMessage(self, message, wparam, lparam)

        #result = ctypes.c_long()
        #ret = win32functions.SendMessageTimeout(self, message, wparam, lparam,
        #    win32defines.SMTO_NORMAL, 400, ctypes.byref(result))

        #return result.value


    #-----------------------------------------------------------
    def SendMessageTimeout(
        self, message, wparam = 0 , lparam = 0, timeout = .001):
        """Send a message to the control and wait for it to return or to timeout

        If no timeout is given then a default timeout of .4 of a second will
        be used.
        """

        result = ctypes.c_long()
        win32functions.SendMessageTimeout(self, message, wparam, lparam,
            win32defines.SMTO_NORMAL, int(timeout * 1000), ctypes.byref(result))

        return result.value


    #-----------------------------------------------------------
    def PostMessage(self, message, wparam = 0 , lparam = 0):
        "Post a message to the control message queue and return"
        return win32functions.PostMessage(self, message, wparam, lparam)

        #result = ctypes.c_long()
        #ret = win32functions.SendMessageTimeout(self, message, wparam, lparam,
        #    win32defines.SMTO_NORMAL, 400, ctypes.byref(result))

        #return result.value


    #-----------------------------------------------------------
    def NotifyMenuSelect(self, menu_id):
        """Notify the dialog that one of it's menu items was selected

        **This method is Deprecated**
        """


        import warnings
        warning_msg = "HwndWrapper.NotifyMenuSelect() is deprecated - " \
            "equivalent functionality is being moved to the MenuWrapper class."
        warnings.warn(warning_msg, DeprecationWarning)


        self.SetFocus()

        msg = win32defines.WM_COMMAND
        return self.SendMessageTimeout(
            msg,
            win32functions.MakeLong(0, menu_id), #wparam
            )


    #-----------------------------------------------------------
    def NotifyParent(self, message):
        "Send the notification message to parent of this control"

        return self.Parent().PostMessage(
            win32defines.WM_COMMAND,
            win32functions.MakeLong(message, self.ControlID()),
            self)

    #-----------------------------------------------------------
    def GetProperties(self):
        "Return the properties of the control as a dictionary"
        props = {}
<commit_msg>Removed some extra spaces<commit_after># GUI Application automation and testing library
# Copyright (C) 2006 <NAME>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
# as published by the Free Software Foundation; either version 2.1
# of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
#    Free Software Foundation, Inc.,
#    59 Temple Place,
#    Suite 330,
#    Boston, MA 02111-1307 USA

"Basic wrapping of Windows controls"

__revision__ = "$Revision$"

# pylint:  disable-msg=W0611

#from pprint import pprint

import time

import ctypes

# the wrappers may be used in an environment that does not need
# the actions - as such I don't want to require sendkeys - so
# the following makes the import optional.
try:
    import SendKeys
except ImportError:
    pass


# I leave this optional because PIL is a large dependency
try:
    import PIL.ImageGrab
except ImportError:
    pass

from pywinauto import win32defines
from pywinauto import win32functions
from pywinauto import win32structures

#from pywinauto import findbestmatch
from pywinauto import handleprops

# also import MenuItemNotEnabled so that it is
# accessible from HwndWrapper module
from menuwrapper import Menu, MenuItemNotEnabled

delay_after_click = 0.0 #5
delay_after_menuselect = 0#0.05
delay_after_sendkeys_key = .01
delay_after_button_click = 0#.1
delay_before_after_close_click = .2


#====================================================================
class ControlNotEnabled(RuntimeError):
    "Raised when a control is not enabled"
    pass

#====================================================================
class ControlNotVisible(RuntimeError):
    "Raised when a control is nto visible"
    pass



#====================================================================
class InvalidWindowHandle(RuntimeError):
    "Raised when an invalid handle is passed to HwndWrapper "
    def __init__(self, hwnd):
        "Initialise the RuntimError parent with the mesage"
        RuntimeError.__init__(self,
            "Handle 0x%d is not a vaild window handle"% hwnd)


#====================================================================
# just wrap the importing of WrapHandle - because it imports us
# and we import it - it can't be at the global level
def WrapHandle(hwnd):
    """Wrap a window handle

    * **hwnd** the handle of the window to wrap

    This is a simple wrapper around wraphandle.WrapHandle
    that we need to have due to import cross dependencies."""
    import wraphandle
    return wraphandle.WrapHandle(hwnd)

#
#    # Optimization - check if the control name matches exactly
#    # before trying a re.match
#    if class_name in _HwndWrappers:
#        return _HwndWrappers[class_name][1](hwnd)
#
#    for wrapper_name, (regex, class_) in _HwndWrappers.items():
#        if regex.match(class_name):
#            #print wrapper_name
#            return class_(hwnd)
#
#    # so it is not one of the 'known' classes - just wrap it with
#    # hwnd wrapper
#    wrapped_hwnd = HwndWrapper(hwnd)
#
#    # if it's not a dialog -
#    #if not isDialog:
#    #	wrapped_hwnd._NeedsImageProp = True
#
#    return wrapped_hwnd


#====================================================================
class HwndWrapper(object):
    """Default wrapper for controls.

    All other wrappers are derived from this.

    This class wraps a lot of functionality of underlying windows API
    features for working with windows.

    Most of the methods apply to every single window type. For example
    you can Click() on any window.

    Most of the methods of this class are simple wrappers around
    API calls and as such they try do the simplest thing possible.

    A HwndWrapper object can be passed directly to a ctypes wrapped
    C function - and it will get converted to a Long with the value of
    it's handle (see ctypes, _as_parameter_)"""

    friendlyclassname = ''
    handle = None

    #-----------------------------------------------------------
    def __init__(self, hwnd):
        """Initialize the control

        * **hwnd** is either a valid window handle or it can be an
          instance or subclass of HwndWrapper.

        If the handle is not valid then an InvalidWindowHandle error
        is raised.
        """
        # handle if hwnd is actually a HwndWrapper
        try:
            self.handle = hwnd.handle
        except AttributeError:
            self.handle = hwnd

        # verify that we have been passed in a valid windows handle
        if not win32functions.IsWindow(hwnd):
            raise InvalidWindowHandle(hwnd)

        # make it so that ctypes conversion happens correctly
        self._as_parameter_ = self.handle

        # specify whether we need to grab an image of ourselves
        # when asked for properties
        self._NeedsImageProp = False

        # default to not having a reference control added
        self.ref = None

        self.appdata = None

        # build the list of default properties to be written
        # Derived classes can either modify this list or override
        # GetProperties depending on how much control they need.
        self.writable_props = [
            'Class',
            'FriendlyClassName',
            'Texts',
            'Style',
            'ExStyle',
            'ControlID',
            'UserData',
            'ContextHelpID',
            'Fonts',
            'ClientRects',
            'Rectangle',
            'IsVisible',
            'IsUnicode',
            'IsEnabled',
            'MenuItems',
            'ControlCount',
            ]


    #-----------------------------------------------------------
    def FriendlyClassName(self):
        """Return the friendly class name for the control

        This differs from the class of the control in some cases.
        Class() is the actual 'Registered' window class of the control
        while FriendlyClassName() is hopefully something that will make
        more sense to the user.

        For example Checkboxes are implemented as Buttons - so the class
        of a CheckBox is "Button" - but the friendly class is "CheckBox"
        """
        if not self.friendlyclassname:
            return handleprops.classname(self)
        else:
            return self.friendlyclassname

    #-----------------------------------------------------------
    def Class(self):
        """Return the class name of the window"""
        return handleprops.classname(self)

    #-----------------------------------------------------------
    def WindowText(self):
        """Window text of the control

        Quite  a few contorls have other text that is visible, for example
        Edit controls usually have an empty string for WindowText but still
        have text displayed in the edit window.
        """
        return handleprops.text(self)

    #-----------------------------------------------------------
    def Style(self):
        """Returns the style of window

        Return value is a long.

        Combination of WS_* and specific control specific styles.
        See HwndWrapper.HasStyle() to easily check if the window has a
        particular style.
        """
        return handleprops.style(self)

    #-----------------------------------------------------------
    def ExStyle(self):
        """Returns the Extended style of window

        Return value is a long.

        Combination of WS_* and specific control specific styles.
        See HwndWrapper.HasStyle() to easily check if the window has a
        particular style.
        """
        return handleprops.exstyle(self)

    #-----------------------------------------------------------
    def ControlID(self):
        """Return the ID of the window

        Only controls have a valid ID - dialogs usually have no ID assigned.

        The ID usually identified the control in the window - but there can
        be duplicate ID's for example lables in a dialog may have duplicate
        ID's.
        """
        return handleprops.controlid(self)

    #-----------------------------------------------------------
    def UserData(self):
        """Extra data associted with the window

        This value is a long value that has been associated with the window
        and rarely has useful data (or at least data that you know the use
        of).
        """
        return handleprops.userdata(self)

    #-----------------------------------------------------------
    def ContextHelpID(self):
        "Return the Context Help ID of the window"
        return handleprops.contexthelpid(self)

    #-----------------------------------------------------------
    def IsUnicode(self):
        """Whether the window is unicode or not

        A window is Unicode if it was registered by the Wide char version
        of RegisterClass(Ex).
        """
        return handleprops.isunicode(self)


    #-----------------------------------------------------------
    def IsVisible(self):
        """Whether the window is visible or not

        Checks that both the Top Level Parent (probably dialog) that
        owns this window and the window itself are both visible.

        If you want to wait for a control to become visible (or wait
        for it to become hidden) use ``Application.Wait('visible')`` or
        ``Application.WaitNot('visible')``.

        If you want to raise an exception immediately if a window is
        not visible then you can use the HwndWrapper.VerifyVisible().
        HwndWrapper.VerifyActionable() raises if the window is not both
        visible and enabled.
        """

        return handleprops.isvisible(self.TopLevelParent()) and \
            handleprops.isvisible(self)

    #-----------------------------------------------------------
    def IsEnabled(self):
        """Whether the window is enabled or not

        Checks that both the Top Level Parent (probably dialog) that
        owns this window and the window itself are both enabled.

        If you want to wait for a control to become enabled (or wait
        for it to become disabled) use ``Application.Wait('visible')`` or
        ``Application.WaitNot('visible')``.

        If you want to raise an exception immediately if a window is
        not enabled then you can use the HwndWrapper.VerifyEnabled().
        HwndWrapper.VerifyReady() raises if the window is not both
        visible and enabled.
        """
        return handleprops.isenabled(self.TopLevelParent()) and \
            handleprops.isenabled(self)

    #-----------------------------------------------------------
    def Rectangle(self):
        """Return the rectangle of window

        The rectangle is the rectangle of the control on the screen,
        coordinates are given from the top left of the screen.

        This method returns a RECT structure, Which has attributes - top,
        left, right, bottom. and has methods width() and height().
        See win32structures.RECT for more information.
        """
        return handleprops.rectangle(self)

    #-----------------------------------------------------------
    def ClientRect(self):
        """Returns the client rectangle of window

        The client rectangle is the window rectangle minus any borders that
        are not available to the control for drawing.

        Both top and left are always 0 for this method.

        This method returns a RECT structure, Which has attributes - top,
        left, right, bottom. and has methods width() and height().
        See win32structures.RECT for more information.
        """
        return handleprops.clientrect(self)

    #-----------------------------------------------------------
    def Font(self):
        """Return the font of the window

        The font of the window is used to draw the text of that window.
        It is a structure which has attributes for Font name, height, width
        etc.

        See win32structures.LOGFONTW for more information.
        """
        return handleprops.font(self)

    #-----------------------------------------------------------
    def ProcessID(self):
        """Return the ID of process that owns this window"""
        return handleprops.processid(self)

    #-----------------------------------------------------------
    def HasStyle(self, style):
        "Return True if the control has the specified sytle"
        return handleprops.has_style(self, style)

    #-----------------------------------------------------------
    def HasExStyle(self, exstyle):
        "Return True if the control has the specified extended sytle"
        return handleprops.has_exstyle(self, exstyle)

    #-----------------------------------------------------------
    def IsDialog(self):
        "Return true if the control is a top level window"
        return handleprops.is_toplevel_window(self)

    #-----------------------------------------------------------
    def Parent(self):
        """Return the parent of this control

        Note that the parent of a control is not necesarily a dialog or
        other main window. A group box may be the parent of some radio
        buttons for example.

        To get the main (or top level) window then use
        HwndWrapper.TopLevelParent().
        """
        parent_hwnd = handleprops.parent(self)

        if parent_hwnd:
            return WrapHandle(parent_hwnd)
        else:
            return None

    #-----------------------------------------------------------
    def TopLevelParent(self):
        """Return the top level window of this control

        The TopLevel parent is different from the parent in that the Parent
        is the window that owns this window - but it may not be a dialog/main
        window. For example most Comboboxes have an Edit. The ComboBox is the
        parent of the Edit control.

        This will always return a valid window handle (if the control has
        no top level parent then the control itself is returned - as it is
        a top level window already!)
        """
        if self.IsDialog():
            return self

        parent = self.Parent()

        if not parent:
            return self

        if not parent.IsDialog():
            return parent.TopLevelParent()
        else:
            return parent

    #-----------------------------------------------------------
    def Texts(self):
        """Return the text for each item of this control"

        It is a list of strings for the control. It is frequently over-ridden
        to extract all strings from a control with multiple items.

        It is always a list with one or more strings:

          * First elemtent is the window text of the control
          * Subsequent elements contain the text of any items of the
            control (e.g. items in a listbox/combobox, tabs in a tabcontrol)
        """
        texts = [self.WindowText(), ]
        return texts

    #-----------------------------------------------------------
    def ClientRects(self):
        """Return the client rect for each item in this control

        It is a list of rectangles for the control. It is frequently over-ridden
        to extract all rectangles from a control with multiple items.

        It is always a list with one or more rectangles:

          * First elemtent is the client rectangle of the control
          * Subsequent elements contain the client rectangle of any items of
            the control (e.g. items in a listbox/combobox, tabs in a
            tabcontrol)
        """

        return [self.ClientRect(), ]

    #-----------------------------------------------------------
    def Fonts(self):
        """Return the font for each item in this control

        It is a list of fonts for the control. It is frequently over-ridden
        to extract all fonts from a control with multiple items.

        It is always a list with one or more fonts:

          * First elemtent is the control font
          * Subsequent elements contain the font of any items of
            the control (e.g. items in a listbox/combobox, tabs in a
            tabcontrol)
        """
        return [self.Font(), ]

    #-----------------------------------------------------------
    def Children(self):
        """Return the children of this control as a list

        It returns a list of HwndWrapper (or subclass) instances, it
        returns an empty list if there are no children.
        """

        child_windows = handleprops.children(self)
        return [WrapHandle(hwnd) for hwnd in child_windows]

    #-----------------------------------------------------------
    def ControlCount(self):
        "Return the number of children of this control"

        return len(handleprops.children(self))

    #-----------------------------------------------------------
    def IsChild(self, parent):
        """Return True if this window is a child of 'parent'.

        A window is a child of another window when it is a direct of the
        other window. A window is a direct descendant of a given
        window if the parent window is the the chain of parent windows
        for the child window.
        """

        # Call the IsChild API funciton and convert the result
        # to True/False
        return win32functions.IsChild(parent, self.handle) != 0

    #-----------------------------------------------------------
    def SendMessage(self, message, wparam = 0 , lparam = 0):
        "Send a message to the control and wait for it to return"
        return win32functions.SendMessage(self, message, wparam, lparam)

        #result = ctypes.c_long()
        #ret = win32functions.SendMessageTimeout(self, message, wparam, lparam,
        #    win32defines.SMTO_NORMAL, 400, ctypes.byref(result))

        #return result.value


    #-----------------------------------------------------------
    def SendMessageTimeout(
        self, message, wparam = 0 , lparam = 0, timeout = .001):
        """Send a message to the control and wait for it to return or to timeout

        If no timeout is given then a default timeout of .4 of a second will
        be used.
        """

        result = ctypes.c_long()
        win32functions.SendMessageTimeout(self, message, wparam, lparam,
            win32defines.SMTO_NORMAL, int(timeout * 1000), ctypes.byref(result))

        return result.value


    #-----------------------------------------------------------
    def PostMessage(self, message, wparam = 0 , lparam = 0):
        "Post a message to the control message queue and return"
        return win32functions.PostMessage(self, message, wparam, lparam)

        #result = ctypes.c_long()
        #ret = win32functions.SendMessageTimeout(self, message, wparam, lparam,
        #    win32defines.SMTO_NORMAL, 400, ctypes.byref(result))

        #return result.value


    #-----------------------------------------------------------
    def NotifyMenuSelect(self, menu_id):
        """Notify the dialog that one of it's menu items was selected

        **This method is Deprecated**
        """

        import warnings
        warning_msg = "HwndWrapper.NotifyMenuSelect() is deprecated - " \
            "equivalent functionality is being moved to the MenuWrapper class."
        warnings.warn(warning_msg, DeprecationWarning)

        self.SetFocus()

        msg = win32defines.WM_COMMAND
        return self.SendMessageTimeout(
            msg,
            win32functions.MakeLong(0, menu_id), #wparam
            )


    #-----------------------------------------------------------
    def NotifyParent(self, message):
        "Send the notification message to parent of this control"

        return self.Parent().PostMessage(
            win32defines.WM_COMMAND,
            win32functions.MakeLong(message, self.ControlID()),
            self)

    #-----------------------------------------------------------
    def GetProperties(self):
        "Return the properties of the control as a dictionary"
        props = {}

{'fraction_non_alphanumeric': 0.16702565106716272, 'fraction_numerical': 0.004944194243195614, 'mean_word_length': 1.748721743810549, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6064942', 'n_tokens_mistral': 9773, 'n_tokens_neox': 9360, 'n_words': 4131}