Home General

Error TCheckBoxState and TppCheckBoxState Incompatible States

I have just updated Delphi 7's ReportBuilder from v16 directly to v19, skipping v18 where the new tri-state Checkbox feature was added. Unfortunately, I use a LOT of checkboxes and my main application is rather large and full of both checkboxes on the form itself and within the report ... connecting to Paradox True/False boolean fields. The result this morning has been a bit of chaos. What I am looking for is a time-efficient way to address these issues. Is there some external replace set of commands I can use to replace/delete properties in the DFM's regarding this new feature? Is there a DUAL state ppDBCheckBox I can use instead of the regular one? Right now, the program I compiled several hundred times this year without complaint, is now stopping me at every ReportBuilder report with a checkbox on it. Some 139. Gulp.

Just to be clear, the error message specifically states: [Error] FXXXX,pas[162]: Incompatible Types: 'TCheckBoxState' and 'TppCheckboxState'

I originally thought it might be an issue with a checkbox on the form itself. As it tripped on a line that said:
if cbHot.state=cbChecked
then pipHot.print
else pipStandard.print;

So, I changed the actual checkbox to something from a different, more modern library. Still failed. So I commented it out and found a separate checkbox trigger that was from a THIRD different checkbox library. But in each case, it was the line with the actual report.pint that was triggering the error. I checked, the reports were using MyDBCheckBox. So, I replaced the TMyDBCheckBoxes with TppDBCheckboxes and recompiled. The error continued.

You will note the antiquity of these reports. They retain the pip name from the old Piparti days and the MyDBCheckBoxes.

Right now, I am in a holding pattern with an angry customer sending emails with LOTS OF RED in them.

Thanks in advance for any help. GM

