View Issue Details

IDProjectCategoryView StatusLast Update
0031993LazarusLCLpublic2017-06-29 15:52
ReporterSoner Assigned Towp  
PrioritynormalSeverityminorReproducibilityhave not tried
Status closedResolutionfixed 
Platformi386OSWindows 
Product Version1.6.4 
Target Version1.8RC2 
Summary0031993: (Patch)RadioItems from TDBRadioGroup is changeable also by TDataSet.ReadOnly=true
DescriptionRadioItems from TDBRadioGroup is changeable also when associated TDataSet is ReadOnly.
The Datafield value does not changed only the Radioitems can be selected.
Steps To Reproduce1) Start the example
2) Click readonly-Button
3) Click on the DBRAdioGroup on the left.
4) Look in the grid, the value doesn't changed only
 the selected RadioButton is changed.
5) Apply my patch and start the example again.
Additional InformationThis is the Patch (only the last 4 lines):
lcl\include\dbradiogroup.inc
procedure TDBRadioGroup.UpdateRadioButtonStates;
// .. dont change it shows only where to add the patch
  if (NewValue<>OldValue) and FDatalink.CanModify and not SettingValue then
  begin
// .. dont change it shows only where to add the patch
  end
  
    //; Soner FOLLOWING IS PATCH ..........
  else if (not DataLink.CanModify) and (DataLink.Field.AsString<>NewValue) then begin
    fValue:=''; // because in procedure TDBRadioGroup.SetValue is
                // if FValue=AValue then exit;
    Value:= OldValue;
  end;
end;
TagsNo tags attached.
Fixed in Revision55344
LazTarget1.8
WidgetsetWin32/Win64
Attached Files

Relationships

duplicate of 0021099 resolvedLuiz Americo Packages DBRadioGroup Behavior 
related to 0032077 resolvedwp Lazarus Access Violation in TDBRadioGroup.UpdateRadioButtonStates 

Activities

Soner

2017-06-09 21:33

reporter  

Juha Manninen

2017-06-11 10:43

developer   ~0101018

Please create a proper patch.
 http://wiki.freepascal.org/Creating_A_Patch

Soner

2017-06-11 14:21

reporter   ~0101020

Last edited: 2017-06-11 14:33

View 2 revisions

Possible solution that works(note: "and DataLink.Active " ) :
Change the file: lcl\include\dbradiogroup.inc
Add the end of the procedure TDBRadioGroup.UpdateRadioButtonStates;
following lines:
  //; <- comment out ;
  else if (not DataLink.CanModify) and (DataLink.Active) and (DataLink.Field.AsString<>NewValue) then begin
   fValue:=''; // because in procedure TDBRadioGroup.SetValue is:
               // if FValue=AValue then exit;
   Value:= OldValue;
 end;

Soner

2017-06-11 14:30

reporter   ~0101021

@Juna Manninen
I can't send proper patch, because:
 - this isn't patch, it is possible solution.
 - I don't have svn-Version from Lazarus and I can't just download svn-Version, because I have only 56K internet connection (mobile Smart-phone connection).
I download new or fixed Versions from Lazarus in Office or by friends.

Sorry for misleading issue title, in future I will not call it patch, when it isn't patch.
Sorr again.

Juha Manninen

2017-06-11 20:51

developer   ~0101027

The initial loading of SVN version takes bandwidth.
After that only diffs for the latest changes are downloaded (eg. "svn up") and the bandwidth usage is minimal.
You use much more bandwidth when downloading the release versions with binaries and all included.

wp

2017-06-13 00:24

developer   ~0101072

The patch works, but I am not sure if it fixes the right place. The patch just reverts a change of the radiogroup's ItemIndex if the dataset is readonly. I think the correct fix should not allow the radiogroup to change at all. Unfortunately, TCustomRadioGroup does not have a ReadOnly property, and according to 0021099, it probably will never have one. There is a method "CanModify" which could be overridden to return FDataLink.CanModify, but it does not seem to be fully implemented.

Soner

2017-06-13 11:48

reporter   ~0101080

@wp
I followed your idea and found possible solution, this works also with normal TRadioButtons.
To set the TRadioButtons ClicksDisabled property automatically, we can use TDataLink.SetReadOnly or similar. I set ClicksDisabled in example programm self.

