You're asking about an issue with TXBrowse::MouseRowPos() returning 0 because ::nDataRows is being calculated incorrectly, which you suspect is related to ::HeaderHeight() performing extra calculations.
The Problem
Looking at the MouseRowPos() method, it calculates the row position from pixel coordinates and returns 0 if the calculated position exceeds ::nDataRows: 1-cite-0
METHOD MouseRowPos( nRow ) CLASS TXBrowse
local nRowPos, nTmp
if nRow <= ::FirstRow()
return 0
endif
nTmp := nRow - ::FirstRow()
nRowPos := Int( nTmp / ::nRowHeight ) + 1
if nRowPos > ::nDataRows
nRowPos := 0
endif
return nRowPos
The issue is that ::nDataRows is calculated during the Adjust() method and depends on ::HeaderHeight() and ::FooterHeight(): 1-cite-1
METHOD RowCount() INLINE ( If( ::nRowHeight == nil, ::Adjust(),), Int( ( ::BrwHeight() - ::FirstRow() - ::FooterHeight() ) / ::nRowHeight ) )
The Root Cause
The HeaderHeight() method includes additional height when lFull parameter is .t., adding ::nGetBarHeight if ::nBarHdr > 0: 1-cite-2
METHOD HeaderHeight( lFull ) INLINE If( ::lHeader, IfNil( ::nHeaderHeight, 0 ) + ::nTopBarHeight + ;
If( lFull == .t. .and. ::nBarHdr > 0, IfNil( ::nGetBarHeight, 0 ), 0 ), ;
If( ::lDrawBorderIn, 1, 0 ) )
When MouseRowPos() calls ::FirstRow(), which in turn calls ::HeaderHeight(.t.), it includes the extra bar height: 1-cite-3
However, ::nDataRows is calculated based on the browse height minus the full header height, which may not match what MouseRowPos() expects.
The Fix
The issue is that ::nDataRows needs to be recalculated when the browse is adjusted. Looking at the Adjust() method, ::nDataRows should be set after all height calculations are complete: 1-cite-4
Solution: Ensure ::nDataRows is properly calculated by calling ::RowCount() after the browse is fully adjusted. In your drag-and-drop handler, you can force a recalculation:
FUNCTION Toplu_New_KASA_DragAll(nRow, nCol, uDropInfo, oBrw)
local nRowPos
// Ensure browse is adjusted
if oBrw:nRowHeight == nil
oBrw:Adjust()
endif
// Calculate row position manually
nRowPos := oBrw:MouseRowPos(nRow)
if nRowPos > 0
// Move to the calculated row
oBrw:Skip(nRowPos - oBrw:nRowSel)
oBrw:nRowSel := nRowPos
oBrw:Refresh()
endif
RETURN 0
Alternatively, if MouseRowPos() consistently returns 0, you can calculate the position directly:
FUNCTION Toplu_New_KASA_DragAll(nRow, nCol, uDropInfo, oBrw)
local nRowPos, nTmp
if nRow > oBrw:FirstRow()
nTmp := nRow - oBrw:FirstRow()
nRowPos := Int(nTmp / oBrw:nRowHeight) + 1
if nRowPos <= oBrw:RowCount()
oBrw:Skip(nRowPos - oBrw:nRowSel)
oBrw:nRowSel := nRowPos
oBrw:Refresh()
endif
endif
RETURN 0
Notes
The ::nDataRows data member is marked as "used internally" and is supposed to hold the actual number of visible data rows. 1-cite-5 It's calculated during painting and adjustment phases. If you're experiencing issues with MouseRowPos() returning 0, it's likely that ::nDataRows hasn't been properly initialized yet, which typically happens on the first paint cycle. Calling oBrw:Adjust() or oBrw:Refresh() before processing the drop should resolve this.
Wiki pages you might want to explore:
Citations
File: source/classes/xbrowse.prg (L251-251)
nDataRows,; // Actual number of data rows, used internally
File: source/classes/xbrowse.prg (L768-770)
METHOD HeaderHeight( lFull ) INLINE If( ::lHeader, IfNil( ::nHeaderHeight, 0 ) + ::nTopBarHeight + ;
If( lFull == .t. .and. ::nBarHdr > 0, IfNil( ::nGetBarHeight, 0 ), 0 ), ;
If( ::lDrawBorderIn, 1, 0 ) )
File: source/classes/xbrowse.prg (L774-774)
METHOD RowCount() INLINE ( If( ::nRowHeight == nil, ::Adjust(),), Int( ( ::BrwHeight() - ::FirstRow() - ::FooterHeight() ) / ::nRowHeight ) )
File: source/classes/xbrowse.prg (L776-776)
METHOD FirstRow() INLINE ::HeaderHeight( .t. )
File: source/classes/xbrowse.prg (L1441-1469)
endif
::nHeaderPad := ::nFooterPad := 0
if ::lAdjusted .and. ::lFitGridHeight .and. ;
( ( ::lHeader .and. ::nHeaderHeight > 1 ) .or. ::lFooter )
if ( nGap := ::DataRect:nHeight % ::nRowHeight ) > 0
if ::lHeader .and. ::nHeaderHeight > 1
if ::lFooter
::nFooterPad := Int( nGap * ::nFooterHeight / ( ::nHeaderHeight + ::nFooterHeight ) )
::nHeaderPad := nGap - ::nFooterPad
// ::nFooterHeight += ::nHeaderPad // bug fixed 2018-07-10
// ::nHeaderHeight += ::nFooterPad
::nFooterHeight += ::nFooterPad // bug fixed 2018-07-10
::nHeaderHeight += ::nHeaderPad
else
::nHeaderHeight += ( ::nHeaderPad := nGap )
endif
else
::nFooterHeight += ( ::nFooterPad := nGap )
endif
endif
endif
return Self
File: source/classes/xbrowse.prg (L4716-4731)
METHOD MouseRowPos( nRow ) CLASS TXBrowse
local nRowPos, nTmp
if nRow <= ::FirstRow()
return 0
endif
nTmp := nRow - ::FirstRow()
nRowPos := Int( nTmp / ::nRowHeight ) + 1
if nRowPos > ::nDataRows
nRowPos := 0
endif
return nRowPos