Correlation using Child windows


Child window Creation

Because no graphics correlation has been built into the operating system, one might look for different ways of performing correlation externally. Perhaps viewing existing graphics programs - like PC paint is in order. A snapshot of PC paint is shown below.

In the above picture, it appears that the client area has shrunk and that there are other items surrounding it - such as a tool bar on the left and a color palette and status bar on the bottom. These are not part of the client area, but are separate child windows. This releases the application from having to perform calculations with regards to selection of these objects from within the client window procedure. That is, an application can use multiple windows to subdivide the visible display.

To perform the same correlation as the programs of the previous section, it is possible to subdivide a parent window into twenty five child windows, each of which manages its own painting and selection. This may appear somewhat contrived - and it is; however, it is worth the practice of experimenting with creating children. In the sample of this section, an array of 25 handles is declared in the client data structure - as shown below.

struct window_data
{
    handle child_array[divisions][divisions];
};

When the message message::create is received by the client window procedure, the child class is registered and the array of 25 child windows is created - as shown below.

case message::create:
 {
        window_data* data = new window_data();
        set_window_pointer(window_handle, 0, (void*)data);

        for (int x = 0; x < divisions; x++)
            for (int y = 0; < < divisions; y++)
                data->child_array[x][y] = create_window(child_class,
                    (const character*)"Child",
                    (unsigned)(style::child | style::visible),
                    use_default,
                    use_default,
                    use_default,
                    use_default,
                    window_handle,
                    (handle)(y << 8 | x));

        return (result)true;
    break;
 }
 break;

Apart from creating the window, the only other major function of the parent window is to position the child windows. It does this upon receiving the sizing message - as shown below.

case message::size:
    {
        window_data* data = (window_data*)get_window_pointer(window_handle, 0);

        int width_of_block = low_part(parameter2) / divisions;
        int height_of_block = high_part(parameter2) / divisions;

        for (int x = 0; x < divisions; x++)
            for (int y = 0; y < divisions; y++)
                move_window(data->child_array[x][y],
                    x * width_of_block,
                    y * height_of_block,
                    width_of_block,
                    height_of_block,
                    true);
    }
    break;

Each of the 25 child windows is positioned using the win+ function move_window. The remaining logic is restricted to the child window procedure. The children must intercept the left button down message and organise to paint themselves according to their state (selected or non-selected). The trivial left button down logic is shown below.

case message::left_button_down:
 set_window_part(window_handle,0,1^get_window_part(window_handle,0));
 invalidate_rectangle(window_handle,null,false);
 break;

When the child window class was registered an additional 2 bytes of memory (a part) was reserved for each instance of the class. Additional window memory defaults to zero value initially. This memory is used to contain the state of the child (checked or unchecked). The extra part is queried, complemented (using exclusive or) and then reset in a single statement. The paint routine is also simple and shown below.

case message::paint:
 {
  paint paint_struct;
  handle device_context = begin_paint(window_handle,&paint_struct);

  rectangle client;
  get_client_rectangle(window_handle,&client);

  draw_rectangle(device_context,0,0,client[1](0),client[1](1));

  if (get_window_part(window_handle,0))
   {
    move_to(device_context,0,0);
    draw_line_to(device_context,client[1](0),client[1](1));
    move_to(device_context,0,client[1](1));
    draw_line_to(device_context,client[1](0),0);
   }

  end_paint(window_handle,&paint_struct);

 }
 break;

The current state of the child window is queried and only if it is non-zero is the cross painted.