Trying to return column number in a browser

Posted by Shaun Henderson on 01-Jun-2016 09:54

I have a browser object and I'm trying to get the number of the column in which the user clicked a cell - is that possible? My browser is called brw-misc so when I try:

brw-misc:CURRENT-COLUMN

I get '?' in return unless I've clicked on the column heading to sort the records before that I tried.

brw-misc:COLUMN

Which always returns '1'.

Thanks

All Replies

Posted by Matt Gilarde on 01-Jun-2016 10:13

Are you trying to query CURRENT-COLUMN in a trigger? I did a quick test using a ROW-ENTRY trigger and it looks like CURRENT-COLUMN isn't updated until after the trigger has run so its value is out of date. That may be the issue you're running into. It seems like a bug to me.

Posted by Patrick Tingen on 02-Jun-2016 01:54

Getting the column in wich the user clicked is a real pita. I have used a workaround in the DataDigger. It works along these lines:

  • When user right-clicks, determine mouse coordinates with a windows api call
  • Walk through the visible (!) columns of the browse and determine whether the mouse coordinates are on that column

Create a window with a browse on it and paste the below code into the "MOUSE-MENU-CLICK" trigger. That includes the extra procedures. Just copy and paste it all in the section editor. You may need to change the name of the browse in the 3rd line of the code (the call to getClickedColumn). Then run the program and right-click a column. It should pop up with the name of the column you clicked on. 

DO:
  DEFINE VARIABLE hColumn AS HANDLE NO-UNDO.
  RUN getClickedColumn(INPUT {&BROWSE-NAME}:HANDLE,OUTPUT hColumn).
  MESSAGE hColumn:NAME VIEW-AS ALERT-BOX INFO BUTTONS OK.
END.

PROCEDURE GetCursorPos EXTERNAL "user32.dll" : 
  DEFINE INPUT-OUTPUT PARAMETER lRect AS MEMPTR. 
END. 

PROCEDURE ScreenToClient EXTERNAL "user32.dll" :
  DEFINE INPUT  PARAMETER hWnd     AS LONG.
  DEFINE INPUT  PARAMETER lpPoint  AS MEMPTR.
END PROCEDURE.

PROCEDURE getClickedColumn:
  /* Return the handle of the column we clicked on */
  DEFINE INPUT  PARAMETER phBrowse AS HANDLE NO-UNDO.
  DEFINE OUTPUT PARAMETER phColumn AS HANDLE NO-UNDO.
  
  DEFINE VARIABLE iColumn AS INTEGER     NO-UNDO.
  DEFINE VARIABLE iMouseX AS INTEGER     NO-UNDO.
  DEFINE VARIABLE iMouseY AS INTEGER     NO-UNDO.
  DEFINE VARIABLE hColumn AS HANDLE      NO-UNDO.
  
  RUN getMouseXY(INPUT phBrowse:FRAME, OUTPUT iMouseX, OUTPUT iMouseY).
  
  findColumn:
  DO iColumn = 1 TO phBrowse:NUM-COLUMNS:
    hColumn = phBrowse:GET-BROWSE-COLUMN(iColumn).
    IF    (iMouseX - phBrowse:X) > hColumn:X
      AND (iMouseX - phBrowse:X) < (hColumn:X + hColumn:WIDTH-PIXELS) THEN
    DO: 
      phColumn = hColumn.
      LEAVE findColumn.
    END. 
  END.
END PROCEDURE. /* getClickedColumn */

PROCEDURE getMouseXY :
  /* Get the position of the mouse relative to the frame */
  DEFINE INPUT  PARAMETER phFrame AS HANDLE      NO-UNDO.
  DEFINE OUTPUT PARAMETER piMouseX AS INTEGER     NO-UNDO.
  DEFINE OUTPUT PARAMETER piMouseY AS INTEGER     NO-UNDO.

  DEFINE VARIABLE lp AS MEMPTR  NO-UNDO. 
  
  SET-SIZE(lp) = 16. 
  RUN GetCursorPos(INPUT-OUTPUT lp). 
  
  /* Get the location of the mouse relative to the frame */
  RUN ScreenToClient(INPUT phFrame:HWND, INPUT lp).
  
  piMouseX = GET-LONG(lp, 1). 
  piMouseY = GET-LONG(lp, 5). 
  
  SET-SIZE(lp) = 0. 
END PROCEDURE. /* getMouseXY */

Posted by Shaun Henderson on 02-Jun-2016 04:40

Hi Patrick,

thanks a lot for your response. I've implemented your code and it's getting closer but now it seems to be comparing with some predefined column coordinates instead of the current ones: if I click in the first 2 columns it's okay, then it starts returning wrong information. If I resize the columns to certain sizes I can get it to return the correct names , but that's not convenient in this case.

Do you have any idea what might be the cause for this?

Cheers,

Shaun

Posted by Patrick Tingen on 02-Jun-2016 08:42

Yes, there's a plain bug in the code [:$] I do not take into account columns that are not visible. Just replace the 'findColumn' loop with this code:

  findColumn:
  DO iColumn = 1 TO phBrowse:NUM-COLUMNS:
    hColumn = phBrowse:GET-BROWSE-COLUMN(iColumn).
    IF hColumn:X > -1  
      AND (iMouseX - phBrowse:X) > hColumn:X
      AND (iMouseX - phBrowse:X) < (hColumn:X + hColumn:WIDTH-PIXELS) THEN
    DO: 
      phColumn = hColumn.
      LEAVE findColumn.
    END. 
  END.


Key element here is the addition of the check on hColumn > -1. This indicates whether a column is visible.

Bad news is that I just discovered that this bug is in the DataDigger too :(

This thread is closed