Jump to content

PeaShooter_OMO

Members
  • Content Count

    97
  • Joined

  • Last visited

Everything posted by PeaShooter_OMO

  1. PeaShooter_OMO

    TButton: change font color

    @davornik BS_OWNERDRAW means you must do the drawing of the button yourself. You must also detect user interactions and state changes and respond to them visually. Here is an exmple of such a button (as @Remy Lebeau pointed out on Stack Overflow) : Delphi - Pascal Windows Color Button
  2. PeaShooter_OMO

    Mouse cursor

    I aplogize; I meant Firefox browser
  3. PeaShooter_OMO

    Mouse cursor

    @MMSoft I don't know if you are aware but your approach should foremostly be from a Web Development perspective. Any question you have about how to achieve anything related to your project should be evaluated to see if it is related to web developement or not. For instance; You wanted to know what the position of the page is relative to the scrolled area. That is a web development question and as such you should ask the question on Google for Javascript. In the Firebird browser there is an add-on called Greasemonkey. It allows you to write Javascript scripts that you can run on any website you choose. I do not know what you can use for Chrome, etc. So what you would do is you will ask yourself what you need to do, one step at a time, in this case find out the scroll offset of the currently loaded page. You will search on Google for a solution for that in Javascript. You will create a Greasemonkey script to do only that single step and then test it on your website via Firebird and Greasemonkey. This way you can quickly iterate possible solutions without having to try and build it into Delphi. Once you found the solutions to all your required steps then you build it into Delphi, worrying only about the aspect of getting your Javascript into the TWebBrowser or alternative and fixing whatever limitations the TWebBrowser might present. This obviosuly will require you to learn other developement tools but it is worth it.
  4. PeaShooter_OMO

    VCL UI Design Challenge for Delphi Developers πŸ’‘

    One of his challenge requests is: Resizable & smooth movement – The form should be fully resizable and draggable without lag If the form is to be movable then what is behind it and what would be coming through it via the blur/transparency will change thus the constant re-blurring. All this is moot. The OP started this challenge from a false or at least diverted premise which makes me question the motives. Unless the OP comes clean on what he/she wants I would not bother.
  5. PeaShooter_OMO

    VCL UI Design Challenge for Delphi Developers πŸ’‘

    Is that form resizable and draggable on the web page without third party frameworks? There are a few ways that I can think of that you can use to do this with pure non-third-party VCL. Many component authors will find this easy to do. If perhaps you are fishing for a solution then consider asking. Someone might even spend the time to show you.
  6. PeaShooter_OMO

    Disable all controls on panel

    That is correct. In your current situation Application.ProcessMessages serves one main purpose; To fix your queued windows messages issue. Rightfully so @Anders Melander mentioned that it is a way to fix that because it disposes of the queued windows messages that were destined for the disabled controls. But your code has the ability to produce another "artifact" and that is an unresponsive GUI while the lengthy operation is taking place (when the result of WaitFor takes a a little longer to arrive). Application.ProcessMessages where you placed it will not fix that because the possible occurance of a longer-than-usual WaitFor happens before Application.ProcessMessages. Your GUI will be unresponsive wile the WaitFors take place. As @Remy Lebeau mentioned; you can use Indy's TIdAntiFreeze to fix the unresponsive GUI issue but it only works while the WaitFor is being processed. So you can place the following into a thread (obviously with modifications to handle thread-safety and other things as required) : if fTCPClient.Connected then begin fTCPClient.IOHandler.WriteLn('set OutputType=ASCII_SHORT'); if fTCPClient.IOHandler.InputBufferIsEmpty then begin for i := 0 to 1 do myStr := myStr + fTCPClient.IOHandler.WaitFor(Char($0A), True, False, IndyTextEncoding_ASCII, 5000); end; end;ο»Ώ You have to remember that that thread will now leave your main thread and GUI free to continue and this will be evident in any Buttons, Menus, "interactions" being available for the user to click on unless you specifically disable them. You also have to have some result for the thread which means as soon as the WaitFors finish and you have your answer from the TCP then you should obviously react by passing the resulting String to the main thread, enable all that needs to be enabled again, continue with whatever you still wanted to do, etc.
  7. PeaShooter_OMO

    Disable all controls on panel

    Indeed. The Application.ProcessMessages at his chosen position does resolve his issue with queued messages though but because of my "buddy-buddy" feelings I have for threads I would have put that operation in a thread aspecially for the instances where he does not get a quick response from the TCP peer.
  8. PeaShooter_OMO

    Disable all controls on panel

    You have a good point. It basically disposes of the queued messages related to the controls which at that stage would be disabled.
  9. PeaShooter_OMO

    Disable all controls on panel

    If he puts the Application.ProcessMessages right before pnl3.Enabled := True; then it basically is the same as leaving it out because the two WaitFor calls have already taken place which means the lengthy operation is finished and btnWriteASCII_ShrtClick is already on its way out. As such the application will continue processing in anyway immediately after.
  10. PeaShooter_OMO

    Disable all controls on panel

    No, try and stay away from Application.ProcessMessages. Its a "poor-programmer's" response to an issue which can be fixed in a better way. In anyway, the Waitfor will negate Application.ProcessMessages where you put it. Common-rule-of-thumb is to put lengthy operations inside a thread to not adversely affect the main thread. The long Timeout on the WaitFor call makes it a very lengthy operation. (Changing the timeout length is not the solution either). Use a thread.
  11. PeaShooter_OMO

    Disable all controls on panel

    The OP is doing fTCPClient.IOHandler.WaitFor which will cause the execution of the main thread to wait on that call which will cause windows messages to queue and as soon as btnWriteASCII_ShrtClick returns the queued messages will be processed. To Disable all controls inside the panel is required if you want the visual aspect to correlate to the state
  12. PeaShooter_OMO

    LSP Rant

    I assume its still that you have to have logged a bug yourself before you are able to see other people's bugs?
  13. PeaShooter_OMO

    Event handler in thread

    @ErikT I can assure you it still is pretty much the same. The Main application loop has been created for you by Delphi and that is inside the Application instance of TApplication and its setup you will find inside the DPR file (Project Source file). It is similar to what you will find in the Arduino ecosystem where the "Sketch" file is basicaly abstracted from the actual Main loop. The guys from Arduino thought it best to provide newbies two procedures; "setup" and "loop" in a sketch but there is another piece of code that has a Main loop that calls Setup and then just loops the Loop procedure. Delphi's Main loop receives Windows Messages from the underlying OS. Almost like interrupts they inform the application what is happening in repect to hardware and OS related events. The Delphi Application instance will then act upon some of those messages or will send the rest on to all corners of its fiefdom and any object, window or control that wants to can have those messages and react. For instance a Mouse Move event in the OS will cause the OS to send a correlating message to the Application instance if need be. The Application instance will check who should get the messages and then pass it on. A Button might receive the message if it is found that the mouse moved over the button's area and then the button can redraw with a highlighted display to show that the mouse is over it. All these happen the whole time, in a loop the same as your Main loop checking and waiting for interrupts. Below is Arduino's main.cpp. You don't see this when you use the Arduino IDE. Just like Delphi. Threading is just an extension of this whole process that allows you to do mutiple actions that seems to be happening at the same time. In the old days of mono-core CPUs it was done in a way where the OS will give each thread a time slice which will make it look as if the threads did their thing at the same time but it was still a sequential process. Nowadays with multi-core CPUs each core will be doing that which means that a single core will be giving its own threads each a time slice but across cores many threads might really be running at the same time. In an environment like Delphi you can be totally unaware of most of this and still create a great application and never even encounter any of the behind-the-scenes code. But it is good to know how these things work because it broadens your ability to figure out why a bug is doing what it is doing. If your Delphi edition has the source code for the VCL and FMX then go into that code and check it out. #include <Arduino.h> // Declared weak in Arduino.h to allow user redefinitions. int atexit(void (* /*func*/ )()) { return 0; } // Weak empty variant initialization function. // May be redefined by variant files. void initVariant() __attribute__((weak)); void initVariant() { } void setupUSB() __attribute__((weak)); void setupUSB() { } int main(void) { init(); initVariant(); #if defined(USBCON) USBDevice.attach(); #endif setup(); for (;;) { loop(); if (serialEventRun) serialEventRun(); } return 0; }
  14. PeaShooter_OMO

    Event handler in thread

    It really is not that much different. I personally think Delphi can be much more alike to microcontroller programming than some other languages. You allocate memory, you remember to deallocate it. A good microcontroller programmer probably has that ingrained. You most probably have an advantage to those starting their programming career on multi-core, mega-memory, full fledged operating system computers; you are conscious about space and performance. Just like on microcontrollers there are ways of doing things in Delphi that might work but most of the time there are the correct ways to do things. You learn as you go. Threading is so cool once you get the hang of it, just like pointers. The main rule is; if it is not an atomic operation when accessing/changing some memory then you must be conscious about which thread is accessing what and when and whether changing it can cause another thread some issues. Read up on thread-safety if you have not already. Ask questions here as there are brilliant and very knowledgeable Delphi experts on this forum. Anders Melander being one of them.
  15. PeaShooter_OMO

    Event handler in thread

    Coming back to the threading; Remember that Thread-Safety is important and you need to be certain that the ComPortDriver does not do thread-UNsafe things.
  16. PeaShooter_OMO

    Event handler in thread

    The CommPortReceiveData member you declared is incorrectly declared and should be somethin like: (Note that the parameters should be the same as CommPortDriver1.OnReceiveData) procedure CommPortReceiveData(Sender: TObject; DataPtr: Pointeο»Ώr; DataSize: Cardinal); This should be a method of the class and in there you will handle the data you received. The way you did is not what you want and is what you would have done if you wanted an Event property to be added tou your class.. like so: private FOnCommDataReceive : TCommDataReceiveEvent public property OnCommDataReceive : TCommDataReceiveEvent read FOnCommDataReceive write FOnCommDataReceive; As a side note; try and use Delphi naming standards. Generally accepted, your class fields should have F prefixed to their names.
  17. PeaShooter_OMO

    TppIBOPipeline for Delphi 11.2

    @Sennerei You can contact Jason Wharton, the author of IBObjects. He is very helpful. There is an evaluation on the IBObjects site which you can download as well.
  18. PeaShooter_OMO

    Edge Webview2 Environment

    Can you elaborate?
  19. PeaShooter_OMO

    Edge Webview2 Environment

    Attached you wll find a sample project that works for me. It is a 32bit project. My Dev machine is Windows 10 with Delphi 11. I have a Windows 7 (64bit OS) machine around. It did not have Edge or the WebView2 Runtime installed on it and WebView2Loader.dll did not exist on it. I installed the runtime (32bit version) on the Win7 machine using what I downloaded from https://www.catalog.update.microsoft.com/Search.aspx?q=webview2 Runtime version 109 Windows 7 is only supported by Runtime 109 and older. For instructions on how to get the Runtime installed from the update catalog file: After the installation the WebView2Loader.dll still did not exist on the machine. I copied the WebView2Loader.dll I found in my Delphi installation under c:\Program Files (x86)\Embarcadero\Studio\22.0\Redist\win32\ to the executable folder and copied the EXE and DLL to the Win7 machine. It works there as well as on my Win10 machine. The runtime is important as it does not work without it. EdgeBrowserSample.zip
  20. PeaShooter_OMO

    Edge Webview2 Environment

    Yes. I do not set BrowserExecutableFolder at all and I make sure WebView2Loader.dll is located in the same folder as my project executable. I use Delphi 11 As a side note; above the BrowserExecutableFolder property declaration in the Vcl.Edge source it says "If the path contains \Edge\Application\ then the WebView2 creation will fail".
  21. @Darian Miller In times like these I just use pointers. Not sure whether that will affect the API interaction though. PRecordB = ^TRecordB; PRecordC = ^TRecordC; TRecordA = record Field1 : Integer; Field2 : PRecordB; Field3 : string; TopX : PRecordC; end; TRecordB = record Field4 : Integer; Field5 : TRecordA; end; TRecordC = record Items : TArray<TRecordA>; end;
  22. @o815 TAdvStringGrid does not have any functionality to satisfy your request, at least not as far as I can remember. You will have to iterate font sizes to do that. You can have a look at Canvas.TextHeight Canvas.TextWidth Canvas.TextExtent
  23. PeaShooter_OMO

    Set form in read only mode

    Another thing to consider is the visual aspect. When you disable a single control it may have a change in its visual representation as is the case with a button or an edit box that goes gray/grey and for good reason because that gives an indication to the user that it has been disabled. If you want that level of indication then you will have to disable each visually relevant control by itself. Disabling a parent container control does not affect the child controls visually. Disabling a few controls are easy and just a few lines but if you have many then you can loop through them and disable them that way. Have a look at the Controls and ControlCount properties of the parent containers (Form, Panel, TabSheet, GroupBox).
  24. PeaShooter_OMO

    TEdgeBrowser how to clear the cache

    I use TEdgeBrowser and it creates a sub-folder in the folder where my executable is outputted to. It is called <name of executable>.exe.WebView2 Many folders in it seem to be related to "Cache" Do you have such a folder?
Γ—