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