Here is possible solution:
1)In lazarus\lcl\interfaces\win32\win32callback.inc
//soner: Add this from here .....
// (remove this after moving TButtonControl.ClicksDisabled in public-area)
type
  TButtonControlHack = class(TButtonControl)
  public
    property ClicksDisabled;
  end;
// ... to here.
  
  
//soner: change this
function TWindowProcHelper.DoWindowProc: LResult;
//..
    BM_SETCHECK:
    begin
      //LParam holds BST_CHECKED, BST_UNCHECKED or SKIP_LMCHANGE;
      if LParam <> SKIP_LMCHANGE then
        LMessage.Msg := LM_CHANGED;
      if lWinControl is TRadioButton then
      begin
      
      //Soner add this from here ...
        if (TButtonControlHack(lWinControl).ClicksDisabled) then begin //soner
          if Ord(TRadioButton(lWinControl).SavedState)<>SendMessage(lWinControl.Handle,BM_GETCHECK,0,0) then
            Windows.sendMessage(lWinControl.Handle, BM_SETCHECK,
              Windows.WParam(Ord(TRadioButton(lWinControl).SavedState){BST_UNCHECKED}), Windows.LParam(SKIP_LMCHANGE));
        end
        else
 
      // ... to here.
      
      //Uncheck siblings
      if WParam = BST_CHECKED then
        ClearSiblingRadioButtons(TRadioButton(lWinControl));
//..


// ****************************************************
2) In lazarus\lcl\stdctrls.pp
  TCustomCheckBox = class(TButtonControl)
//..
  public
    constructor Create(TheOwner: TComponent); override;
    function SavedState: TCheckBoxState; //soner add this (we need this because checked returns current(win32)state not the saved state)


// ****************************************************
3) In lazarus\lcl\include\customcheckbox.inc
function TCustomCheckBox.SavedState: TCheckBoxState; //soner add this
begin
  Result:=FState;
end;

    
// ****************************************************
4) In example programm

type
  TButtonControlHack = class(TButtonControl)
  public
    property ClicksDisabled;
  end;
  
procedure TForm1.BtnReadOnlyClick(Sender: TObject);
var i: integer;
begin
  BufDataset1.ReadOnly:=BtnReadOnly.Down;
  if BufDataset1.ReadOnly then Caption:='ReadOnly'
  else Caption:='Not ReadOnly';

  for i:=0 to DBRadioGroup1.ControlCount-1 do
    TButtonControlHack(DBRadioGroup1.Controls[i]).ClicksDisabled:=AValue;
    
   //test for the normal radiobuttons
   TButtonControlHack(RadioButton1).ClicksDisabled:=AValue;
   TButtonControlHack(RadioButton2).ClicksDisabled:=AValue;

end;

Soner

2017-06-13 12:06

reporter   ~0101081

I would prefer first solution because it is crossplatform and the changed solution needs changes in lcl and it is only for win32-widgetset.

wp

2017-06-13 12:17

developer   ~0101083

Last edited: 2017-06-13 12:33

View 2 revisions

Thank you.

I did not yet try to bring your code snippets into current code because I see two main problems:

