Jump to content

Anders Melander

Members
  • Content Count

    2935
  • Joined

  • Last visited

  • Days Won

    166

Everything posted by Anders Melander

  1. Anders Melander

    A smart case statement in Delphi?

    And how is that going for us? There are many, many ways of searching for occurrence of a string in a static set of strings, but hashing certainly isn't the fastest. Hashing is a generic algorithm that doesn't take strings' unique properties into account. A chatbot couldn't have expressed it better - whatever it is.
  2. Yes, you're probably right.
  3. Run the 32-bit executable in the debugger while specifying the 64-bit application as the host?
  4. Anders Melander

    Bug VCL I'm losing my TControls course ?

    At the moment, as far as I've been able to conclude from what you've written, the only lead you have, to the cause of the problem, is the OnExit pattern. If I were you, I would run with that and try to eliminate that pattern everywhere (because it's a bug in user code) it occurs. That can't be too hard; Either just search for OnExit/OnEnter and examine the handler code, or place a breakpoint in SetFocus and look for recursion. The recursion is likely what breaks the focus state. Good luck.
  5. Anders Melander

    Bug VCL I'm losing my TControls course ?

    That must mean that Windows' internal focus state has become messed up because Focused is implemented as: function TWinControl.Focused: Boolean; begin Result := (WindowHandle <> 0) and (GetFocus = WindowHandle); end; My guess is that Windows' internal SetFocus is implemented something like this: function WinApi.SetFocus(ANewFocusHandle: THandle): THandle; begin Result := FCurrentFocusHandle; if (FCurrentFocusHandle = ANewFocusHandle) then exit; if (FCurrentFocusHandle <> 0) then SendMessage(FCurrentFocusHandle, WM_KILLFOCUS, ANewFocusHandle, 0); // WM_SETFOCUS propagates to OnExit in Delphi SendMessage(ANewFocusHandle, WM_SETFOCUS, FCurrentFocusHandle, 0); // Update the internal focus state FCurrentFocusHandle := ANewFocusHandle; end; In Delphi, the WM_SETFOCUS message causes the OnExit event of the currently active control to fire. If you, in the OnExit handler then does something that causes the focus to change (e.g. activating another form) then the internal focus state will become invalid. So again, I suggest you focus your efforts on fixing the problem instead of working around it - large code or not.
  6. Anders Melander

    Bug VCL I'm losing my TControls course ?

    GetFocus & SetFocus if (MyEdit.Handle <> GetFocus) then SetFocus(MyEdit.Handle); or simply if (not MyEdit.Focused) then MyEdit.SetFocus; You have all this info available in the VCL source and the Windows API. ...but why not simply avoid doing the thing that causes the problem in the first place?
  7. Anders Melander

    Bug VCL I'm losing my TControls course ?

    It hasn't "lost" the caret. It just doesn't have focus - hence no caret.
  8. Anders Melander

    Start Menu items missing for RAD Studio 12.3

    I think Microsoft has a whole division dedicated to coming up with ways to make the Start menu shittier for each new version of Windows. Windows 8 is still the champion though - Like that other version 8 which is best forgotten.
  9. Anders Melander

    New file system monitoring component

    One of the benefits of a pull request is to make it as easy as possible for the maintainer, who probably has better things to do than manually comparing files to find differences, to review, comment on, and merge changes. Posting the modified file somewhere doesn't do that.
  10. Anders Melander

    Bug VCL I'm losing my TControls course ?

    You can't. The "global" solution to doing something that causes problems is to stop doing something that causes problems.
  11. Anders Melander

    Bug VCL I'm losing my TControls course ?

    You mean the caret, right? The cursor is the one you move with the mouse. The caret is the blinking indicator that shows the current position in a text control. The caret should be shown automatically if an edit control has the focus (unless it's been explicitly hidden with HideCaret (it's hasn't in this case)) so my guess is that the sequence of actions you are doing (see Peter's answer) is causing VCL to think that the control has focus while Windows is of another opinion (and of course Windows is always right, in this case). One solution would be to simply not lose the focus by showing your fading form without activating it. See ShowWindow(SW_SHOWNA). Another is the PostMessage trick Peter mentioned. I wouldn't recommend the TTimer workaround - it's a lazy hack. const MSG_DO_STUFF = WM_USER; type TMyForm = class(TForm) private procedure MsgMyStuff(var Msg: TMessage); message MSG_DO_STUFF; end; ... procedure TMyForm.MsgMyStuff(var Msg: TMessage); begin ShowDialog('It works!'); end; procedure TMyForm.Edit1Exit(Sender: TObject); begin PostMessage(Handle, MSG_DO_STUFF, 0, 0); end;
  12. Anders Melander

    New file system monitoring component

    Maybe this would be a good occasion to learn Git then... Here's a quick intro I made for someone else that wanted to contribute a change to Graphics32: On Github Create a Github account: https://github.com/signup Fork the Graphics32 repository to your own Github account. This gives you a copy, on your own Github account, of the main repository where you can push your changes. On your local system Clone your own Graphics32 repository to your local system using a Git client. I recommend the Fork git client: https://git-fork.com/ Create a branch in your local repository. Commit your changes to that branch. Push the branch to your own Graphics32 repository. On Github Create a pull request on your Graphics32 repository. Specify the master branch at the main Graphics32 repository as the target, and your branch at your repository as the source. When Github notifies me that you have submitted a pull request I'll review the changes. Once I accept the pull request, the changes are merged into the branch you specified as the target branch.
  13. Anders Melander

    New file system monitoring component

    ...unless you also monitor the parent directory. Maybe make the polling optional?
  14. Anders Melander

    New file system monitoring component

    VPN is just transport layer encryption and is not relevant. The documentation for ReadDirectoryChangesW answers your other question:
  15. Anders Melander

    Using "Claude Code" with Delphi

    It sounds as if you've given up before the fight's begun - and a fight there will be. On many different fronts. So far I've read and heard endless tales of the efforts wasted on "ai". I'm sure it will eventually settle into something actually usable - if we can survive that long, but until then I'm running circles around the people that try to get ahead of the game "ai". The cake is a lie.
  16. Anders Melander

    capture user desktop

    Bad case of astigmatism? 🙂
  17. Anders Melander

    PNG Chunks

    I doubt that you will find anything that implements everything since there's really no need or practical use for that. You can have a look at the PNG implementation in Graphics32: https://github.com/graphics32/graphics32/blob/master/Source/GR32_PortableNetworkGraphic.pas I don't know if it covers more or less of the specs than TPNGImage but at least it's fully extensible so you can add anything that it's missing if you want to.
  18. Anders Melander

    capture user desktop

    Not my users - but of course that's not really relevant to you. "The program" isn't shown on a monitor; A window is and a program can have several windows, each positioned independently. You can use TForm.Monitor to determine what monitor a form is currently positioned on. Anyway, here's some reading material: https://learn.microsoft.com/en-us/windows/win32/gdi/the-virtual-screen https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics#SM_CXVIRTUALSCREEN https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetrics#SM_XVIRTUALSCREEN https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createdcw
  19. Anders Melander

    capture user desktop

    This might be because the Desktop Window Manager (DWM) ghosts your application and synthesizes an image of it. The same thing happens if your application isn't reading from the message queue (e.g. it's running in a tight loop, doing stuff); The application can't repaint itself so DWM takes over and displays an image of what it looked like the last time it was repainted. I think that what we get when copying from the desktop DC isn't necessarily what is actually displayed on the screen. I think the DWM has an internal buffer that composes the image we see based on the desktop DC and whatever other things it thinks should be shown (e.g. ghosted windows). There's probably an API somewhere that provides access to DWM.
  20. Anders Melander

    capture user desktop

    I second that. I wouldn't dream of using my own code for something like this when we have madExcept. It even allows the user to annotate the screenshot AFAIR.
  21. Anders Melander

    capture user desktop

    I think you need to work with monitors instead of "the screen". Different monitors can have different DPI, and they might not align. Here's some random code: procedure TBitmapEditorToolScreenShot.TSnapShotList.Capture; var i: integer; DesktopDC: HDC; Canvas: TCanvas; begin if (FItems = nil) then FItems := TObjectList<TSnapShot>.Create else FItems.Clear; for i := 0 to Screen.MonitorCount-1 do FItems.Add(TSnapshot.Create(Screen.Monitors[i])); // Capture desktop DesktopDC := GetDC(HWND_DESKTOP); if (DesktopDC = 0) then RaiseLastOSError; try Canvas := TCanvas.Create; try Canvas.Handle := DesktopDC; for i := 0 to FItems.Count-1 do FItems[i].Capture(Canvas); // See TSnapShot class below finally Canvas.Free; end; finally ReleaseDC(HWND_DESKTOP, DesktopDC); end; end; All it does it to create a list of monitors and then it does a capture of each monitor into separate bitmaps. Here's the class that represents a monitor and its bitmap and which does the actual capture: type TBitmapEditorToolScreenShot = class(TCustomBitmapEditorTool, ICaptureController) strict private type TSnapShot = class private FMonitor: Forms.TMonitor; FBitmap: TBitmap; public constructor Create(AMonitor: Forms.TMonitor); destructor Destroy; override; procedure Capture(DesktopCanvas: TCanvas); property Monitor: Forms.TMonitor read FMonitor; property Bitmap: TBitmap read FBitmap; end; ...more stuff... end; procedure TBitmapEditorToolScreenShot.TSnapShot.Capture(DesktopCanvas: TCanvas); begin if (FBitmap = nil) then FBitmap := TBitmap.Create; FBitmap.SetSize(FMonitor.BoundsRect.Width, FMonitor.BoundsRect.Height); FBitmap.PixelFormat := pf24bit; FBitmap.Canvas.CopyRect(FBitmap.Canvas.ClipRect, DesktopCanvas, FMonitor.BoundsRect); end; constructor TBitmapEditorToolScreenShot.TSnapShot.Create(AMonitor: Forms.TMonitor); begin inherited Create; FMonitor := AMonitor; end; destructor TBitmapEditorToolScreenShot.TSnapShot.Destroy; begin FBitmap.Free; inherited; end;
  22. Anders Melander

    Freeeee

    Yup. I started with Turbo Pascal's ancestor PolyPascal, which used WordStar key bindings, and I have used that ever since (that's the Classic IDE binding in Delphi). Unfortunately many of Delphi's newer editor functions aren't available with the Classic IDE key bindings. That said, I seem to remember that Classic had a key binding for column mode but I can't remember what it was. ^KN or something like that. No, it shouldn't. The compiler will use the project options by default.
  23. Anders Melander

    Freeeee

    I'm not sure I understand your question. You can get the editor to insert the current compiler options into the source with Ctrl+O+O (default and classic keyboard binding), if that's what you're asking.
  24. Anders Melander

    Freeeee

    Compiler options: {$ALIGN 8} {$ASSERTIONS ON} {$BOOLEVAL OFF} {$DEBUGINFO OFF} {$EXTENDEDSYNTAX ON} {$IMPORTEDDATA ON} {$IOCHECKS ON} {$LOCALSYMBOLS ON} ...etc... Compile-time feature flags & compiler version, and platform detection (these were snipped from the Graphics32 library): (* Symbol: NO_GENERIC_METACLASS_LISTS ------------------------------- The C++ Builder linker has problems resolving ambiguities caused by metaclass types because they all get mangled as TClass. As a result of this the compiled object files end up containing duplicate symbols, which in turn causes a LIB266 linker error. Specifically we get into problems with TCustomClassList<T> where "T" is a metaclass. To work around the problem we define the NO_GENERIC_METACLASS_LISTS for C++ Builder which causes us to use TClassList for all class types. *) {$if defined(BCB)} {$define NO_GENERIC_METACLASS_LISTS} {$ifend} (* Symbol: GENERIC_POINTERS ------------------------------- Typed pointers to generic types are supported. Older Delphi versions cannot resolve a pointer to a generic type correctly and therefore must use plan untyped pointers instead. Exact Delphi version is unknown but XE4 doesn't work and Delphi 10 does. The symbol is defined for XE5 and later, and for FPC. The exact version of Delphi that supports the feature is unknown at this time. *) {$if defined(FPC)} {$define GENERIC_POINTERS} {$elseif (CompilerVersion > 25.0)} {$define GENERIC_POINTERS} {$ifend}
×