Comments

  • edited April 2018
    Hi Gary,

    One solution is to prefix enum values with the type.
      myCheckBox1.CheckboxState := TppCheckboxState.cbChecked;
      CheckBox1.State := TCheckboxState.cbChecked;
    
    When not prefixed as above, the compiler resolves the enum value based on 'uses' clause unit order. So another solution is
    
    uses
      myChkBox,
      Vcl.StdCtrls;
    
      myCheckBox1.CheckboxState := TppCheckboxState.cbChecked;
      CheckBox1.State := cbChecked;
    
    

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • Nard,

    You're talking a BIT above my understanding level. Plus, the solution uses VCL.stdCtrls. Is that a Delphi 7 or a Delphi XE7 or a term for both in the uses clause? In my form, it's simply StdCtrls. Probably FROM the VCL unit, but the dot reference is something XE-sounding to me. And while I need THAT solution too, eventually, the CURRENT hot enchilada is Delphi 7. I PROMISE you that this is the last year for it, but 2018 is young yet.

    Let's dumb it down for me, if you can. I'm not using actual states WITHIN the reports. These are obviously older reports that have not been changed in approaching two decades. And in that time, I've stayed pretty behind the curve as much as possible. In the example I gave you, I reference a checkbox on the form and based on it's state, I run either one report or the other. The error message trips at the THEN clause, meaning it's the REPORT that it balks at. The message then says it's an incompatible type.

    To me, this means the problem is in the report itself, although it hasn't been a problem UNTIL I updated past v16 to v19. A little reading on the internet for the error message and of the update information per v18 indicates ReportBuilder NOW has a tri-clause checkbox.

    I tried changing the mydbCheckBox to a ppDBCheckBox. Actually, both of them in the first indicated problem report. Recompiled and the error tripped in the same exact spot. I'm GUESSING the mycheckbox unit in the top uses clause might be at issue. So, I deleted just about the whole uses clause and let the compiler rebuild it. Same problem.

    Now, I tend to fumble around with examples to learn what I learn. It's like a painter mixing colours. I take what I know and slap a little of this into it and a little of that. And finally, I get a working colour. That's my learning curve.

    IF you can, can you talk me through WHERE I stick these enum values and maybe why? Enumeration tends to indicate integers in my experience and integer to integer SEEMS compatible. Guess not. I appreciate you are going beyond ReportBuilder 101 to do this, but I honestly don't get the solution. And do I apply it to the roughly 90 units with twice that number of reports? Or is one central location in the DPR or the main form good enough to fix this? It can't be a MAJOR issue, cuz your forums would be full of how come/why fors. So I suspect it's just me looking into the forest for the sign that's right behind me.

    Thanks, GM
  • Hi Gary,

    - Vcl.StdCtrls is equivalent to StdCtrls in legacy Delphi.

    - Enumerated types are similar to constants, but are not interchangeable. Each enum type is a distinct type and is not assignment compatible with other enum types.

    The Delphi StdCtrls.pas unit defines the TCheckbox class and also defines TCheckboxState
    TCheckBoxState = (cbUnchecked, cbChecked, cbGrayed);
    The RB myCheckbox.pas unit defines the TmyCheckbox class and also defines TppCheckboxState
     TppCheckboxState = (cbChecked, cbGrayed, cbUnchecked);
    
    When the compiler reads code like
    Checkbox1.State := cbChecked;
    its not clear whether cbChecke refers to TCheckBoxState.cbChecked or TppCheckboxState.cbChecked.

    One solution is to prefix cbChecked with the correct type
    Checkbox1.State := TCheckBoxState.cbChecked;
    Another solution is to order the 'uses' clause like this
    uses
        myChkBox,
        StdCtrls;
    
      Checkbox1.State := cbChecked;  
    
    
    
    Whereas this code example results in a compiler error
    uses
        StdCtrls,
        myChkBox;
    
      Checkbox1.State := cbChecked;  
    
    
    

    As a test, try creating a new project with a Form, add a Checkbox and a Report that contains a myCheckbox and play around with compiling the above code examples.

    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • Nard,

    A perfect lesson, I think. Lots of clues, without doing my actual coding for me. Thanks, GM
  • So, a report and a question.

    First, the report. I decided to use this situation to homogenize all the check boxes in all the forms to one common one: TJVCheckbox. Turns out I couldn't do that completely. There were places where TMS' THTMLCheckBox and TParamListCheckBox were needed. BUT there were a fair number of OTHER checkbox types involved because this is a program that has evolved over more than 20 years and I often put in the new Checkbox toy of the month when doing something new. Not a good thing, but it is what it is.

    So, I got them all into just the three types and then started adding TJvCheckBox.cbChecked/cbUnchecked or THTMLcheckbox.cbChecked or TParamListCheckbox.cbchecked as needed. Then I compiled and found out NONE of the statements would compile with the added prefixed types before cbChecked or cbUnChecked. That seem completely contradictory to your first bit of advice, but I at least got the standardization of simple checkboxes out of it, including a few libraries that don't exist anymore and who's code isn't guaranteed to run in Delphi XE7 when that time comes for me. So not a waste of time.

    What worked was having MyChkBox, StdCtrls run at the direct end of the default Delphi units in the Used clause at the top of the form. In fact, it was only some 40 forms to do and it went by quickly and I was up and running with a new and successful compilation.

    So here's the question: Why does ReportBuilder have a checkbox component (two, if you included the DBcheckbox) with a different order than the standard out of the box Delphi Checkbox? The order seems logical in having greyed be the zero while the other actual states are absolute 1. But 'breaking' the default Delphi order, however illogical it might be, seems counter-productive.

    It's not the only case of this I've run across. Our office WANTED badly to ditch Microsoft Office for OpenOffice early in this decade. But we ran across a problem in lookup list handling in OpenOffice. In OO's Calc, if the comparison number fell BELOW the lowest number in the list, the result would NOT be the lowest number. i.e. comparing 3 to a list of 5, 10, 15 would be either zero or null, I can't actually remember which. In Excel, the answer would be 5. Excel's answer is demonstrably illogical (if it is going to be that way, then all lookuplists should start with zero).

    I contacted the OpenOffice mandarins and noted that this discrepancy prevented us from using Calc to replace Excel. The mandarins basically replied that too many extent sheets in THEIR format existed to make a change. We had third-party sheets that used the Excel methodolog and would not produce the same result in Calc. It put a spike in our plans to convert and save a huge cheque to Microsoft with every update (later every year).

    I suspect that I am in the same territory here. But I AM interested in your decision to do checkboxes differently.

    Thanks for helping me with a solution to my problem. Greatly appreciated. GM
  • Hi Gary,

    For the next release, I'll modify TppCheckboxState to define the enums in the same order as Delphi TCheckboxState. Thanks for the feedback.

    RB includes TmyCheckbox and TmyDBCheckbox. It does not have TppCheckbox or TppDBCheckbox. This is due to a decision in the beginning to include Checkbox and DBCheckbox as examples of how to build a custom RB component. In hind set, should have just named them with the 'pp' prefix. If you have TppCheckbox/TppDBCheckbox then that must be what you did.

    For the compile issues, such as TJvCheckBox.cbChecked, refer to the docs and source code for the enum type name. TJvCheckBox is the class name, the enum type name will be something like TJvCheckboxState, which would mean TJvCheckboxState.cbChecked would compile. Also make sure the 'uses' clause includes a reference to the unit the defines the enum type.








    Best regards,

    Nard Moseley
    Digital Metaphors
    www.digital-metaphors.com
  • Appreciate the feedback. It looks like I modified the right side rather than the left side in the state comparison. Thanks for clearing that up. Now, does your change BREAK existing code or will we all benefit equally from the change in order precedence? If it's going to go all-right, all the time, then I can just concentrate on the one big app right now, plus the XE7 update I'm working on. Not having to comb through ALL the other code for all the other programs would be a boon indeed. Thanks, GM
Sign In or Register to comment.