I am using the VirtualTreeView together with the OnMeasureItem event to display rows of variable size. The problem is that the event seems to be called only if a row is painted (following the virtual paradigm). But this leads to the scrollbar being displayed incorrectly. If I scroll to the bottom (by dragging the scrollbox with the mouse, not clicking the scroll buttons at the top or bottom), not the last row is displayed (which is what I would expect), but some row in the middle. After that, the scrollbar is updated and I can scroll further down. It seems as if the component uses the DefaultNodeHeight for its scrolling calculations. But since my rows have variable height, I cannot specify a DefaultNodeHeight that would lead to correct results. Option toVariableNodeHeight is enabled.
Has anyone experienced this before and maybe found a workaround? Or am I doing it wrong?
You need to set DefaultNodeHeight to the maximum value you will be using and OnMeasureItem event set custom height value for the current node. Similar issue was described here.
Related
The TDrawGrid component has a standard way of determining how much to scroll when you scroll to the right and left for example. I want the same behaviour as with a TScrollBox. The amount scrolled to the right and left is a lot less and you can control that. I was using a TScrollBox for this exact reason until I figured out that I can't have fixed Rows and Fixed Cols anymore because my ScrollBox determines the scrolling.
Is there a short way to do this without creating my own component?
I have a THorzScrollBox in a form, and some TStyledControls inside. Each StyledControl has a Tag to identify. Using an TEdit to inform a value, I can find inside the ScrollBox an specific Control by his tag.
If the control that I searched is not on the screen, I want to scroll the ScrollBox to show it.
How can I do this programmatically?
I found a way to do this.
I have to use ScrollBy. But the detail is that if I want to scroll the controls to right I have to use a negative value.
Example:
sbItems.ScrollBy(-10, 0); // this will scroll to right
If I use a positive value, it will scroll to left.
sbItems.ScrollBy(10, 0); // this will scroll to left
The point is, if you scroll once, the ViewportPosition will change and the next time you execute ScrollBy, it will not reset the scroll position, it will scroll from the point you already have scrolled.
I have a DBGrid on a form. The DBGrid has many columns, so an horizontal scroller is displayed. I scroll the DBGrid view to the right to see more columns. If I select a row, the DBGrid view is automatically reset to view the first column (As if I scroll back to the left most position).
Is there a way to prevent that?
I assume you have goRowSelect in the grid options. This forces the selected col to be the first non-fixed column, so whenever the row changes the code to scroll the selected cell into view forces the first non-fixed column to be visible.
Since goRowSelect also effectively disables the horizontal scrolling with the keyboard I try to live without it. You can use custom drawing of the grid cells to show all cells of the current row with the proper colours for selected cells, even though only one cell is really selected. I use this also to show different colours depending on whether the grid is focused or not, similar to what a standard tree control does. For this to work properly you do however need to handle not only grid cell navigation events, but some other events too, like OnEnter and OnExit of the grid, OnActivate and OnDeactivate of the Application, and so on.
You might be able to ask for the scrollbar position
GetScrollInfo(Self.Handle, SB_VERT, SIOld);
and use SetScrollInfo( ) to put it back. There's probably a better way. SelectedField is another way (get/set it as needed).
Delphi 2007.
I have a TGrid with more rows than will fit on the screen, and the height of the grid is such that there is a partially drawn row at the bottom.
When I click on this partial row, it jumps up to be fully visible (via a procedure called 'ClampInView' in Grids.pas). But it doesn't stop. Since the mouse is now over a new partially drawn row, that jumps up too.
The net effect is that clicking on the partially drawn row starts selecting cells in a vertical column, spinning all the way to the bottom (or until you release the mouse).
I have replicated this on a fresh winforms project with just a single grid with 100 rows, and no code, so I'm pretty sure it's not something I'm doing in code wrong.
It is bad for me because the form I have in real code has drag and drop type behaviour, so clicking and releasing ~0.1 seconds later on the partial row will pick up the item in the cell and drop it about 50 rows lower. This is definitely not what you expect to happen when you click on a cell.
Any suggestions how to fix/work around this?
This is what I have always done because I think it is tacky to have partially visible rows. I adjust the size of the grid so its client area is an even multiple of row height. You can do that at design time, or it is easy to do via code as well. The kicker would be if you have re-sizable rows. If that is the case then just put the code to resize the grid in the event handler for the row resize event (I believe it has one).
Not only does this prevent the behavior you are trying to fix, but it also (in my opinion) makes your UI look a lot cleaner!
You can try override MouseDown in your grid and do not call inherited MouseDown, if user clicks in "bad" places.
I have a DBGrid on a form. The DBGrid has many columns, so an horizontal scroller is displayed. I scroll the DBGrid view to the right to see more columns. If I select a row, the DBGrid view is automatically reset to view the first column (As if I scroll back to the left most position).
Is there a way to prevent that?
I assume you have goRowSelect in the grid options. This forces the selected col to be the first non-fixed column, so whenever the row changes the code to scroll the selected cell into view forces the first non-fixed column to be visible.
Since goRowSelect also effectively disables the horizontal scrolling with the keyboard I try to live without it. You can use custom drawing of the grid cells to show all cells of the current row with the proper colours for selected cells, even though only one cell is really selected. I use this also to show different colours depending on whether the grid is focused or not, similar to what a standard tree control does. For this to work properly you do however need to handle not only grid cell navigation events, but some other events too, like OnEnter and OnExit of the grid, OnActivate and OnDeactivate of the Application, and so on.
You might be able to ask for the scrollbar position
GetScrollInfo(Self.Handle, SB_VERT, SIOld);
and use SetScrollInfo( ) to put it back. There's probably a better way. SelectedField is another way (get/set it as needed).