Included Delete method. Also Cut/Paste/Delete method will scroll to the current cell, if necessary. (CellEnsureVisible)
Included AutoClipboard property.
Printable View
Included Delete method. Also Cut/Paste/Delete method will scroll to the current cell, if necessary. (CellEnsureVisible)
Included AutoClipboard property.
Update released.
Minor bugfix for the ShowLabelTips property. The cell text was considered falsely as "folded" in case the cell rect was partially clipped by the border of the client rect.
That resulted in showing the label tooltip when in fact the text was fully visible.
The 1.5 OCX was also updated with this fix.
Thank You for Your great job!
By the way, I can't find any documentation or some description of the functions and its parameters... Do You have plans for it? It would be very useful!
Thanks!
Updated released.
Included the cell flooding feature to display like a progress bar in cells. (CellFloodPercent/CellFloodColor/FloodColor property)
Like in the vsFlexGrid a positive FloodPercent will be from left to right and a negative from right to left.
Also added enum FlexCellFloodPercent and FlexCellFloodColor to enrich the Cell property.
Update released.
The Checkboxes feature is now included via the CellChecked property.
Attachment 186462
The new events CellBeforeCheck/CellCheck event helps to react to user interaction.
These are not fired by code, only by mouse click or the space key.
New hit result enum FlexHitResultCheckBox for obvious reason.
The alignment of the checkbox can be either left-center, center-center or right-center and is linked to the CellPictureAlignment property. (!)
The Combo button is already hot-tracked. But yes, the combo cue isn't as it's drawn built in by the grid.
So, yes. I wouldn't want to have mouse track on by default always for the grid itself.
Thus having a new "HotTracking" property would be ideal.
If set to true, all checkboxes and combo cues are being drawn "hot" when the mouse is over them.
Beside those items, how to react to normal cells? Hotlight the cell text?
Update released.
Improved AutoSize/FormatString to resize based on best fit rather than text measure only.
Best fit means to include ComboCue, CheckBox, Picture (NoOverlap align only) and ColSortArrow.
ColSortArrow was previously included in the internal GetTextSize (CX/CY) function which could be misleading.
Now included new internal GetBestWidth function and renamed GetTextHeight to GetBestHeight.
The public exposed functions TextWidth/TextHeight still use the internal GetTextSize function. (but now text only, means without ColSortArrow)
Included BestFitMode property which defaults to 0 - TextOnly (used for AutoSize/FormatString) to behave like intended.
Else you can choose between 1 - Full, 2 - SortArrowText or 3 - OtherText.
Having 2 - SortArrowText is the same as previous behavior, means leaving the other contents (checkbox, combocue) un-measured.
I copy a range from A1 to C3 in excel, then select 3x3 grids in VBflexgrid and click Paste Button (VBFlexgrid1.Paste). data only pasted to second and third column, the second and third row of first column is empty
Updated released.
Support for dynamic checkboxes which are based on the cell text. (added FlexTextAsCheckBox/FlexDisabledTextAsCheckBox enum to FlexCheckBoxConstants)
Empty text (like DBNull) as grayed state, else text to boolean conversion to either checked or unchecked state.
The application is responsible to react on CellCheck event to update the cell text to the new state.
Furthermore the cell text gets hidden/not drawn. Also the label info is as if the cell has no text.
Currently the text is still measured for those cells which has "hidden text". (e.g. GetTextSize/GetBestHeight/GetBestWidth)
This may change in future.. though the vsFlexGrid does also still measure. (there is dynamic approach on ColDataType = boolean)
Update released.
Included new IVBFlexDataSource2 interface. This additional interface enhances the custom data source. It's not put in stone yet and may be extended. If somebody has further suggestion/ideas please post.
The new interface must be implemented in addition. It can not work alone.
When IVBFlexDataSource2 is missing then everything is as before.Code:Option Explicit
Implements IVBFlexDataSource
Implements IVBFlexDataSource2
Provide option flags. Currently these are FlexDataSourceNoFieldNames and FlexDataSourceToolTipText. (Enum FlexDataSourceFlags)Code:Private Function IVBFlexDataSource2_GetFlags() As Long
FlexDataSourceNoFieldNames is convenient because values on fixed rows are not regarded as bound data. So to skip the overwriting via the .GetFieldName just return that flag.
FlexDataSourceToolTipText allows the tool tip text property to be treated in the flex data source. Otherwise GetToolTipTex/SetToolTipText will not be fired and treated as normal properties.
Called upon TTN_GETDISPINFO or via .CellToolTipText. It allows dynamic tool tip text. E.g. the data source can have a column for tip infos which is hidden but get provided here to another field.Code:Private Function IVBFlexDataSource2_GetToolTipText(ByVal Field As Long, ByVal Record As Long) As String
For completeness the other way around.Code:Private Sub IVBFlexDataSource2_SetToolTipText(ByVal Field As Long, ByVal Record As Long, ByVal NewValue As String)
Added FlexDataSourceUnboundFixedColumns enum to FlexDataSourceFlags.
With this flag that can be returned by IVBFlexDataSource2::GetFlags the behavior of .FlexDataSource is the same as .DataSource to treat the fixed columns as unbound.
The reason why .FlexDataSource bounds to the fixed columns was due to compatibility to vsFlexGrid. And of course that keeps this way, this flag just enables a way to change it.
EDIT:
Added FlexDataSourceNoData enum.
This enables to keep the cell texts non-virtual and to make tool tip text virtual only. This allows to take advantage of a certain feature w/o the burden of full fletch virtual source.
Hi,
I used the OCX version since now, everything was fine, but i wanted to use the control directly.
I added all the subs / controls / Res to my project.
Changed the initial object to Sub Main
Added the Call SetupVisualStylesFixes(Me) to the main form and the one where it has the VbFlexgrid used.
Added only 1 VbFlexgrid to a form (the project has more forms), and randomly, when i start (in IDE) my project and load the form (a child form in a MDI project), visual basic closes without error.
If I just open Vb6 again, load the project and run it, now it works...
any idea about why this is happening?
Edit:
If a compile my project and used it from the exe file, it seems it works fine..
Then.. i think it has something wrong with Windows 11 + vb6 sp6. I 'll try to find it, but any idea from where to start to look will be great.
Thanks !
Edit2:
I think the RevMditabs control is the problem than me... just if anyone has the same problem, check it first :-(
Dear Krool,
Greetings! First of all (and as ever), my hearty heartfelt thanks in TONs for your selfless work.
Well, this message is regarding an issue (as stated below) faced by me while editing inside cells of a ComboEditable column.
(Note: In case whatever I have stated below as an issue is itself not correct, then, sorry about it. Kindly guide me as to what I should do to have all the navigation keys working while editing inside the cells of a 'ComboEditable' column)
Issue:
In a 'ComboEditable' column, when I try to edit inside a cell by pressing F2, 'Up' and 'Down' arrow keys do not act. For instance, at runtime, in UserEditingForm (in the VBFlexGridDemo project provided by you), suppose I press 'F2' in the first cell ("Arnold") under 'ComboEditable' column and press Shift+Enter to create a new line and type "is my name". Now, if I press 'Up' arrow key to move to the top(1st) line "Arnold", it does not act. I need to move the 'Left' arrow key only, to move to the 1st line. Now, if I press 'Down' arrow key to move to the bottom(2nd line), it does not act either. I need to move the 'Right' arrow key only, to move to the 2nd line. 'Home', 'End', etc. navigation keys do not work either.
Solution tried:
Initially tried SendKeys and keybd_event, as a quick workaround. They did not act. So, took time to look into the control's code and added an 'if-then-else' line of code at one point. And, it worked. But, I am not sure whether this is the right thing to do. So, I just consider my code alteration (kindly see the red lines below) as a temporary workaround only. I await your correct solution. Thanks.
Kind Regards.Code:If VBFlexGridComboButtonHandle <> 0 And VBFlexGridComboListHandle <> 0 Then
If IsWindowVisible(VBFlexGridComboListHandle) = 0 Then
'
Else
Select Case KeyCode
Case vbKeyUp, vbKeyDown, vbKeyPageDown, vbKeyPageUp, vbKeyHome, vbKeyEnd
SendMessage VBFlexGridComboListHandle, wMsg, wParam, ByVal lParam
Exit Function
End Select
End If
End If
Your suggestion improves the behavior. Thanks! I incorporated this "fix".
Code:If VBFlexGridComboButtonHandle <> 0 And VBFlexGridComboListHandle <> 0 Then
If IsWindowVisible(VBFlexGridComboListHandle) <> 0 Then
Select Case KeyCode
Case vbKeyUp, vbKeyDown, vbKeyPageDown, vbKeyPageUp, vbKeyHome, vbKeyEnd
SendMessage VBFlexGridComboListHandle, wMsg, wParam, ByVal lParam
Exit Function
End Select
End If
End If
Thanks a lot, Krool, for the prompt update.
By the way, I noticed one more thing. When I tried to increase the 'RowHeight' (say, in 'EditKeyUp' event - of any editable cell, not necessarily ComboEditable cell) to be in accordance with the 'TextHeight' of the contents of the cell in which I am editing and entering more content, the redrawing of the cell in accordance with the changed row height was not happening. Please see reference screenshot below. The 2nd line ('is my name') is what I have entered extra. The first line ('Arnold') is hiddden above it. These 2 lines are the actual contents of the cell. The 'Arnold' at the bottom you see in the sreenshot is actually not what I typed. This 'Arnold' is the original content (before I added 'is my name') appearing still at the bottom, along with a repeated ComboCue indicator (since the cell's and combocue's redrawing have not taken place, I believe).
https://www.vbforums.com/image/png;b...AASUVORK5CYII=
I looked into the control's code and saw a DrawCell method. So, I did try giving .CommitEdit and .StartEdit one after the other whenever I changed the RowHeight but I was not able to place the cursor at the correct editing point again. Please guide me as to how to achieve what I wish for. May be the way I am adopting to change the RowHeight is not the correct way to do it. Kindly help.
Kind Regards.
Is there a "test suite" for VbFlecGrid, which use all properties/methods? I though that this will be as a reference for those who want to get the most from this control.
Update released.
Included the ShowScrollTips feature. The feature is most useful when the ScrollTrack property is set to False.
The demo project is updated to demonstrate usage of the ScrollTip event.
If you prefer that the scroll tip follows the thumb as the user scrolls set the ScrollTipFollowThumb property to True.Code:Private Sub VBFlexGrid1_ScrollTip(ByVal Row As Long, ByVal Col As Long)
If Row > -1 Then
VBFlexGrid1.ScrollTipText = "Row " & VBFlexGrid1.TextMatrix(Row, 0)
ElseIf Col > -1 Then
VBFlexGrid1.ScrollTipText = "Column " & VBFlexGrid1.TextMatrix(0, Col)
End If
End Sub
I'd love to have a property that shows the status of the scrollbars, e.g. isScrollbarvisible = vbSBNone, vbBoth etc.
While the state of the scrollbar can be calculated by the app, the data is already in the grid, so why not make it easy.
Another issue is the behavior with many rows and sorting. It should be a doEvent (or maybe an other solution) to prevent the app from showing a non responding window titlebar. A grid with 60k records or more can freeze for minutes, and the user may not know that the sorting is still active and press repeatedly keys or clicks close.
I solved this in my private version of the grid with a property HandleDoEvents()= True or False to allow the grid a DoEvents while sorting or not.
Maybe the property HandleDovents() stores an intervall of milliseconds instead of a boolean value, where 0 disables DoEvents.Code:'*Seniorchef
Public Property Get HandleDoEvents() As Boolean
HandleDoEvents = PropDoEvents
End Property
Public Property Let HandleDoEvents(ByVal Value As Boolean)
PropDoEvents = Value
UserControl.PropertyChanged "HandleDoevents"
End Property
'*End Seniorchef
Private Sub MergeSortRec(ByVal Left As Long, ByVal Right As Long, ByVal Col As Long, ByRef Data() As TCOLS, ByVal Sort As FlexSortConstants)
Dim Middle As Long
Static xTimer As Single
Middle = (Left + Right) \ 2
If Left < Right Then
Call MergeSortRec(Left, Middle, Col, Data(), Sort)
Call MergeSortRec(Middle + 1, Right, Col, Data(), Sort)
Call InplaceMergeSort(Left, Middle, Right, Col, Data(), Sort)
'*Seniorchef
'Every 250 ms a Doevents() to Prevent not respondig Control
If PropDoEvents Then
If Timer - xTimer > 0.25 Then
DoEvents
xTimer = Timer
End If
End If
'*End Seniorchef
End If
End Sub
Of course, the calling app has to ensure that nothing weird happens while the grid processes its doEvents.
Thanks for feedback.
You can simply use GetWindowLong and check for existence of WS_VSCROLL/WS_HSCROLL.
If it's there then it's visible. IMO we don't need properties/functions for everything. It's fairly practical in this case.
About Sort.. well DoEvents is considered as Evil.
So I could offer a "SortTick" event.
A new property "SortTimer As Long" would tell the sort function to install a timer before processing with the given value as milliseconds.
The sorting function then ensures to PeekMessage WM_TIMER internally.
If SortTimer is 0 (default) it's disabled.
This way you could make your DoEvents in the SortTick event.
Is that an idea or stupid?
EDIT: or better just track GetTickCount inside the sorting and raise SortTick if it's due. I think that is ligher with less overhead.
Don't use timer, just raise the event passing two variables, a Cancel and a Skip. Cancel true to stop sorting, and Skip true to not sorting now but command will be in use. So when the list is short, we do not use the event, and always the sort happen. For larger lists let the user handle it. The Skip flag means we have something other in process, so wait until that process end to continue.
Thanks for your answers.
@Krool - you're right, I'm also not a friend of too many "extrawürste". So, ok, I'll try your approach.
@GeorgeKar - It is not to allow another process to jump in or to stop the sorting, it is to enable the OS to process eg. users keystrokes (ESC) or mouseclicks and show a message without interrupting the sort. Some users tend to press keys all over again because there is no feedback (while the sorting is still in progress) and finally stop the running app with the taskmanager or the "wait or kill?"-query.
DoEvents is evil - I know. I still use it in certain circumstances, especially to keep the UI alive while processing time consuming subs.
And it's the only way I know to prevent the app's window from being grayed out by the OS (I'm not a expert in subclassing neither do I know the abyss of the API). Or am I wrong?
The GetTickCount in conjunction with raiseevent()is a good idea (I tested something similar before I made my first Post, and it didn't work -maybe I missed something).
I will give it another try and: I'll be back.
Greetings
Ok, I tested the Event - and it works for me.
I added a RaiseEvent SortTick() and placed a DoEvents in my app in the event handler and Tataa - it's what I need.
As I don't want to stop the sorting, it is up to you to add a Cancel to the Event. For the sake of completeness it would be better. And a timer for the SortTick would also be convenient.
Thanks and
Greetings
To not get Gray Window use this:
Private Declare Sub DisableProcessWindowsGhosting Lib "user32" ()
At sub main call DisableProcessWindowsGhosting and forget the gray window..
You say:
But you have the tools to make not to do anything. Just use events to mark the start and end of the sort and at the "Start mark" disable the form, and enable it at the end (if it is time consuming sort).Quote:
It is not to allow another process to jump in or to stop the sorting, it is to enable the OS to process eg. users keystrokes (ESC) or mouseclicks and show a message without interrupting the sort
The best for me would be to choose for time consuming work to display a wait message, with pause/cancel buttons, and not allow user to click anything else but the cancel/ pause key.
@georgekar - you're right. Honestly, I didn't know the DisableProcessWindowsGhosting, so I will learn to use it. That is a good piece of advice.
Thanks and greetings
I never use editing in place for VBFlexGrid. Before I will update VBFlexGrid I do a enable=false, so no redrawing happen. Then I make the update and then VBFlexGrid1.Enabled = True and VBFlexGrid1.Refresh. I always use a private variable busy as boolean, so in any event handling sub I have If busy then exit sub (so I am not disable controls like commandbutton type for a busy work).
So your problem is that you want more things that the VBFlexGrid can do, like to auto update and redraw according the desired height. So to check it split the process, to a placeholder outside the Grid, where you edit the value to be insert, maybe two ore more lines of text, and then disable Grid, update it, enable it and refresh it.
There is already an internal helper "UpdateEditRect". It currently only moves (SWP_NOSIZE used) but that could be enhanced relativ quickly to also include sizing.
It's used for the moment only when scrolling occurs. (auto update)
The more discussion part is whether to "auto update" on various places, e.g. RowHeight/ColWidth property (and possible more) or to just "auto update" when calling .Refresh ?
I personally do like the "Refresh" solution better. What do you mean ? (the scrolling auto update would remain though)
I am hesitating with this. It involves extra code in the sort routines.
For the bubble sort (custom sort only) it's practical but for the merge sort it would involve at various places to allow good resolution.
Update released.
You should now be able to call .Refresh after your .RowHeight() change and the edit window will fit to the new situation.
Yes, i see. That's why I used the timer and the positioning in the MergeSortRec().Quote:
I am hesitating with this. It involves extra code in the sort routines.
For the bubble sort (custom sort only) it's practical but for the merge sort it would involve at various places to allow good resolution.
As I understand this code, the MergeSortRec() is called recursively 'til the end of the splitting of the array. The static var xTimer counts on every recursion and the event should, with my sample code, be raised almost regularly. I put the code in my copy of the control and it works. Of course, the code in the MergeSortRec()-Sub to skip the checking of the event must be as short as possible.
Here's my code
This is only an idea that works for me. I don't bother if this feature is not included in the grid as long as I can implement it by myself. It was a suggestion.Code:Private Sub MergeSortRec(ByVal Left As Long, ByVal Right As Long, ByVal Col As Long, ByRef Data() As TCOLS, ByVal Sort As FlexSortConstants)
Dim Middle As Long
Dim Cancel As Boolean
Static xTimer As Single
Middle = (Left + Right) \ 2
If Left < Right Then
Call MergeSortRec(Left, Middle, Col, Data(), Sort)
Call MergeSortRec(Middle + 1, Right, Col, Data(), Sort)
Call InplaceMergeSort(Left, Middle, Right, Col, Data(), Sort)
'Every x ms a RaiseEvent() to process calling apps DoEvent
If PropSortTickIntervall > 0 Then
If (Timer - xTimer) * 1000 > SortTickIntervall Then
RaiseEvent SortTick(Cancel)
xTimer = Timer
End If
End If
End If
End Sub
The Custom sort has no need for this feature as there is already an event to be custom the can be used for this purpose, too.
Another thing came to my attention:
I use the event "BeforeUserResize()" to throw a Cancel when a column must not be resized.
Works fine but that leads to a click_event on that column (and that leads to a sorting of the column in my app)
I think the cancelled UserResize() should not lead to a click_event. Either the column is resized or not, nothing else.
In my code, I have to set a flag to ignore the first click after a BeforeUserResize().
Greetings
Thanks and I have a look at the ColResizeable() property.
Back to my sample code in post #815. The cancel in the event is a leftover from my tests and has no effect in the sample. I do not need a Cancel as I don't want to interrupt the sort. Sorry for this inconvenience.
Greetings
Hi Krool, maybe a little bug?
If i set the grid as read only:
Attachment 187000
I can check and uncheck a cell created with .cellchecked = 0
I will check if i'm using your last version now (i think yes)
Edit:
Checked, i can still check/uncheck the cell with the last version
Perfect, Thanks !
Updated released.
New ColCheckBoxes property to have predefined checkboxes in a column.
All FlexNoCheckBox values are mapped as FlexUnchecked.
This makes it easier to add new rows and automatically have new unchecked checkboxes.
Also included GetChecked/SetChecked to the IVBFlexDataSource2 interface to enable to have virtual checkboxes.
To avoid extra overhead here this feature is enabled only when ColCheckBoxes is set to true for the column.
And of course FlexDataSourceChecked must be returned on IVBFlexDataSource2::GetFlags.
ColCheckBoxes and IVBFlexDataSource2 work in conjunction but are still independent. So ColCheckBoxes can be used without IVBFlexDataSource2.
EDIT: Added FlexNoCheckBoxEver enum to FlexCheckBoxConstants as it can be useful to exclude individual cells for ColCheckBoxes. (e.g. for frozen rows)
Fixed rows are always excluded and must be set explicitly.
Update released.
ColFormat always applied to whole column. (like vsFlexGrid)
However, it can be safer sometimes to disable formatting on the fixed cells. So the new FixedFormat property can be used.
But you must apply "" and not vbNullString. If the StrPtr() is 0 then FixedFormat inherits from ColFormat.
Furthermore the internal GetLabelInfo respects now the text display. Also the AutoSize method respects the text display now.
In WIN11 operating system, it cannot be compiled into EXE, and finally it will prompt crash information such as unreadable memory
HI all,
A little question, the checkbox color can be changed ?
the cellforecolor is not working on a cell with a checkbox, i want a greeen checkbox when checked and a red one when it's not checked.
It's possible?
Sure:
Attachment 187153
Done quick with paint xD
In red when checkbox not checked.
Green when checked
The last one is untouched (i just painted the 3 first)
i think it could be perfect
Update released.
CheckBoxDrawMode property (run-time only) included with related CheckBoxOwnerDraw event.
The Row/Col parameter in the CheckBoxOwnerDraw event enables to draw certain columns differently for instance.
When the Cancel As Boolean parameter is set to True the default check box drawing will be done. This enables to only owner draw certain columns effectively.
The ItemState parameter is convenient to draw different states of the check box.
It can be ODS_CHECKED, ODS_GRAYED, ODS_HOTLIGHT and/or ODS_DISABLED.
The viewport is always 0, 0.
Hi all, another question.
Anybody else is suffering ide hangs ?
I mean, when I change code on a form with a vbglexgrid on it, and execute it, works fine, then I change some code (not from the grid, it can be an sql for example), on the form that contains the grid, I execute my program on the IDE, and when I load the form with the grid, it hangs.
I have to start visual basic again and then it works fine the first time, but it hangs if I start the program for a second time.
It's just me ?
I will try to.
what i can see is:
this is how a normal grid is displayed on IDE:
Attachment 187182
And when i change something AND save my project, then it displays this way:
Attachment 187183
If i start the project and go to any form with a Grid on it... IDE hangs and it closes.
I will try to create an small project and try if it hangs too.
Hi again,
I was thinking.. maybe i'm doing the things wrong?
What i'm doing is adding all the modules / controls /etc to my project (and it works)
Maybe i should add the whole project to my project? I tried, but if i set the property public to true, i have an error when adding the control to a form about :
Compile Error: "Private object modules cannot be used in public object modules..
Then... what is the best way to use this project? like i'm doing or.. there is another way ?
Edit1:
Uh...
I found that:
1.- adding whole project to mine (with add project)
2. changing the vbflexgriddemo project properties to control ActiveX
3.- setting to true the public property of the control
4.- setting the instance porp. to 6-globalmultiuse in both clas modules
it seems to work fine in my project?
It's then the best way to add this control to a project ?
Edit2.. no it's not working something else i need to do in order to use this way
Edit3: (sorry xD) Well finally it worked this way, adding the whole project to my project.
I will try to use this way in order to see if not more hangs on IDE when starting / closing it.
But, can you tell me if it's this the right way of using your control? thanks!
I know, but when I need to update it, it's better using it embedded in my soft.
It seems, that is working fine when I created the group of programs in vb6
Edit:
I did more tests (i inform just to see if maybe you/somebody has an idea).
Created New Project.
Added everything again (forms, modules, controls, everything from the old one).
Everything works fine, no hangs in IDE.
Then if i write anything in a form with no grid, and save, everything stills fine.
BUT if i modify a form that has a grid, and SAVE the project, when i load the project again and enter in a form that has a grid, it hangs.
In the windows events it created an error event:
Code:Nombre de la aplicación con errores: VB6.EXE, versión: 6.0.97.82, marca de tiempo: 0x403acf6c
Nombre del módulo con errores: unknown, versión: 0.0.0.0, marca de tiempo: 0x00000000
Código de excepción: 0xc000041d
Desplazamiento de errores: 0x0968813f
Identificador del proceso con errores: 0x30cc
Hora de inicio de la aplicación con errores: 0x01d95b25eb387a57
Ruta de acceso de la aplicación con errores: C:\VB98\VB6.EXE
Ruta de acceso del módulo con errores: unknown
Nombre completo del paquete con errores:
Identificador de aplicación relativa del paquete con errores:
Hi again, sorry for the monologue.
Found when it hangs:
https://www.vbforums.com/images/ieimages/2023/03/17.png
If i stop the program at this line, and then i press F8, it hangs.
I will try to find if i have any api in conflict with it, but any ideas will be welcome.
Thanks in advance