Fr0sT.Brutal 900 Posted December 12, 2022 Hooking an RTL procedure is rather simple https://github.com/Fr0sT-Brutal/Delphi_MemoryModule/blob/master/FuncHook.pas but Windows-only Share this post Link to post
PizzaProgram 9 Posted December 12, 2022 OFF: Thank you very much to all of you! I'll take the advice of @programmerdelphi2k : On 12/11/2022 at 1:34 AM, programmerdelphi2k said: to replace an occurrence with another occurrence! @Fr0sT.Brutal : That "hook" code is great, đ although a bit complicated for me, without "how to use it" example. Thank you very much! But I'm still using Delphi7 and the code is only for 2009+. Also have a "keyboard hook" in my code, and it's always leaking, when I close the program, so I rather stay away from that technic.  For "easy replacing" :  I have GExpert installed. It is easy to click "Grep Search" and than > replace.  I'm just afraid of forgetting next time: NOT to use ShowMessage function any more... (25+ years of daily practice is hard to replace đ ) Share this post Link to post
Fr0sT.Brutal 900 Posted December 12, 2022 (edited) 24 minutes ago, PizzaProgram said: But I'm still using Delphi7 and the code is only for 2009+. It's easy to backport to D7 24 minutes ago, PizzaProgram said: Also have a "keyboard hook" in my code, and it's always leaking, when I close the program, so I rather stay away from that technic. That's completely different tech sharing the same name  You can also place your custom proc with the same name ShowMessage in any common unit and ensure it goes after RTL one in the uses list. Compiler will pickup the proc from the most later used unit. However you'll need to ensure to always use that unit where ShowMessage is called. Edited December 12, 2022 by Fr0sT.Brutal Share this post Link to post
programmerdelphi2k 237 Posted December 12, 2022 (edited) A simple way to "replace" ( I say: betweem quotes ), would be! create a unit with your "procedure/function" called: ShowMessage(...) -->( with same params then "showmessage by Delphi") in all units desired, you would put it in "last" place on "USES" clause! then, you can replace the "occurrence" this way:  uses ..... others, ..... MyNewSHOWMESSAGEunit;  ... where is: ShowMessage(....) ... you change to:  MyNewSHOWMESSAGEunit.ShowMessage(....) then, nothing really would be changed on "Delphi sources", only a "workaround" (bad) but works!  this is done when needs "avoid" conflicts, then, you use "namespaces" from units, or types! including, you can "use this unit name" in your Project-Options->Compiling-> Unit Aliases... unit uMyNewSHOWMESSAGE; interface interface procedure ShowMessage(const AText: string); implementation uses Vcl.dialogs; procedure ShowMessage(const AText: string); begin Vcl.dialogs.ShowMessage('My ShowMessage: ' + AText); // ... or, your customized code here end; end. var Form1: TForm1; implementation {$R *.dfm} uses uMyNewSHOWMESSAGE; procedure TForm1.Button1Click(Sender: TObject); begin Vcl.Dialogs.ShowMessage('Hello'); // by VCL // needs because the same names and uses clause above! // uMyNewSHOWMESSAGE.ShowMessage('hello world'); // your ShowMessage! end;  Edited December 12, 2022 by programmerdelphi2k Share this post Link to post
PizzaProgram 9 Posted December 15, 2022 The only question remains about a self-created ShowMessage dialog: Â How to determine optimally the necessary wide / height for the text. 1. Normally I like small boxes at the middle of the screen, 2. but would like to make it "screen-wide" if the text is longer. 3. and even Full-Screen sized, if the text is toooooo long. Â I've thought about "checking 3x", if it fits, but can not determine the current Height, because the TextHeight function does not properly working under Delphi 7. Label1.Width := 400; Label1.Font.Size := 14; Label1.WordWrap = True; // Label1 is a "sLabel" of AlphaSkin component pack, if that counts? y_1 := Label1.Canvas.TextHeight('Ăg'); // y_1 = 13 txt := 'first line' + #13#10 + #13#10 + #13#10 + #13#10 + #13#10 + 'other very long line to force a word wrap occure... 1234567890'; y_All := Label1.Canvas.TextHeight(txt); // does not give back correct word-wrapped info! :-( // y_All = 47; = 3 lines only, instead of more. linesNum := y_All div y_1; Any ideas? (Checked 50 forums, but did not find any answer.) Share this post Link to post
Lajos JuhĂĄsz 293 Posted December 15, 2022 In order to calculate the required space you can use windows APIÂ DrawTextEx with format option DT_CALCRECT. 1 Share this post Link to post
PizzaProgram 9 Posted December 15, 2022 Thanks, I'll look into it. Seems promising. đ I guess I'll also need: DT_WORDBREAK or DT_TOP or DT_LEFT. Anything else? Share this post Link to post
programmerdelphi2k 237 Posted December 15, 2022 (edited) try my sample:Â Form2 with a TLabel for receive the text... uses Unit2; procedure TForm1.Button1Click(Sender: TObject); function HowManyLinesOnText(const MaxWidth: integer; const ATextLen: integer): integer; begin result := (ATextLen div MaxWidth); // if (ATextLen mod MaxWidth) <> 0 then result := result + 1; end; var MyText : string; LCharWidth : integer; LCharHeigth : integer; LTextLen : integer; LNewLabelHeight: integer; begin for var i: integer := 1 to 10 do MyText := MyText + Format('%dx a long text to show on my custom dialog to user!', [i]); Form2 := TForm2.Create(nil); try // LTextLen := Length(MyText); LCharWidth := Form2.Canvas.TextWidth('W'); LCharHeigth := Form2.Canvas.TextHeight('W'); // LNewLabelHeight := HowManyLinesOnText(Form2.Width, LCharWidth * LTextLen); // Form2.Width := 300; Form2.Height := LNewLabelHeight * LCharHeigth; // Form2.Top := (Screen.Height div 2) - (Form2.Height div 2); Form2.Left := (Screen.Width div 2) - (Form2.Width div 2); // Form2.Label1.Top := 0; Form2.Label1.Autosize := false; Form2.Label1.WordWrap := true; // Form2.Label1.Left := 0; Form2.Label1.Width := (Form2.Width - LCharWidth); Form2.Label1.Height := LNewLabelHeight * LCharHeigth; // Form2.Label1.Caption := MyText; // Form2.ShowModal; finally FreeAndNil(Form2); end; end; Â Â Edited December 15, 2022 by programmerdelphi2k 1 Share this post Link to post
PizzaProgram 9 Posted December 15, 2022 59 minutes ago, Lajos JuhĂĄsz said: you can use windows APIÂ DrawTextEx with format option DT_CALCRECT. Succeeded đ Â var R : TRect; ... function GetY(const TXT: string): integer; begin Windows.DrawTextEx( lbl_1.Canvas.Handle, PAnsiChar( TXT ), Length( TXT ), R, DT_TOP or DT_RIGHT or DT_CALCRECT, nil ); Result := R.Bottom; end; begin ... R := Rect (0,0, 500, 300); y_ALL := GetY(myText); ... That was the key. Share this post Link to post
PizzaProgram 9 Posted December 15, 2022 13 minutes ago, programmerdelphi2k said: try my sample:Â Form2 with a TLabel for receive the text... Â Thank you very much, I did it similarly too đ Share this post Link to post