*Dear Cosmin,*

Sorry about that.
I follow EXACTLY the steps described by you until step 6 because that's 
the only way the logic can flow.
At that step, I had a problem with Delphi help system. It sometimes 
loses the path of my help files. I do not know why and I found no event 
to trigger that behavior.
More exactly it tells me that it cannot find a help file and it shows me 
the path to that file: c:BorlandDelphi7HelpD7.hlp
So I kinda give up on this path but I still spent some hours looking on 
Google for peoples who encountered this problem.

This bad event accumulated with other problems and other bugs in Delphi.
This time they really were bugs in Delphi IDE because they were reported 
at the official web site.
Last night Delphi IDE started to act totally strange. On the official 
web page, they said that removing SP2 form Windows XP will help but this 
is out of question. Therefore, I decided to try again Delphi 2006 or 
Lazarus.
I tried Delphi 2006 some times ago but Update 1 and 2 were not available 
at that moment so, there is no big difference (in stability) in Delphi 
2006 compared with Delphi 7.

I am pretty stubborn, I admit, and I hardly give up on something.
Every time I had a problem with a piece of code, I continued to look for 
the reason even if meanwhile (like in the case of TStringList and TEdit) 
I have found an alternative solution or a temporary work around.
I think sooner of later I would have re-installed Delphi 7 and continue 
to track the problem in Microsoft's kingdom.
Anyway, I did not declared 100% this is a bug in Delphi but just asked 
if it is.
This is way I used question mark at the end of the phrase. When a 
strange behavior occurs in Delphi (especially in an ancient version like 
mine), YOU MUST ADMIT that maybe even for a second you think that may be 
a bug.

Some years ago, I used to check the documentation first. But now, when 
something strange happens I check first the official bug list and then I 
dig to find the problem.
A quote says: "When you burnt yourself with soup, next time you will 
check even the yogurt".

So reporting a bug is not such a bad thing as you may think. It is much 
better to have a busted bug than a 'free and wild' one.

Next time I will remember that Borland guys does not think as I am when 
trying to use a TStringGrid as a support for other components :)

Anyway thanks a lot for your extremely well documented solution.

 

 









