Jump to content

MarkShark

Members
  • Content Count

    50
  • Joined

  • Last visited

Everything posted by MarkShark

  1. Thanks Dalija and the other posters, this is all "good stuff" and I love to learn new things and techniques. I'm not sure how the word condescending matches anything said here so far btw. Also just as a note I see that Emba switched to using AtomicCmpExchange instead of InterlockedCompareExchangePointer in Delphi 11 (or perhaps earlier.) Kind of interesting.
  2. Anders, that may be the case. I determined that it was for thread safety from some stack overflow posts that seemed to match the code style. The link is https://stackoverflow.com/q/5392107/113128 and there are a number of suggestions that some of the implementation examples aren't fully safe. It's definitely a good thing to keep in mind, thanks!
  3. Going to answer my own question after some research. Looks like it's for thread safety! Got it now, thanks.
  4. Thank you Peter! I'm checking out your code and trying to learn some uncoupling/interface techniques. In the HelperRegistry function I notice you use the following code to set the InternalHelperRegistry while also returning it. Is it done this way for thread safety or is it just related to maintaining the proper refcount of the interface? BTW: Your posts through the years have been extremely helpful to me, so thanks as always! Result := THelperRegistry.Create; Result._AddRef; // the call below does not increment the refcount! P:= InterlockedCompareExchangeObject(InternalHelperRegistry, TObject(Pointer(Result)), nil); if P <> nil then begin Result._Release; Result := InternalHelperRegistry; end; {if} -Mark
  5. I realize that this is going to be very subjective, but what are people's thoughts on using begin end just to limit the scope of an inline variable? For example: ... code begin var LocalString := 'My String'; ... Use LocalString for something end; ... more code Are there any caveats to doing so? I know that doing this can cause an implicit try-finally for managed types, so I can see that being a performance factor in a loop and something to be aware of. It also seems like they've fixed the issues with the debugger and inline vars in Delphi 11 (at least in the simple cases I've tried), which makes them more usable. -Mark
  6. Remy, all the techniques I tried caused my application to be the foreground one. I'm guessing that's what the OP found as well. That might be how the TRzTrayIcon works or possibly I just missed something obvious back then.
  7. I had to do this for a password management tray app I wrote for personal use. Here's the technique I ended up with (with lots of help from stack overflow and others.) Step 1: Use EnumWindows with a callback to build up a list of window handles. They will be in the current z-order. It needs to check if the window is visible, unowned, and has WS_EX_APPWINDOW in its style before adding it to your list. Step 2: Loop through the window handles above and find the first one in the list with a thread process id different than your current program. This is done using GetWindowThreadProcessId on each window handle from your enum list and comparing to the results of GetCurrentThreadID. That window handle should be the main window of the app that was last active. I would perform the above whenever my tray app was activated. I'm guessing there are exceptions for "stay on top" apps and such but it seemed to work for my needs. I hope that helps or at least gives a clue! -Mark Update note: Once I get the window handle of the last activated app I would also call GetLastActivePopup on it (as I needed to know if it had a modal popup active.)
  8. Agreed! A quick search found this one: https://quality.embarcadero.com/browse/RSP-34831 -Mark
  9. MarkShark

    SynEdit preferred version?

    Hey all. I use SynEdit in a few projects and I was wondering if anyone has insight on which of the various version is the preferred one to use. I'm on 10.4 and don't need backwards compatibility btw. The one that is on "GetIt" appears to be an older version (1.5.) The one listed as SynEdit2 on github by pyscripter appears to be active, includes some nice changes (ole drag and drop for example) lots of fixes and cleanup (some related to removing support for older Delphi versions.) The one listed as SynEdit/SynEdit on github which seems to be more actively developed then the other two. I've worked with the second two and, as always, it seems when working with third party components I have to make a few changes to the source (adding some missing properties, fixing the extra space on word wrap lines (thanks to a stack overflow answer) and a few other minor issues) which have to be merged into each new update, so picking the "correct" one will obviously help. On a side note I have a feeling that the correct answer might be that there is no correct answer... Just looking for any feedback or thoughts. And this post wouldn't be complete without thanking and acknowledging all the great work people have done on these projects! -Mark
  10. Summary: Using a Parallel.BackgroundWorker if I check for WorkItem.CancellationToken.IsSignalled within the .OnExecute anonymous procedure I see that it is terminated immediately if I call FWorker.CancelAll from the main thread. HOWEVER if I use a function called from the OnExecute handler it seems that the token is only signaled once the function completes. I've included some code below, but if anyone could explain what I'm seeing it would be much appreciated! Using a Paralel.BackgroundWorker created like: FWorker := Parallel.BackgroundWorker.Execute(nil); I then schedule a work item like: FWorker.Schedule( FWorker.CreateWorkItem(TOmniValue.Null), FWorker.Config .OnExecute( procedure(const WorkItem: IOmniWorkItem) begin var LElapsed: Integer := 1; repeat Sleep(100); Inc(LElapsed, 100); until WorkItem.CancellationToken.IsSignalled or (LElapsed > 5000); end) .OnRequestDone( procedure (const Sender: IOmniBackgroundWorker; const WorkItem: IOmniWorkItem) begin if WorkItem.CancellationToken.IsSignalled then Memo1.Lines.Add('Task ' + WorkItem.UniqueID.ToString + ' onRequestDone and was cancelled.') else Memo1.Lines.Add('Task ' + WorkItem.UniqueID.ToString + ' onRequestDone'); end ) ); Calling FWorker.CancelAll; from the main thread cancels this workitem immediately. However if instead of the "repeat until" above I call the following function, the token is never signaled "during the call", though it is signaled after the call returns. function NiceWaitEx(const ACancelToken: IOmniCancellationToken; AWaitMs: Integer): Integer; begin const LagMs = 100; var LElapsed: Integer := 1; repeat Sleep(LagMs); Inc(LElapsed, LagMs); until ACancelToken.IsSignalled or (LElapsed > AWaitMs); Result := LElapsed; end; FWorker.Schedule( FWorker.CreateWorkItem(TOmniValue.Null), FWorker.Config .OnExecute( procedure(const WorkItem: IOmniWorkItem) begin NiceWaitEx(WorkItem.CancellationToken, 5000); end) .OnRequestDone( procedure (const Sender: IOmniBackgroundWorker; const WorkItem: IOmniWorkItem) begin if WorkItem.CancellationToken.IsSignalled then Memo1.Lines.Add('Task ' + WorkItem.UniqueID.ToString + ' onRequestDone and was cancelled.') else Memo1.Lines.Add('Task ' + WorkItem.UniqueID.ToString + ' onRequestDone'); end ) ); When I use the second version (with the call) the workitem always goes the full 5 seconds although shows that it was cancelled at the end. I hope that's enough to explain the issue (and my confusion lol.) Any thoughts appreciated! -Mark
  11. MarkShark

    TListView and Stylebook on 10.4

    Ha! Sorry about that. I didn't notice this question was in FMX! -Mark
  12. MarkShark

    TListView and Stylebook on 10.4

    I can confirm it. The only solutions are to use a different control (such as the Virtual String Tree) or to use the following library. RRuz VCL Style Utils -Mark
  13. MarkShark

    Annoying IDE behavior changes in 10.4.2

    I can confirm the change as well. I've also noticed that the Ctrl-Alt-Up and Ctrl-Alt-Down keys don't seem to navigate between methods anymore (although Ctrl-Alt-Mousewheel still seems to do it.) I was going to suggest it to jump to the first line after begin, but it's gone. So if you want the old behavior you can do Ctrl-Shift-Up, Ctrl-Shift-Down, and then Ctrl-Alt-Mousewheel up! Simple, right? (Wink) Method Hopping: http://docwiki.embarcadero.com/RADStudio/Sydney/en/Code_Navigation_(IDE_Tutorial)
  14. MarkShark

    Issue about calling Canvas.Polygon

    Thanks! I notice you're calling it like ACanvas.SaveDC so I thought maybe you were encapsulating the API functions (my TCanvas doesn't seem to have those as methods.) I do use the api calls directly, but obviously your code is cleaner.
  15. MarkShark

    Issue about calling Canvas.Polygon

    @Anders Melander Are your SaveDC and RestoreDC calls from a class helper for TCanvas? I don't do a lot of canvas drawing and only recently need to use the API functions for this and I don't fully understand when calling Canvas.Refresh is needed... and I'm wondering if your calls handle that. Thanks!
  16. I have a background worker that I create with: FWorker := Parallel.BackgroundWorker .NumTasks(1) .Execute(HandleQueryWorkItem); I queue jobs to this worker and everything works great . I have a situation where I want to check if the worker is idle with a timeout, so I'm trying to use: FWorker.WaitFor(MyMilliseconds); This seems to work in my test cases, however calling WaitFor calls "CompleteAdding" (which seems to make sense.) However it never gets turned back on and future queueing of jobs raises "Adding to completed collection". So is there a way to turn queueing back on, or am I doing something fundamentally wrong? Thanks for any insight or tips! -Mark
  17. Windows file explorer in detail view shows combobox-like headers (on hover over) that allow filtering the data based on the column type (for example to only show files changed today, or to only show Excel documents.) Does anyone know if this is something that the standard TListView control is capable of directly, or is this more an owner draw header type thing? Alternately, is there a similar control that can do this? The TVirtualStringTree in column mode perhaps? My searches on this haven't panned out so I'm wondering if anyone has any suggestions or thoughts. Thanks! -Mark
  18. MarkShark

    Capturing Tab key in a TCombobox

    The specific case is that I'm using a TComboBox as an editor in a VirtualStringTree. Unfortunately I can't seem to capture VK_TAB on the KeyDown event of the control. I've used code very similar to the "Properties" tree demo included in the Advanced Demo. Running that demo I get the same affect, pressing Tab while a combobox is active goes to the next focus control. I'd like to handle it much like the enter key and move to the next cell after accepting the edit. Apparently the tab handling is happening at the form level and the TCombobox never seems to get it. Any suggestions on how to handle this? Thanks!
  19. MarkShark

    Capturing Tab key in a TCombobox

    Thank you François! I ended up creating my own TEmbeddedComboBox and used the handling suggested in Remy's answer to your linked SO question.. and SCORE! procedure TEmbeddedComboBox.WndProc(var Msg: TMessage); begin inherited; if Msg.Msg = WM_GETDLGCODE then Msg.Result := Msg.Result or DLGC_WANTTAB; end;
  20. MarkShark

    Capturing Tab key in a TCombobox

    Lars, thanks. This is code I'm writing for a VirtualStringTree that allows editing. I'm sure you're correct that the actions could be handled at the form level, but obviously I'd prefer to keep the handling internal to the control if possible. I was hoping this was just something I'm thinking incorrectly about, maybe there's another way to handle it. Although the fact that the VST demo app shows the same behavior makes me think it's not an easy fix. I did some code searching and it looks like Delphi's TInplaceEditList (part of the Grids Unit) is what they use instead of just using a TComboBox, I assume that's to give more control and to handle this issue. It's a bit complex for a transplant, so I'm hoping someone can suggest an alternative. It's one of those things where it seems like I'm so close to getting it to work the way I want.
  21. MarkShark

    Project Magician gotcha

    I've attached ProjTest.dproj. I took the following steps: Created a new Vcl project. Added Target Platform Win64 Used the Project Options Dialog to add version info to "All Configurations - All Platforms" setting version 1.2.3.4 (and also editing the key/values) Used the Project Options Dialog to add version info to "All Configurations - Windows 32-bit Platform" setting version 5.6.7.8 (and also editing the key/values) Used the Project Options Dialog to add version info to "All Configurations - Windows 64-bit Platform" setting version 9.10.11.12 (and also editing the key/values) Also added some debug and release version info for each target. Save on Project Options Save Project Result: The debug and release verinfo sections were correctly removed. The Base, Base-Win32 and Base-Win64 sections remain intact (I'm still unsure if that's "as intended" or not.) ProjTest.dproj [added: I'm using Delphi 10.4.1 and the latest Project Magician.]
  22. MarkShark

    Project Magician gotcha

    Yes, though I'll make a new test case and retest my findings just in case it's project specific (this particular project is one that's been around for years.) Thanks for clarifying about when Project Magician does its work!
  23. MarkShark

    Project Magician gotcha

    My projects platforms are Win32 and Win64. Am I correct that the Magician actions take place on Project Save? Basically I'm just switching Targets, changing the version info, then saving the project and then looking at the dproj file to see the results. [added] In my testing with a project that has Win32 and Win64 target platforms only, that Base_Win32 and Base_Win64 retain <verinfo_*> changes when saving the project.
  24. MarkShark

    Project Magician gotcha

    I've been doing some testing of the current version and I might be misunderstanding things. I have a dproj file with a Base config with verinfo information (including <VerInfo_Keys> info.) I added a new one under Base-Win32 and both seem to stay around. I was expecting the win32 one to be removed in favor of Base. Am I misunderstanding how it works? It did correctly remove the verinfo stuff from a debug section. Is this so that you can have different version info for different target platforms? Project Magician is awesome btw!
  25. MarkShark

    Turbo SynEdit & Font Ligatures

    My goto has been Consolas, but this change seems a good one! I'll have to look into those fonts. BTW, having recently started to use Delphi Styles I'd love to see SynEdit support them. Fortunately I get around it by adding: TCustomStyleEngine.RegisterStyleHook(TCustomSynEdit, TMemoStyleHook); // to get styled scrollbars And then either changing the all the colors whenever the style changes OR by using the Vcl.Styles.Hooks unit. I usually go with the hooks since I use a couple other controls that don't support styles fully (like spTbxDock and spTbxToolbar, which I've noticed you're doing some much needed work on!) Fantastic work!
×