EditTable Cookbook - How to get cell coordinates

Published 22 SEP 2009 at 09:00:00AM by Captain C

Many of the applications we write need to display things like option dialog boxes near a specific control. In most cases this is quite easy to handle as we can easily obtain the SIZE property of a control and work out our positioning from that. A slightly more difficult task is to position something relative to an EditTable cell because OpenInsight doesn't expose this information as a property or a method.

We've seen many attempts to calculate cell coordinates in Basic+ - we've even done it a few times ourselves and it's quite a pain, having to take into account all the different styles of the edit table, the width of columns, which columns are hidden and so forth.

Well, there's a really easy way to do this, and that's by asking the EditTable itself what the coordinates are via the standard Windows API SendMessage function. We just need to know what message to send to the EditTable.

DTM_READCELLRECT

The message we need is called DTM_READCELLRECT, and it returns the coordinates of the cell identified via the ACCESSPOS property. All we need to do is pass it the address of a RECT structure to fill in, which we then translate into a dynamic array which we can use further.

Here's a simple function to demonstrate this:

0001  compile function edt_GetCellRect( edtID, colNo, rowNo ) 0002  /* 0003     Author   : Darth C, Sprezzatura Actual 0004     Date     : Sep 09 0005     Purpose  : Function to return edit table cell coordinates 0006      0007     Parameters 0008     

0009      0010       edtID    → Fully qualified name of the edit table  0011        0012       colNo    → Column number of the target cell. Defaults  0013                   to currentPos  0014        0015       rowNo    → Row number of the target cell. Defaults to  0016                   currentPos 0017        0018     Returns 0019     

0020      0021       Returns the edit table cell coordinates as per the RECT 0022       structure layout, i.e. 0023        0024          <1> Left 0025          <2> Top 0026          <3> Right 0027          <4> Bottom 0028        0029       Note these coordinates are relative to the Edit Table  0030       CLIENT area, NOT the desktop/screen! 0031        0032  */ 0033     declare function sendMessage, blank_Struct, struct_To_Var 0034     declare function get_Property 0035      0036     equ DTM_READCELLRECT$ to 1079      ; * // (WM_USER + 55) 0037     equ DTA_ACCESS$       to 0x0000 0038      0039     if assigned( edtID ) else edtID = "" 0040     if assigned( colNo ) else colNo = "" 0041     if assigned( rowNo ) else rowNo = "" 0042      0043     if len( edtID ) else 0044        return "" 0045     end 0046      0047     if len( colNo ) and len( rowNo ) then 0048        call set_Property( edtID, "ACCESSPOS", colNo : @fm : rowNo ) 0049     end else 0050        * // Use the current "caret" position - ensure ACCESSPOS 0051        * // is sync'd with CARETPOS 0052        call set_Property( edtID, "ACCESSPOS",               | 0053                           get_Property( edtID, "CARETPOS" ) ) 0054     end 0055      0056     * // Create a blank RECT structure for the edit table 0057     * // to fill for us and lock it 0058     rc = blank_Struct( "RECT" ) 0059     lockVariable rc as BINARY 0060      0061     * // Send the DTM_READCELLRECT message.  0062     * // 0063     * // The third parameter (wParam) contains a value that  0064     * // tells the edittable which cell we want. DTA_ACCESS 0065     * // means "use the ACCESSPOS property". 0066     * // 0067     * // We send the address of the RECT structure to fill in 0068     * // as the last parameter (lParam). 0069     call sendMessage( get_Property( edtID, "HANDLE" ), | 0070                       DTM_READCELLRECT$,               | 0071                       DTA_ACCESS$,                     | 0072                       getPointer( rc ) ) 0073      0074     * // Unlock and translate the structure to a 0075     * // dynamic array 0076     unlockVariable rc 0077     rc = struct_To_Var( rc, "RECT" ) 0078      0079  return rc

(The more pedantic amongst you may notice that we didn't reset ACCESSPOS after we updated it. The reason for this is simple - every low-level function in the EditTable updates ACCESSPOS to the required coordinates before executing, and you should never assume ACCESSPOS is at the correct coordinates - always set it yourself before use!)

You can download a text version of edt_GetCellRect here

Comments

Original ID: post-2414642644942419674
  • third_party_content/sprezz_blog/15241.375.txt
  • Last modified: 2024/01/17 19:45
  • by 127.0.0.1