Cosmin Prund wrote:
> Hello CubicDesign. I solved your problem :-) And it's not a bug in 
> Delphi, it's just something you misunderstood.
>
> Next time, please be more reserved about announcing a bug. It only masks 
> the problem and scares away people that might be able to help. If your 
> subject line would have looked something like this: "TEdit.OnChange not 
> triggering in custom component" you would have attracted allot more 
> people. And it would have shown that you care and you try to fix your 
> problem. I took the time to debug your problem out of anger. If  Horváth 
> Márton didn't post a message that could be misinterpreted as a 
> bug-confirmation, I wouldn't have bothered with your question.
>
> So here are the steps I took to fix your problem:
>
> (1) Create the code, hit F9, run the code, notice it's OnChange doesn't 
> work.
>
> (2) First test: Did I really assign OnChange? Is there some strange code 
> changing my OnChange event handler? Put a button on the form hosting 
> your grid and add this code to it:
> <code>
> if Assigned(MyGrid.Editor.OnChange) then ShowMessage('it''s assigned!')
> else ShowMessage('NOT assigned! Got you!');
> </code>
> Well... that's not the issue. OnChange is in fact assigned, so the code 
> is not in the fact that OnChange is not assigned.
>
> (3) Ask this question: If OnChange IS assigned, why doesn't it trigger? 
> The answer is probably in the code that makes the actual call to 
> OnChange. Open StdCtrls.pas (the unit where TEdit is defined) and do a 
> search for OnChange. You'll find the definition you're after at line 232 
> (property OnChange of object TCustomEdit). You'll then find it's 
> internal var name (FOnChange). Now do a search for FOnChange and see how 
> it's used.
>
> (4) Searching for FOnChange in that file you'll notice a call at line 
> 1991, in TCustomEdit.Change; That's very "standard looking" code for the 
> Delphi VCL. It provides a very simple way for calling the OnChange event 
> handler from other places in the code while providing the "Assigned" 
> test. So now you'll have to look for Change, to see how that's called.
>
> (5) The first call to the Change routine is found at line 2032 in the 
> CNCommand event handler. So it's something about a command handler, that 
> calls for a MSDN search (yes, it's MSDN search, Microsoft, not Borland). 
> Do a MSDN search for EN_CHANGE (or, if you're like me and reaaaaaly hate 
> MSDN search, do a google search and click on the first MSDN link :-) )
>
> (6) It will get you here:
> http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/editcontrols/editcontrolreference/editcontrolmessages/en_change.asp
> Read the document. You'll notice something really funny: The message is 
> sent to the control THROUGH THE PARENT WINDOW!!! Boy that's big news. So 
> it's not actually the TEdit control that is to blame for not triggering 
> this message but it's parent window. But what makes the parent window 
> NOT pass the notification back to TEdit, as it's expected of it? Well... 
> TStringGrid is not a typical control because it's really a "final" 
> control, it's not like TPanel. It's something you drop on a form and use 
> directly. So take a look at how TPanel handles WM_COMMAND, just to get 
> an idea of how it SHOULD be done.
>
> (7) Open ExtCtrls (the "home" of TPanel) and do a search for WM_COMMAND. 
> What? It's not there? That's strage... so the message is not handled in 
> TPanel, but in TWinControl, TPanel's parent. That's bad news since 
> TStringGrid also inherits from TWinControl so it SHOULD inherit this 
> behavior! Take a look into Controls.pas (the of TWinControl) to further 
> understand this problem.
>
> (8) In Controls.pas at line 1114 you'll find the definition for the 
> WM_COMMAND handler in TWinControl. Hit ctrl+shift+down to get to the 
> implementation and you'll find the implementation for this handle. VERY 
> simple code. Why isn't it working? We'll have to put a brakepoint on 
> this line to see what happens. Make sure you tick "use debug DCU's" in 
> project options a do a "build". Hit run. Click on your miss-behaved edit 
> and type some text. You'll notice something: your brakepoint does NOT 
> trigger! But that's not possible, because, according to MSDN 
> documentation a change in an edit control would automatically send an 
> WM_COMMAND to it's parent window. Well... maybe there's something in the 
> way, like an other WM_COMMAND handler that does not call inherited?
>
> (9) Open grids.pas, home of TStringGrid and do a search for WM_COMMAND. 
> And at line 315 you'll find the definition for an WM_COMMAND handler! 
> Again, hit ctrl+shift+down to get to the implementation (at line 3901). 
> Notice something? It's not the same code, and it does not call 
> inherited! Since it doesn't call inherited the code in TWinControl 
> doesn't get invoked and, in turn, it doesn't send the CN_COMMAND message 
> to TCustomEdit so the EN_CHANGE never gets handled by TCustomEdit so the 
> OnChange event handler is not triggered!
>
> (10) well... that's it. You've cracked it! You found the cause of your 
> problem. Now, is it a bug? I don't think so. TStringGrid is free to 
> handle WM_COMMAND any way it wants. After all, that's what the message 
> is for... Should TStringGrid have looked at the Handle for the control 
> and call "inherited" if it doesn't know the handle? TStringGrid is an 
> "final" component, just like TCustomEdit. It's not supposed to get 
> controls on top of it, so why bother with the extra 3 lines of code?
>
> The fix: Add this code to YOUR grid:
> <def>
> procedure WMCommand(var Message: TWMCommand); message WM_COMMAND;
> </def>
> <implementation
> procedure TBGrid.WMCommand(var Message: TWMCommand);
>
>   function DoControlMsg(ControlHandle: HWnd; var Message): Boolean;
>   var
>     Control: TWinControl;
>   begin
>     DoControlMsg := False;
>     Control := FindControl(ControlHandle);
>     if Control <> nil then
>       with TMessage(Message) do
>       begin
>         Result := Control.Perform(Msg + CN_BASE, WParam, LParam);
>         DoControlMsg := True;
>       end;
>   end;
>
> begin
>   if Message.Ctl = Editor.Handle then
>     DoControlMsg(Message.Ctl, Message) // Restore "normal" behaviour
>                                        // for Editor
>   else
>     inherited; // do the TStringGrid thing
> end;
> </implementation>
>
> My code only does this: it restores TWinControl behaviour for WM_COMMAND 
> if the control is your Editor. Plane and simple. DoControlMsg is 
> copy-pasted from the Controls unit so it wasn't difficult.
> --
> Cosmin Prund,
> Happy Coding everyone!
>
> CubicDesign wrote:
>   
>> I use small cells (13x13 pixels) in my TStringGrid, and the 
>> InpalceEditor (which I use it now) is also small, so I need to replace 
>> it with something bigger.
>>
>> Please tell me if the OnClick worked in your Delphi because in mine is 
>> working.
>> It is so strange that OnClick is working and OnChange is not.
>>
>> Somebody with a version of Delphi higher than 7 can confirm if the bug 
>> was fixed?
>> Maybe is finally the time to buy Delphi 2005.
>> Anyway, Delphi 7 started to behave very strange in the last month and 
>> the IDE editor crashed more often than usual.
>>
>> They say that Delphi is the most RAD tool. Maybe it will be true if its 
>> IDE will be not so damn buggy.
>> (This does not mean that I will not buy/upgrade Delphi anymore :)
>>
>>
>>
>>
>> Horváth Márton wrote:
>>   
>>     
>>> Hi,
>>>
>>>   I have tried your sample, and I found the same (in D7). I think the 
>>> guilty 
>>> is the StringGrid descendant, who is the parent of the TEdit. It steal the 
>>> Change message from the Edit. You can use the OnKey.... events (it is so 
>>> ugly), or (more confortable) the TInPlaceEdit descendant instead the TEdit.
>>>   In the TInPlaceEdit descendant you can override the protected methods: 
>>> UpdateContents, Click, DblClick as you wish.
>>>
>>> regards.: m.
>>>
>>> ----- Original Message ----- 
>>> From: "CubicDesign" <[EMAIL PROTECTED]>
>>> To: <delphi-talk@elists.org>
>>> Sent: Thursday, November 16, 2006 1:13 PM
>>> Subject: Bug in Delphi?
>>>
>>>
>>>   
>>>     
>>>       
>>>> *Dear List   * :)
>>>>
>>>> I created my own custom TStringList VCL and now I want to add a better
>>>> editor to it. I want to let the user to enter the text in a TEdit
>>>> control, positioned right above the cell.
>>>> For this, I want to create at run time a TEdit control. All is nice and
>>>> beautiful until I want to assign an event to TEdit.OnChange. It does not
>>>> assign:
>>>>
>>>>
>>>> TYPE
>>>>  TBGrid= class(TStringgrid)
>>>>   Private
>>>>     ...
>>>>   protected
>>>>     Editor: TEdit;     { Custom InPlace Editor in StringGrid }
>>>>   End;
>>>>
>>>>
>>>> constructor TBGrid.Create;
>>>> begin
>>>>  inherited Create(AOwner);
>>>>  Editor:= TEdit.Create(Self);
>>>>  Editor.Parent   := Self;
>>>>  Editor.OnChange := Edit2Change;       <- this is working
>>>>  Editor.OnClick     := Edit2Change;       <- doesn't assign
>>>> bla bla bla
>>>> End;
>>>>
>>>>
>>>> procedure TBGrid.Edit2Change(Sender: TObject);
>>>> begin
>>>>  Bip(5000, 200);
>>>> end;
>>>>
>>>>
>>>>
>>>> I put the StringGrid on a form, I run the program. The Editor shows.
>>>> If I click on it, it beeps. If I type a char in it, it does not beep.
>>>>
>>>>
>>>>
>>>> __________________________________________________
>>>> Delphi-Talk mailing list -> Delphi-Talk@elists.org
>>>> http://www.elists.org/mailman/listinfo/delphi-talk
>>>>
>>>>
>>>>     
>>>>       
>>>>         
>>> __________________________________________________
>>> Delphi-Talk mailing list -> Delphi-Talk@elists.org
>>> http://www.elists.org/mailman/listinfo/delphi-talk
>>>
>>>   
>>>     
>>>       
>> __________________________________________________
>> Delphi-Talk mailing list -> Delphi-Talk@elists.org
>> http://www.elists.org/mailman/listinfo/delphi-talk
>>
>>   
>>     
>
> __________________________________________________
> Delphi-Talk mailing list -> Delphi-Talk@elists.org
> http://www.elists.org/mailman/listinfo/delphi-talk
>
>   
__________________________________________________
Delphi-Talk mailing list -> Delphi-Talk@elists.org
http://www.elists.org/mailman/listinfo/delphi-talk

Reply via email to