Any way to debug and see the form at the same time? lazarus / 12-Debugger ---------------------------------------------------------------------- old_DOS_err · 2025-11-17 09:33 Hi form gurus, Forms are not my forte. I'm testing a project, mostly working now, just trying out the resize. I have everything set up, but one of my values is out. The problem is that I really need to be able to see the form and the breakpoint to the code at the same time. Also noticed that the breakpoint is causing problems with the form and resetting the resize. So is there a way to run the debug and the form in parallel? I suspect not. But one can ask. Just so you know, I am experienced in debugging (was doing that before Windows was a glint in Bill Gates' eye, I used to insert C3, Int 3, DOS breakpoint directly into exe files loaded into DOS debug, ah, the 80s was fun). Phil ---------------------------------------------------------------------- Thausand · 2025-11-17 09:38 Quote from: old_DOS_err on November 17, 2025, 10:33:55 amJust so you know, I am experienced in debugging (was doing that before Windows was a glint in Bill Gates' eye, I used to insert C3, Int 3, DOS breakpoint directly into exe files loaded into DOS debug, ah, the 80s was fun). If is (w)intel https://forum.lazarus.freepascal.org/index.php/topic,71218.0.html Regard see form. I debug then step and when form is update then form go to front debugger and see form. Not for you ? ---------------------------------------------------------------------- Martin_fr · 2025-11-17 10:00 Depends a lot on what you mean by "see the form". If you place the IDE Windows to a different part of your screen (not using docking helps in this case) then the form stays "visible" when you hit a breakpoint. Of course assuming the form has already been shown. However, while at the breakpoint, and while single stepping, the form remains frozen. => Even if run outside the debugger, all the changes your code makes, are only applied after your code has returned (and the Lazarus code has taken over again). You can apply (some) changes early with "Form1.Repaint". If you call that, and step over it in the debugger (and have the IDE windows placed, so they don't hide the form) then that should apply some updates (but only once you step over it). You can also see the designer (the editable form in the IDE) while debugging, if that is what you meant. But changes to this, will not be applied to your running app/form. For that the app must be stopped, and recompiled, and then run again. ---------------------------------------------------------------------- cdbc · 2025-11-17 10:00 Hi Hmmm... How about adding a tlabel to your form and then write the value you want to watch, to it, when the app-flow passes by...? ...Or you can write a timestamped logfile. while running the app. Sometimes I have to go "Low-Tech" on its ass to get what I want  If on *nix/nux then you can ofc. use 'writeln' and watch your stuff in a terminal... Regards Benny ---------------------------------------------------------------------- Martin_fr · 2025-11-17 10:15 Quote from: old_DOS_err on November 17, 2025, 10:33:55 amAlso noticed that the breakpoint is causing problems with the form and resetting the resize. So is there a way to run the debug and the form in parallel? Not sure, what problems you mean? Well, if you are on Linux (Gtk2) then breakpoints in certain events (mouse, menu) can freeze the desktop (including the IDE, and with that the debugger). That is an issue with GTK2. You can run the IDE and your app (in the debugger) with the command line param --sync You can also set breakpoints that don't pause. You can do that for the above "sync" issue, or for any other reason. If you edit a breakpoints property, you can - uncheck the "break" checkbox - check the "take snapshot" checkbox Then the debugger will pause very briefly, record the stack window, locals and watches (top stackframe only), and keep running the app. Mind you, you will notice the slowdown, e.g. if you are resizing the form. But the focus wont be taken of the form, so your mouse will keep resizing the form (rather than the IDE getting focus, and the grip on the resize being lost). You can then later use the menu: View > Debug Windows > History : to see a list of all recorded breakpoint hits. (the default view shows the last 30, but the camera icon switches to the "snapshots" which contains all of them (if "take snapshot" was enabled). On top of that you can break only when certain conditions are met. See the condition field in the breakpoints properties. ---------------------------------------------------------------------- old_DOS_err · 2025-11-17 10:38 Thanks for all the replies. Sorry, should have mentitioned that it is in Windows 10. It is a subform (it's a library unit I'm writing using a TFrame). I can get Windows to display both forms from the task bar. But I cannot step into the subform when at the breakpoint, but I can step into the main. I last did Turbo Pascal back in the 90s, before a long time out. I know I've had to insert Windows specific code before, or change the way my program is structured to get things like minimize and restore to work. I started programming again a few years back, but I still think as a low level, linear programmer. Forms always catch me out. @Thausand I did not understand what you meant by "front debugger", was that something specific or a general reference? Quote from: Martin_fr on November 17, 2025, 11:00:03 amHowever, while at the breakpoint, and while single stepping, the form remains frozen. => Even if run outside the debugger, all the changes your code makes, are only applied after your code has returned (and the Lazarus code has taken over again). It would seem to imply that it is not possible. Hi Benny, yeah, I've done similar with this and may be the only way, I hajacked a button and using a simple TStringList, created a report of the class, and saved to file. I was just hoping there might be a more interactive way, especially as it only occurs in resizing. @Martin_fr thanks for the info about the history, that's one to look into. As for the problem, I dragged the window horizontally so it was reduced, I have a set of buttons, basically a tab system, then I noticed that from the breakpoint, if I minimized Lazarus, I had the frozen form, but it was now at its original size before I dragged it and it hit the breakpoint. So it appears the version Windows is showing is not the same version Lazarus is seeing, but I don't know anything about the underlying structure of either as to speculate (we're not in DOS any more). Phil ---------------------------------------------------------------------- Martin_fr · 2025-11-17 11:33 Quote from: old_DOS_err on November 17, 2025, 11:38:11 amSorry, should have mentitioned that it is in Windows 10. It is a subform (it's a library unit I'm writing using a TFrame).- Library as in "library.dll"? - Or Library as in "library of units", e.g. a package? If the latter (package) ensure that you enabled debug info in the package's options. Same applies if you try to step into the LCL (though that should have debug info by default, but if that got changed then you need to enable it again, if you want breakpoints in e.g "unit Forms" from the LCL. If a dll then that should work too.... Well, debugging wise. Creating forms/frames in dll may need a few extra steps => making sure they use the same memory manage as the main app, but more important, the same TApplication instance, and not sure what else.... Debug wise, .... Make sure you compile both - your app - your dll with debug info (and both with some version of DWARF) Disable "external debug info" (for both: app and dll) Ideally make sure to use the FpDebug backend (Tools > Options > Debugger backend). Though gdb should work too, but generally gives lower quality results... Do you statically link the dll? or do you use LoadLibrary? Then, if you set a breakpoint in a dll => which color (and icon) does it take (when the app is running)? It should be red, with a checkmark ("V") on it. If it has an "X" on it, there is a problem. If it has 2 bars (pause "||") on it, then - If you use LoadLibrary, that is ok, UNTIL the LoadLibrary was executed. The breakpoint can't be set, until the lib is loaded - If statically linked, or LoadLibrary was called, then there is some problem. If you have units that are compiled into both (the app and the dll) then I am not sure, never tested that... But the frame in your dll should have a unit that is only in the dll? So that is where you can check if breakpoints work. (you can also check that/if this units shows the small blue dots in the editors gutter (side panel)). ---------------------------------------------------------------------- Handoko · 2025-11-17 11:43 Quote from: old_DOS_err on November 17, 2025, 10:33:55 amI have everything set up, but one of my values is out. The problem is that I really need to be able to see the form and the breakpoint to the code at the same time. Also noticed that the breakpoint is causing problems with the form and resetting the resize. Not exactly what you want but you can try what I usually do. 1. Send the value of the variable to form's caption Insert this line in where you want to check the value:   Caption := AnIntegerVariable.ToString; For example: Quote  Caption := Mouse.CursorPos.X.ToString + ' | ' + Mouse.CursorPos.Y.ToString; 2. Create a non-modal form and put a TMemo in the form Then you can log the variable changes to the memo. 3. Write yourself a debug module I wrote myself a debug module. I send the variable to procedure, to where I can choose to display to: - Application.MainForm.Caption - An auto-created non modal form (popped up automatically when needed) - OS-depended baloon object This module has feature to suppress repeated same values (more than 3 times won't be showed). And because I made use of Pascal overloading syntax feature, I can send any variable type to the procedure, it even supports array of const. Planned but haven't implemented, I want to make it able to log the debug information to a log file. So far this is the interface section: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure ShowInfoToBalloon;procedure ShowInfoToForm;procedure ShowInfoToTitleBar;procedure ShowInfo(const Text: string; const Caption: string = '');procedure ShowInfo(Value: Boolean; const Caption: string = '');procedure ShowInfo(Value: Int64; const Caption: string = '');procedure ShowInfo(Value: QWord; const Caption: string = '');procedure ShowInfo(Value: Extended; const Caption: string = '');procedure ShowInfo(Value: Pointer; const Caption: string = '');procedure ShowInfo(const Info: array of const);  To me, TFrame has many disadvantages, instead I use form-in-form. ---------------------------------------------------------------------- old_DOS_err · 2025-11-17 11:55 Hi @Martin_fr, really sorry my poor use of terms. Yep, just a standard unit (I'd be more at home with the DLLs). I'm used to saying library as a set of tools one has built up. It is a major weakness of mine, trying to explain myself clearly, being extremely out of date doesn't help. I looked at your history, suggestion, whilst not what I required, it did show me that I have really not looked into Lazarus debug options at all and have only scratched the surface. I will have a play around with those. I assume that if just a standard unit, that it would come under the umbrella of the project debug settings. Are there additional settings or code to make a unit behave in a different way? ---------------------------------------------------------------------- old_DOS_err · 2025-11-17 12:11 Thanks @Handoko for the reply. I'm a boring DOS man, I just send mine to a text file and open with notepad++. The less I have to think these days the better, I hate getting old, physical slowness I can live with, slowing down mentally is tough for someone who has spent their whole life thinking and problem solving. Yeah, took me a while to get around the problems with TFrames, but by and large I get them to do the job. The main thing I found was creating manual versions of Create and Destroy and ensuring I called them once and only once (flags are a programmer's best friend). Are form-in-forms a separate class or just a subform embedded somehow? Sorry, probably a really stupid question, but as I say, forms are a mystery to me. ---------------------------------------------------------------------- cdbc · 2025-11-17 13:12 Hi There's also the 'DebugServer' & client, here's the readme:QuoteThe debug server is a simple program that listens for debug messages, and displays them in a list. The messages can be saved, cleared, it can be paused - whatever. It is the server part to a standard FPC unit - dbugintf. This unit offers a simple API to send messages to a debug server (using simpleIPC), modeled after the GExperts GDebug tool for Delphi, with some minor enhancements. Typical usage is as follows (I stripped actual code and {$ifdef debug}): uses dbugintf,sysutils; Procedure BackupFile(FN : String); Var    BFN : String; begin    SendMethodEnter('BackupFile');    BFN:=FN+'.bak';    SendDebug(Format('backup file "%s" exists, deleting',[BFN]));    SendDebug(Format('Backing up "%s" to "%s"',[FN,BFN]));    SendMethodExit('BackupFile'); end; Procedure SaveToFile(FN : String); begin    SendMethodEnter('SaveToFile');    BackupFile(FN);    SendDebug('Saving to file '+FN);    SendMethodExit('SaveToFile'); end; There are some more methods; see the FPC dbugintf help for that. It is extremely useful when debugging GUI code with lots of events - because you see the messages as they are sent, in a separate window which can be kept 'on top'. It can also be used to debug server (e.g. daemons, services, CGI) applications. The indentation of the messages (by SendMethodEnter) is intentional: if an exception occurs, then the SendMethodExit does not happen, and you see that something is wrong visually. ------------------------- Icons used by this application were provided by Roland Hahn (https://www.rhsoft.de/) under Creative Commons CC0 1.0 Universal License (freely available, no restrictions in usage). It's located here: .../lazarus/tools/debugserver Quite a nifty bit of kit  Regards Benny ---------------------------------------------------------------------- Martin_fr · 2025-11-17 13:16 Quote from: old_DOS_err on November 17, 2025, 12:55:20 pmHi @Martin_fr, really sorry my poor use of terms. Yep, just a standard unit (I'd be more at home with the DLLs). I'm used to saying library as a set of tools one has built up. Perfectly fine use for the word. But human language just has ambiguity... QuoteI assume that if just a standard unit, that it would come under the umbrella of the project debug settings. Are there additional settings or code to make a unit behave in a different way? Yes... But, let me ask how you use it. In the below the word "package" should always mean "a lazarus package / lpk". That is, if you have a library (aka collection) of units, then I guess you use it for several projects? So do you have it in some folder, and add that folder to your project's path settings (the IDE would ask you if it should do that, when you add the unit to the project (not open it, but add it). Ok, one step back, to much terminology. You have your project, in folder c:\foo. If you open the "Project inspector" the files are listed there. You have your unit from the collection C:\mystuff\frame.pas You can open it in the editor => but that does not add it to the project You can add it to the "uses" in one of your other units: afaik/iirc "uses frame in 'C:\mystuff\frame.pas'; " => but that does not add it to the project "not add it to the project"  => it wont be listed in the files of the project inspector  => the IDE will not (always) deal with it, e.g. make sure it gets recompiled when it changed So in the project inspector: "add" it. Then you get ask about the path being added, and the uses does not need "in c:....." (Or really better: Invest time, and learn how to put your unit- collection into a package). Of course you can add the path to the project without adding the file... And then, if it is in a package => make sure the path is not added to the project. In any case if the file is not in a package, then the project build settings (debug info) is used for the file. But the compiled result of the file may be outdated, and still be according to an older setting. (to remedy that, search all folder for .ppu files (and .o file) of your unit, and remove those. If you found more than one ppu for the one unit => there is something really bad in your setup. You can always see if the file has debug info, by checking for the blue dots in the gutter. That is kind of the first thing to check - Has blue dots? - Breakpoint are red, and get a checkmark "V" when the debugger runs? ---------------------------------------------------------------------- Martin_fr · 2025-11-17 13:19 If you are looking for live values, while you interact with the form (e.g. see some data, while you resize it, or drag it with the mouse, or type....) On WINDOWS: The best way is to compile your app with -WC (or in the Project settings, disable "GUI app"). Your app will run with all the forms as usual, but also open a console window. Then you can put "writeln" in your code (or use "debugln" from unit LazLogger / that also can go to a file, that you can tail -f then). ---------------------------------------------------------------------- Martin_fr · 2025-11-17 13:19 If you are watching a specify value, because you want to know when it changes => watchpoint (aka data breakpoint). It will stop, when the variable is written to. ---------------------------------------------------------------------- Handoko · 2025-11-17 13:32 Quote from: old_DOS_err on November 17, 2025, 01:11:35 pmAre form-in- forms a separate class or just a subform embedded somehow? Sorry, probably a really stupid question, but as I say, forms are a mystery to me. I forgot what exactly are the disadvantages of using TFrame. After I tried form-in-form approach, I abandon TFrame totally. Try it yourself maybe you will agree with me. Form-in-form requires no rocket science. For example you can see in the screenshot below is a multi-client chat program I designed using form-in-form approach. The left and right sides are exactly an ordinary TForm embedded into 2 panels in the mainform. In the mainform, drop 2 TPanel and a TSplitter onto it. Create the subform (using TForm) and name it frmChild. Then the code in the mainform should be like this: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i uses  Classes, Forms, Controls, ExtCtrls, frmChild; // ... procedure TForm1.FormCreate(Sender: TObject);begin  Constraints.MinWidth        := 520;  Width                       := 640;  Splitter1.Align           := alNone;  Splitter1.Left              := 500;  Panel1.Align              := alLeft;  Panel1.Constraints.MinWidth := 260;  Panel1.Width                := 300;  Splitter1.Align             := alLeft;  Panel2.Left                 := 800;  Panel2.Align              := alClient;  Panel2.Constraints.MinWidth := 260;  with TChildfrm.Create(Panel1) do  begin    Parent := Panel1;    Show;  end;  with TChildfrm.Create(Panel2) do  begin    Parent := Panel2;    Show;  end;end;  Do as what I said and if you put the code correctly, ta-da ... it works like magic. ---------------------------------------------------------------------- LeP · 2025-11-17 13:34 I'm talking about Delphi (but not only that; it's the same with other debuggers like Windbg) in both 32- and 64-bit. The only way I can synchronize the debugger with graphics (any graphics, whether modal windows or dialog boxes) is to use a secondary monitor. I debug with the primary monitor, and the application uses the secondary monitor. After years of struggling, this has solved all my debugging problems, starting with Windows 7. ---------------------------------------------------------------------- old_DOS_err · 2025-11-17 13:55 Wow, ok, thanks Benny, worth looking into. I would have thought it was quite common to have GUI issues or code doing strange things due to the way forms behave (like being surprised how many time owner draw method is called in a listbox). I'm still trying to trace the bug, I know from experience I've done something stupid, but because it only shows during the resize testing, it's tough. It's like training a dog, you can't tell it off after it has done something wrong, you have to catch it mid-event. Thanks @Martin_fr, that looks really helpful. I didn't know about stopping on a variable change, will definitely explore that. And thank you for the clarity on the units, yep, I was doing it the wrong way, just putting it in the uses clause. It is just a single use function, I have a tendency to build a large collection of 'library' codes, from very simple inline to drop-in subforms (TFrames - though I will have a look at Handoko's idea). I had no idea about adding them to the project. I've gone on the policy since I started many moons ago, if it works, just be thankful and don't ask questions. Thanks for the reply @Handoko, again, something I had no idea about. I knew from previous searches TFrames didn't seem very popular, but I didn't know what people used instead. Thank you everyone, I feel like a kid on Christmas morning, stupid I know, but it is really nice when people put time and effort into making these replies. Phil ---------------------------------------------------------------------- old_DOS_err · 2025-11-17 14:04 Interesting way of doing it @Lep. Can that still be interactive? For example, if you are running your form, and you have the code open on another, can see the data live if you hover the mouse on it, or if the code hits a breakpoint, can you do anything with the form, like resize it. Even as write that, I feel I'm answering my own question. I think that is a level of interaction that is the holy grail, but I would love to be proven wrong. If AI can make a believable talking yeti, then anything is possible. ---------------------------------------------------------------------- Handoko · 2025-11-17 14:08 Quote from: old_DOS_err on November 17, 2025, 02:55:07 pm... it is really nice when people put time and effort into making these replies. If you aren't busy you should visit this forum frequently. Even you have nothing to ask, you always can learn something new simply reading the posts. People here like to share tricks and knowledge obtained from years of using Lazarus/Pascal. ---------------------------------------------------------------------- LeP · 2025-11-17 14:41 Quote from: old_DOS_err on November 17, 2025, 03:04:59 pmInteresting way of doing it @Lep. Can that still be interactive? For example, if you are running your form, and you have the code open on another, can see the data live if you hover the mouse on it, or if the code hits a breakpoint, can you do anything with the form, like resize it. Even as write that, I feel I'm answering my own question. I think that is a level of interaction that is the holy grail, but I would love to be proven wrong. If AI can make a believable talking yeti, then anything is possible. P.S: [EDIT] of course, you cannot view a live data without breakpoints. Only with breakpoints you will see any data. If you want to see in live action, do a "writeln" with your datas to a windows console attached. Yes, while debugging, you can see everything (or almost everything). The only thing you might have trouble with is mouse management... when the debugger enters, the mouse moves from the application to the debugger, so whatever you're doing when you restart from the breakpoint, it stops (the mouse operations, for example, resizing). Honestly, I haven't debugged things like this in years; I don't think there are any "secrets" anymore. When I did it years ago, I used Delphi's remote debugger: it allowed you to remotely debug the application (on two different systems), so the debugger didn't interact graphically with the mouse or anything else. Use this in your FormCreate event, and if there is a secondary monitor your application will showed on this (it's for Delphi but should works in Lazarus too): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   var i: integer;  ......  if Screen.MonitorCount > 1 then    begin      for i := 0 to Screen.MonitorCount-1 do        begin          if (not Screen.Monitors[i].Primary) and (Screen.Monitors[i].Left = Screen.Width) then            begin              Top := Screen.Monitors[i].Top;              Left := Screen.Monitors[i].Left;              //MakeFullyVisible(Screen.Monitors[i]);              break;            end;        end;    end; ---------------------------------------------------------------------- old_DOS_err · 2025-11-17 14:53 @LeP thanks for that info. I do have an old, but working monitor right next to the main one (currently attached to a Lenovo that probably would be out-performed by a BBC micro). So wlll try to explore that, would be a good excuse anyway, only time I ever do 2 monitors is if I have to use a laptop (I attach keyboard, mouse and monitor, and voila, no longer mobile). ---------------------------------------------------------------------- Martin_fr · 2025-11-17 16:00 Quote from: old_DOS_err on November 17, 2025, 03:53:25 pm@LeP thanks for that info. I do have an old, but working monitor right next to the main one (currently attached to a Lenovo that probably would be out- performed by a BBC micro). So wlll try to explore that, would be a good excuse anyway, only time I ever do 2 monitors is if I have to use a laptop (I attach keyboard, mouse and monitor, and voila, no longer mobile). IMHO multiple Monitors help a lot with working on code, debugging, and more... Especially, if you use a docked IDE and that will occupy one screen by itself, and you can't spare a corner for the running app, that you want to debug. The crux is (IMHO) that a docked IDE is something you start to need, if you have a single screen, because then you have so many IDE Windows that they don't fit the space you have. And then, if you have only one single screen, the docked IDE makes it a lot harder to have some spare space for the app to run... I only use docking on my laptop, and I don't do much serious work on it, otherwise I have several screens and space enough for all the IDE windows **and** any app I am running. So, if you have a spare monitor, even if it is old and the quality may not be good, use it. If you debug your app on it, it shouldn't matter that is may not have the best contrast or lower resolution, or slow pixel switching times ... Quote from: old_DOS_err on November 17, 2025, 03:04:59 pmFor example, if you are running your form, and you have the code open on another, can see the data live if you hover the mouse on it, or if the code hits a breakpoint, can you do anything with the form, like resize it. Even as write that, I feel I'm answering my own question. I think that is a level of interaction that is the holy grail, but I would love to be proven wrong. If AI can make a believable talking yeti, then anything is possible. There is no "live data". Data only gets loaded when the app is paused (at a breakpoint / single stepping / ...). And when the app is paused you can't interact with it (you can't click buttons, or change the size). Partly that is actually dictated by the "data" itself. NOTE: the below is "in theory". What could be added to the debugger, and what could not. But the below is not currently implemented. Lets start with local vars, they only exist while inside a routine. But to interact with the app, the app must run => so the app will be in different routines all the time. It be 10 millisecond in one routine. There wouldn't be a point to show the data for 10 millisecs. Global vars of course exists all the time. It would be possible (as a feature that has not yet been added) to watch a global var, by pulling the value every 50 millisecs. Fields (in object, e.g. fields of a form or frame) are a middle ground. The are like locals, if the object is a local. If the object is global, and you specify the full name from that global var => and if that feature was implemented (which it is not), then that could be done. Of course that would likely by of limited use. The value could change several time in such short intervals, that you would not even be able to see that it changed several times (or changed at all, if it changed back immediately). And if the value gets updated "on a timer" (e.g. the debugger checks ever 50millisecs) then the debugger may even miss that it changed. Of course the debugger could use the "value changed" notification (which is used for "data breakpoints"). But only 4 values (and only up to pointer size) can be monitored like this.... So, "live watching" would have a lot of limitations. Anyway as it stand now, you can only see values while paused. The usual approach is to single step, and monitor the watch you are interested in, as single stepping will pause at each statement, and therefore give you updates. But if you don't know where approx you need to debug, single stepping may not be a solution (no one would single step 1000 steps...) Then you can use watchpoints. If you know which value should change => set a watchpoint. (you can combine that with the history / if you don't want to pause the app completely when it happens) ---------------------------------------------------------------------- 440bx · 2025-11-17 16:39 First, I want to second (pun intended) all the recommendations about having a second monitor.   It really makes life a lot easier in many ways, debugging among them. That said, there are some cases where even having more than one monitor isn't helpful and, that's when the code that needs to be debugged is executed in real time as a result of mouse movements.  That's the one case where normal debugging doesn't cut it.  Fortunately, there is a solution: make the program a console program by adding {$APPTYPE CONSOLE} at the top of the .lpr file then, simply place writeln instructions to output whatever values are of interest onto the console.  This way, the results of moving the mouse can be inspected in the console window.  If necessary, right click on the console title bar and set  the screen buffer size to 9999.  That will usually be sufficient. Using a console allows tracing any value in real time, which is sometimes necessary.  One unexpected and advantageous side effect of logging to a console window is that is slows down the repainting in the GUI program.  This can sometimes be very useful in uncovering a bug. HTH. PS: the ExtTextOut.7z file attached to the post at: https://forum.lazarus.freepascal.org/index.php/topic,53791.msg398390.h tml#msg398390 is an example of how to do this.  It tracks the values of the mouse in real time as the GUI window is resized. ---------------------------------------------------------------------- old_DOS_err · 2025-11-17 18:37 @Martin_Fr Thank you. I like the analysis of the live data issue, as I noted even as I typed the question I relialised I was being a bit of an idiot. @440bx Thank you, that looks fascinating, I downloaded that link. I've only recently started using the $define structure in some of my units to create debug code, nothing sophisticated, just adding lines to a TStringList. It feels quite exciting, a new challenge. It will take me several days to go through this lot and implement stuff, sadly speed is something I can only reminisce about these days. Phil ---------------------------------------------------------------------- cdbc · 2025-11-17 19:29 Hi Attached is a snapshot of a 'Live' debug-session....  Regards Benny ---------------------------------------------------------------------- old_DOS_err · 2025-11-17 19:48 Thanks Benny, always helpful to have a "This is what it should like." BTW, I did use your label suggestion, although the TFrame sits snugly inside the parent panel, because I'm in a testing program, the parent had a spare label, so just put a TLabel into the TFrame and linked them. Then I could see the relevent values as I dragged the window left and right. They were as expected. So I'm still puzzled about why my program is not behaving correctly on resizing. Hey ho. I'm off to shove more things in the label. Basically I'm using TArrrow for scrolling with a set of home made tabs, these work fine when I just add or remove tabs (it has a trim feature), but on the resize, the arrow is not showing, I checked the Left and it was adjusted correctly, I put the breakpoint where I turn the arrow on, all good. But still the arrow doesn't show. There are times I find programming soo frustrating. ---------------------------------------------------------------------- Martin_fr · 2025-11-17 19:57 Well, one idea that could be done (not sure when...) The watches window could keep the last value visible, when the app continues. Currently it goes back to "invalid", because while the app is running, the value could be anything. So showing the last known value is technically wrong. But, showing the last know value would be useful if you have a breakpoint that continues automatically. The app would pause, but for a few millisecs only. The watches would be evaluated, and while the app runs again, the user could still read the values. I had for a while the idea to "fade out"  the values, in order to reduce flicker when stepping => That is most single steps take only a few ms, if the watches would wait 100ms before clearing (or fading) the values, then during stepping the reset to "invalid" would not happen. Of course keeping the last value would solve that too. Or could be combined, fade to a slightly diff color as indicator that the value is "old". Question then is, when the debug session ended, how long to keep the last set of values? Because IMHO when the app has stopped entirely then it should be cleared. (as code will be edited, and values become pointless) / And they can be viewed on request using the history, which is only cleared when starting the next debug session. Well, for now this remains on my todo, one way or another. ---------------------------------------------------------------------- old_DOS_err · 2025-11-17 20:41 I was wondering about coming in the from the other end, so to spreak. Instead of trying to work out what the system is doing, which was hard enough in MSDOS on an 8086, for those really hard to solve problems that defy all logic, create a simulator. It would be very slow, but for the one-offs it would be fine. Then the simulator creates the forms and is in control of the data, it could emulate things like scope and range checking. I live in a world where I have a thousand ideas, where not even the most basic will ever see see the light of day. Cue violin music, fade to black... ---------------------------------------------------------------------- Martin_fr · 2025-11-17 21:22 Quote from: old_DOS_err on November 17, 2025, 09:41:14 pmI was wondering about coming in the from the other end, so to spreak. Instead of trying to work out what the system is doing, which was hard enough in MSDOS on an 8086, for those really hard to solve problems that defy all logic, create a simulator. It would be very slow, but for the one-offs it would be fine. Then the simulator creates the forms and is in control of the data, it could emulate things like scope and range checking. My first thought (ignoring your dos references) would have been that you may come from scripting (like javascript). Because there you have the interpreter, and it can hook better into the app than traditional debuggers can (at least without to much slow down). About "simulating" => I don't think that is practical. There is something close to that, but for a totally different purpose. Actually not a simulator, but a tool that single steps your entire app without you need to do anything:    valgrind  (Linux only) One of its uses ( -tool=memcheck ) is to find: memleaks, out of bound access, access after free, .... However, if you use it your app will be crawling slow. But it is a good way to find those kind of errors. Another approach of debugging (but Lazarus does not yet have it, I don't know if you can do it with raw gdb from console... maybe/ maybe not): "Back in time debugging" or "reverse stepping" The debugger will again single step everything (takes lots of time), and record everything (at a much higher level of detail than the History in Lazarus). But when you pause anywhere, then you can go back on the timeline (like in a movie editor). You can see the app (not visually, but the data) at any time. You can search when a variable had changed, and stuff like that. Well, we are very far from having that, not sure if we will get that at all. ---------------------------------------------------------------------- Thausand · 2025-11-17 22:00 Quote from: old_DOS_err on November 17, 2025, 11:38:11 am@Thausand I did not understand what you meant by "front debugger", was that something specific or a general reference? I sorry for broken english. Other users write more better grammar for explain (and have explain, so thank). For clarify: When debug application then is present 2 forms. 1 for application and 1 for debug (debugger can have more but for keep simple example). When make step in debugger then debugger make show source step (source-code is front). When code is make update to form for application then code is execute and make application form 'move' to front of debug window and make show update (draw line, draw text, refresh etc). When form finish draw (refresh) then debug window is 'move' to front. It is switch front-back-front ad infinitum (ofc it stop wen application is stop/finish  ) That why other users also write make change for form (example, make update visible component) then form is refresh and show window place 'on top' (=front) debug window (debug window = back"). That back and front explain. I sorry if not clear when first write. ---------------------------------------------------------------------- old_DOS_err · 2025-11-17 22:27 At the risk of being burnt at the stake by the programming community, I think that subtle debugging may be a valid use of AI. I did a tiny bit of program slicing back in the 90s, an interesting idea, semantic checking is a lovely goal. Afterall, what is the job of a computer if not to run through huge volumes of data and make connections that would drive a human insane. It feels odd in a way that we are still relying on an area humans are not strong in, to create programs to make life easier for others. In a few recent google searches, for example drawing a polygon for my tabs, the AI came back with snippets that were actually useful. I know that is a whole other discussion, I noted the Chat GPT subject but not my area. But I think it is a realistic choice now, to put the work in to build better debugging tools as the size of projects grow, or look at using an area where computers are actually more suited. But in the meantime, yes, I think this sort of trail would be very useful. I assume you meant a time line, like say Windows Media Player or youtube, whereby the programmer could have the relevant data in a window and the time line is the duration on the run. Then by simply dragging the mouse (keyboard options), one could get a snap shot of the program at any given (integral) point. I don't think that would be that difficult, for example I used the stringlist to record the data of my program at key points, but the thing is when looking at the text file after, it really didn't mean anything to me, because I couldn't put it into context of what happened in the run just before. The slider is nice and easy. @Thausand thanks for clarifying. No worries, I am English, but have trouble explaining myself, so I can empathise. This is why others have suggested a second monitor, which makes a lot of sense, to get around the to and fro problem. I hope I understood what you were saying. ---------------------------------------------------------------------- Thausand · 2025-11-17 22:43 @old_DOS_err: Yes, you have make good understood. Have 2 monitor (or more) is very good solve (and then no have problem back/front, then have problem look left/right and up/down) ---------------------------------------------------------------------- LeP · 2025-11-18 08:29 A thought of mine, perhaps off-topic, on debugging. Debugging is an art. It's not complex, but it requires a lot of imagination and technical knowledge, as well as having the right tools. Debugging is simple, but effective debugging is not. Many rely on breakpoints, but these are only aids for analyzing a specific "component": is it better to have an effective and complete "stack trace" or see a limited snapshot? And can a profiler help with debugging? You see, let me make a comparison with the universe... when we observe "Proxima Centauri," we see a star, but in reality, we're seeing what happened many years ago (about four and a half years ago) and we're observing history. If we could see a truly current "snapshot"... who knows, maybe "Proxima Centauri" no longer exists. So in debugging, sometimes it's more important to see the "history" than a snapshot..... ---------------------------------------------------------------------- old_DOS_err · 2025-11-18 10:51 @LeP, deep man Update: All my values seemed correct, the program was doing what it should do, but still the right arrow wasn't displaying. Using the passive breakpoint mentioned by @Martin_fr, it showed the line to make it visible was hit numerous times in the resize. Additional adds to the label mentioned by Benny, showed something odd with ClientWidth. At one point it froze and did not update as the width was changed. In general it seemed this value was too high, I use the width to determine where the right arrow would go, choosing to place it just inside the right edge of the frame rather than at the end of the tabs. Anyway, because of my low level history, I still tend to do everything manually. This can sometimes lead to problems, especially with forms. In looking up issues about resizing problems, I found it recommended to change over to Align = alClient, it was alNone. Had to rejig a bit and put an OnResize into the frame (the way it had worked was the OnResize of the parent form had a call to a manual resize method). This has made the program behave rather differently and I need to re- evaluate this change. So, it will take a few days to look further into the avenues brought up here. Thanks again to everyone who contributed. Phil ---------------------------------------------------------------------- Martin_fr · 2025-11-18 12:06 Quote from: old_DOS_err on November 18, 2025, 11:51:57 amI use the width to determine where the right arrow would go, choosing to place it just inside the right edge of the frame rather than at the end of the tabs. QuoteI found it recommended to change over to Align = alClient, it was alNone. Had to rejig a bit and put an OnResize into the frame (the way it had worked was the OnResize of the parent form had a call to a manual resize method). This has made the program behave rather differently and I need to re-evaluate this change There may be another solution to your problem.... But, I do recommend to keep debugging it, for the sake of learning. If you need to watch values/changes of a particular object, then conditional breakpoints may be useful. E.g. if you set a breakpoint in TControl.ChangeBounds or other methods in the LCL that are used by many controls. You may just be interested in calls for a specific control (the shape displaying your arrow). Use a watch to get the value for    pointer(self) Then in the breakpoint add the condition (replace the number as found by the watch)    pointer(self) = $5101234 And the debugger will only stop if that condition is true. Using "align" and other properties may indeed be a better way. If you need the arrow to be at a fixed distance from the RIGHT EDGE of its parent, then you can 1) In the property Anchors, set the value akRight and remove akLeft. Then it will move with the right side of the parent 2) Better: Open the AnchorEditor (the "..." on the Anchors property)   For the left anchor    - UN-set Enabled   For the right anchor    - Set Enabled    - select the parent as Sibling    - select the button "Anchor right side to right side of sibling"    - Set the distance in the spin edit And the control will be fixed there. You can access those values from code, e.g.   Button1.AnchorSide[akRight].Control :=;   Button1.AnchorSide[akRight].Side := ;   Button1.BorderSpacing.Right := And then you don't need any OnResize. If you need grid like layouts check "ChildSizing" ---------------------------------------------------------------------- old_DOS_err · 2025-11-18 15:25 @Martin_fr thank you, again. It's stuff like that that makes me realise I've hardly even scratched the surface with Lazarus and free pascal. I hadn't thought of trying the anchors, I'd got so into the mindset of fixing everything manually. I think that may solve the positioning problem with the right arrow. I still need the resize, as my tabs aren't straightforward (now there's a surprise), so they are redisplayed at every change. Good news is I have plenty of time at the moment, bad news is due to a major health issue, I don't have the stamina I used to. Anyway, back to the mill whilst my brain is half working.