(1) You are referring to win32 interface units. This implies that your code will be working only for Windows. But we need it cross-platform! My preference would be not to touch widgetset code at all because it will become an endless story. (NOTE: When writing this I did not see your previous message # 101081)

(2) The name "ClicksDisabled" implies (maybe I am wrong) that the code works only for mouse clicks. But the radiobutton/radiogroup can also be changed by means of the keyboard: Press the accelerator key assigned to the button, or navigate to the requested button by means of the arrow keys and press Space.

Soner

2017-06-13 12:38

reporter   ~0101085

The first solution(https://bugs.freepascal.org/view.php?id=31993#c101020) is crossplatform. I am using this for my lazarus.

Only the second solution(https://bugs.freepascal.org/view.php?id=31993#c101080) is for win32-interface. But the message part (in TWindowProcHelper.DoWindowProc) can be implemented for other widgetsets.

I am happy with first solution and it solves one problem that very rarely apppers.

wp

2017-06-13 13:50

developer   ~0101089

A non-perfect patch is better than no patch --> applied (r55344). Left a comment in the source that it's only a workaround. Please test and close if ok.

This issue will come back, though, because TDBCheckbox suffers from the same problem...

Soner

2017-06-13 16:51

reporter   ~0101096

@wp
I would make this (the first way) also for TDBCheckbox.

This could be third solution to avoid onchanged event (Not tested):
1) Using TButtonControl.ClicksDisabled.
I think it is for this Kind of usage:
http://lazarus-ccr.sourceforge.net/docs/lcl/stdctrls/tbuttoncontrol.clicksdisabled.html

2)Changing in procedure TCustomRadioGroup.CheckItemIndexChanged;
this
if FLastClickedItemIndex=FItemIndex then exit;

to this:

if clicksdisabled and (FLastClickedItemIndex<>FItemIndex) then begin
  SetItemIndexWithoutEvents(FLastClickedItemIndex); // = SetState-Function
  exit;
end
else
if FLastClickedItemIndex=FItemIndex then exit;

--------------

Now, I close this because this because your patch is okay.

wp

2017-06-13 17:06

developer   ~0101097

SetItemIndexWithoutEvents - I was searching for something like this, but it does not exist.

Soner

2017-06-13 17:31

reporter   ~0101098

Sorry I should write more clearly.
It is the SetState-Function from TCustomCheckBox you must move it to protected or public area.(RadioButton is derived from CheckBox).

It is exactly the this function from procedure TCustomCheckBox.ApplyChanges:
TWSCustomCheckBoxClass(WidgetSetClass).SetState(Self, FState);

But you can use SetState from checkbox.

I will look all the Radio- and CheckBox related bugs closer today, when i am back at home.

Soner

2017-06-15 14:36

reporter   ~0101150

I closed this issue but now it looks like not closed.
Close this as solved.
Third way is not needed, because:
1.In FCL/LCL is some changes for TDataLink.SetReadOnly needed (for setting TButtonControl.ClicksDisabled).
2. No one shuld use TDBRadioGroup.OnChanged, because TDataset.AfterScroll, TField.OnChange or TField.OnSettext is for database more suitable.

Issue History

Date Modified Username Field Change
2017-06-09 21:33 Soner New Issue
2017-06-09 21:33 Soner File Added: DbRgReadOnlyError-public.7z
2017-06-11 10:43 Juha Manninen Note Added: 0101018
2017-06-11 14:21 Soner Note Added: 0101020
2017-06-11 14:30 Soner Note Added: 0101021
2017-06-11 14:33 Soner Note Edited: 0101020 View Revisions
2017-06-11 20:51 Juha Manninen Note Added: 0101027
2017-06-13 00:17 wp Relationship added duplicate of 0021099
2017-06-13 00:24 wp LazTarget => -
2017-06-13 00:24 wp Note Added: 0101072
2017-06-13 00:24 wp Assigned To => wp
2017-06-13 00:24 wp Status new => acknowledged
2017-06-13 11:48 Soner Note Added: 0101080
2017-06-13 12:06 Soner Note Added: 0101081
2017-06-13 12:17 wp Note Added: 0101083
2017-06-13 12:33 wp Note Edited: 0101083 View Revisions
2017-06-13 12:38 Soner Note Added: 0101085
2017-06-13 13:50 wp Fixed in Revision => 55344
2017-06-13 13:50 wp LazTarget - => 1.8
2017-06-13 13:50 wp Note Added: 0101089
2017-06-13 13:50 wp Status acknowledged => resolved
2017-06-13 13:50 wp Resolution open => fixed
2017-06-13 13:50 wp Target Version => 1.8RC2
2017-06-13 16:51 Soner Note Added: 0101096
2017-06-13 16:51 Soner Status resolved => closed
2017-06-13 17:05 wp Status closed => assigned
2017-06-13 17:05 wp Resolution fixed => reopened
2017-06-13 17:06 wp Note Added: 0101097
2017-06-13 17:06 wp Status assigned => feedback
2017-06-13 17:31 Soner Note Added: 0101098
2017-06-13 17:31 Soner Status feedback => assigned
2017-06-15 14:36 Soner Note Added: 0101150
2017-06-15 20:49 wp Status assigned => resolved
2017-06-15 20:49 wp Resolution reopened => fixed
2017-06-18 00:49 Soner Status resolved => closed
2017-06-29 15:52 wp Relationship added related to 0032077