Working with nonstandard controls

Sometimes, the possibilities extended by TestComplete are not sufficient to properly handle the controls elements. If that's the case, we need to extend TestComplete possibilities by using private properties and methods of objects that are within TestComplete's access. The brightest example of the situation at hand lies in working with the grids. Grids are quite complex controls elements, changeable and customizable, depending on the situation.

In this recipe, we will use a simple example of the Microsoft DataGridView control to see how standard control properties can be used for solving nonstandard situations. Our task consists of placing a screenshot to the log of a single cell of the grid (by pre-assigned column and row number).TestComplete allows making a screenshot only of the whole grid, but combining native properties of the control with the TestComplete possibilities, we will be able to come by the targeted result. As a tested application, we will use a simple .NET application, which has only one grid with two rows and two columns.

Working with nonstandard controls

How to do it...

In order to create a code which gets a screenshot of a specific cell, we need to perform the following steps:

  1. First of all, we will need to clarify which means are at our disposal. TestComplete has the Picture method, which returns a screenshot of the controls elements, for which it has been called. This won't do us any good, however, as this method has optional parameters (ClientX, ClientY, OffsetX, and OffsetY), which allow making a screenshot of its specific region impossible.
  2. Now we will have to ascertain if we could get a hold on the coordinates and the size of the specific cell in the grid. By carefully looking into the properties of the grid with the help of the Object Browser tab, we will locate the Item property that takes two parameters—number of the row and the number of the column—and returns the object that corresponds with these coordinates.
    How to do it...
  3. In turn, this object has a property AccessibilityObject, while it has another property Bounds, which just fills the bill with the necessary information. Thus, the full path to the left coordinate of the grid will be WinFormsObject("dataGridView1").AccessibilityObject.Bounds.Left.

    Here, however, we encounter a difficulty: the given properties of Bounds are stored in relation to the screen (for example, the property Bounds.Left contains the X-coordinate relative to the left-border of the screen), and not relative to the grid. This means, we will have to transform the absolute screen coordinates that are returned by the object of Bounds, into relative ones.

  4. Again, having perused the properties of the grid, we will get around to its properties of ScreenLeft and ScreenTop, which also spell out absolute positioning in relation to the screen. This way, subtracting the coordinate grid.ScreenLeft from the cell coordinate Item.AccessibilityObject.Bounds.Left, we will get the distance measured in pixels from the left border of the grid to the cell. This is exactly what we need to pass to the Picture method.
    How to do it...
  5. In exactly the same manner we will calculate the vertical coordinates (to this end, we will use the grid.ScreenTop and Item.AccessibilityObject.Bounds.Top properties).
  6. While dealing with the two more parameters of the Picture method (OffsetX and OffsetY)—they simply correspond to the width and height of the cell, and we can obtain them directly from the Bounds property.
  7. In the result, the function that returns the screenshot of the cell will be constructed programmatically to the following effect:
    function getGridCellPicture(grid, row, col)
    {
      var cellBounds = grid.Item(col, row).AccessibilityObject.Bounds;
      var xOffset = cellBounds.Left - grid.ScreenLeft;
      var yOffset = cellBounds.Top - grid.ScreenTop;
      return grid.Picture(xOffset, yOffset, cellBounds.Width, cellBounds.Height);
    }
  8. Looking up the example of the function at work is possible by writing up a simple function.
    function testGrid()
    {
      var wnd = Sys.Process("TestGrid").WinFormsObject("Form1");
      var grid = wnd.WinFormsObject("dataGridView1");
      wnd.Activate();
      Log.Picture(getGridCellPicture(grid, 0, 1));
    }
  9. In the result of the preceding function, the screenshot of the cell will be found in the log with the coordinates (0;1) (that is, from the first row of the first column, as numbering starts with zero).

How it works...

Despite the seeming simplicity of the solution of the task, writing a similar universal function may take up from several hours to several days on end. The whole matter is that locating the necessary property and understanding how it works is quite a difficult task, especially so when it has never been done before. Another factor that influences speed of the solution of a similar task is the internal complexity of the controls element that you are handling.

Moreover, the solution that suits a specific instance may be a misfit for another. Then a programmer has to tentatively try various solutions. Unfortunately, in such cases there is no other way around. We come up with a solution and try to implement it by looking for necessary properties and methods. One should be looking with the help of Object Browser or in the documentation on the controls element that is being worked over. Often, the selected approach turns out to be improper, and we have to keep looking for newer ways towards the solution.

Sometimes, it is useful to request a consultation from programmers that are coding the tested application, as they are working with these elements on a day-to-day basis and may give you a hint off the top of their heads. Nonetheless, it should be known that programmers practically never go about such tasks, for example, getting coordinates (just the thing we had to accomplish); and the best-case scenario would be combining efforts of programmers and testers.

There's more...

The given example is quite simple, however, in real projects one should account for many additional factors. For example, what would happen if the passed number of the row is greater than the overall number of the rows? What would happen if the cell or its part is found outside the ambits of the screen or beyond the border of the controls element? What would happen if the cell is hidden with the settings of a filter in the grid? All of these points are quite realistic, which may lead to emergence of errors, and this is why such functions should be written really carefully, thought through, and reproduced in as many scenarios as possible.

See also

  • The Mapping custom control classes to standard ones recipe in Chapter 5, Accessing Windows, Controls, and Properties
  • The Using text recognition to access text from nonstandard controls recipe in Chapter 5, Accessing Windows, Controls, and Properties
  • The Using Optical Character Recognition (OCR) recipe in Chapter 5, Accessing Windows, Controls, and Properties
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.237.79