Enabling extended selection on a <table-control>

Home
Introduction
Tips and Techniques
Projects
Libraries
Links

This tip relates to Functional Developer and DUIM.

When you have a <table-control> gadget filled with items you may notice that selecting items with the mouse may work differently than in some Windows applications.

If there are multiple columns in the table you can only select a row by clicking on the row item in the first column. Only that column is highlighted to indicate the selection.

If you click on the row item in the second column then the row is not selected. This is the standard behaviour of the Windows list control. But most applications allow you to click anywhere on the row (ie. in any column) and have the entire row highlighted.

This 'entire row' method of selection is an extended mode of the Windows list control and you can enable this functionality in Functional Developer by using the backend win32-duim library.

For example, the following frame exists in an application:

   define frame <example-frame> (<simple-frame>)
     pane table-pane (frame)
        make(<table-control>,
             headings: #["One", "Two", "Three"],
             generators: vector(identity, curry(\*, 2), curry(\*, 3)),
             items: #[1, 2, 3, 4, 5]);
     layout (frame)
       frame.table-pane;
   end frame <example-frame>;

By default the rows in the table-pane will only be able to be selectable from the first column. By adding the following method we can enable full row selection:

   define method handle-event( frame :: <example-frame>, 
                               event :: <frame-mapped-event> ) => ()
     let hwnd = frame.table-pane.window-handle;
     let LVS-EX-FULLROWSELECT = #x20;
     let LVM-FIRST = #x1000;
     let LVM-GETEXTENDEDLISTVIEWSTYLE = LVM-FIRST + #x37;
     let LVM-SETEXTENDEDLISTVIEWSTYLE = LVM-FIRST + #x36;
     let lstyle = SendMessage(hwnd, LVM-GETEXTENDEDLISTVIEWSTYLE, 0, 0);
     lstyle := %logior(lstyle, LVS-EX-FULLROWSELECT);
     SendMessage(hwnd, LVM-SETEXTENDEDLISTVIEWSTYLE, 0, lstyle);
   end method handle-event;  

Firstly, although I have all the values defined within the method, they can be (and probably should be ) constants defined in a library somewhere.

The <frame-mapped-event> event is raised when the frame has completed creating the Windows back end portions. At this point it is safe to start doing Win32 specific stuff to the gadgets and controls if need be. This is the point we want to extend the functionality of the control.

The details of the method are Win32 specific and outlined in Microsoft documentation so I won't go into it in detail. Basically we are sending Windows a command telling it to enable the extended selection style of the control.

To use this you will need to use the following libraries:

   define library my-library
     [...other library stuff...]
     use win32-duim;
     use win32-user;
     use c-ffi;
    end library;

You will also need to use the corresponding modules. I usually specify exactly the functions I want to import:

   define module my-module
     [...other module stuff...]
     use win32-duim, import: { window-handle };
     use win32-user, import: { SendMessage };
     use c-ffi, import: { %logior };
   end module;

Copyright © 2000, Chris Double. All Rights Reserved.
All products and brand names are the registered trademarks or trademarks of their respective owners.