-
Content Count
2848 -
Joined
-
Last visited
-
Days Won
155
Posts posted by Anders Melander
-
-
24 minutes ago, Javier Tarí said:Any idea on how could I change that order?
AFAIR you just change the order in which the properties are declared.
Note though that I've seen cases where a component depended on properties being set in a specific order during load. Can't remember any specifics.
You could also use a diff tool that can recognize moves. For example Plastic Merge.
-
3 minutes ago, FPiette said:calling ProcessMessages is perfectly correct if you understand what happens when you do so
-
1
-
4
-
-
4 minutes ago, FPiette said:Sure I did since the poster (You !)
- I'm not the OP.
- My example with MsgWaitForMulpitleObjects used QS_PAINT and DispatchMessage.
- The OP's use of QS_ALLINPUT is probably based on not understanding the problems associated with it.
- The circumstances where it's safe to Application.ProcessMessages are so rare that one might just as well not use it. Your example uses it in a button click handler where it's definitely not safe.
-
Just now, FPiette said:Application.ProcessMessages;
Oh no, you didn't!
-
1
-
-
I don't understand what you're asking about but you'll probably want to loop around MsgWaitForMultipleObjects - and process the messages somehow since you're using that variant of WaitForMultipleObjects. Don't fall into the trap of calling Application.ProcessMessages to handle the messages.
I posted an example of MsgWaitForMultipleObjects yesterday:
-
On 9/11/2020 at 9:40 AM, David Schwartz said:Any thoughts?
I have no idea about how TRzLauncher is implemented, but regardless I would just use a thin wrapper around ShellExecuteEx. Here's the implementation I usually use:
unit amShell; (* * Copyright © 2006 Anders Melander * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. *) interface uses Windows, Controls; type Shell = class private public class procedure DisplayURL(const URL: string; Parent: TWinControl = nil; const AdditionalParams: string = ''); class function DisplayFile(const Filename: string; Parent: TWinControl = nil): boolean; class function Execute(const Filename: string; const Parameters: string = ''; Parent: TWinControl = nil; Wait: boolean = False): boolean; overload; class function Execute(Parent: TWinControl; const FileName: string; const Operation: string = 'open'; const Parameters: string = ''; ShowCmd: Integer = SW_SHOWNORMAL; Wait: boolean = False): boolean; overload; static; end; resourcestring sShellExecuteBrowseError = 'Failed to open the homepage in your default browser.'+#13#13+ 'Homepage: %s'+#13+ 'Error: %s'; sShellExecuteFileOpenError = 'Failed to open the file.'+#13#13+ 'Filename: %s'+#13+ 'Error: %s'; implementation uses ActiveX, ShellAPI, SysUtils, IOUtils, Forms, Dialogs, StrUtils, Classes, Types, Messages, IdURI, amCursorService, amDialogs; class function Shell.DisplayFile(const Filename: string; Parent: TWinControl): boolean; var Error: integer; begin Result := Execute(Parent, Filename); if (not Result) then begin Error := GetLastError; MessageDlgEx(Format(sShellExecuteFileOpenError, [Filename, SysErrorMessage(Error)]), mtWarning, [mbOk], 0); end; end; class function Shell.Execute(const Filename, Parameters: string; Parent: TWinControl; Wait: boolean): boolean; var Error: integer; begin Result := Execute(Parent, Filename, '', Parameters, SW_SHOWNORMAL, Wait); if (not Result) then begin Error := GetLastError; MessageDlgEx(Format(sShellExecuteFileOpenError, [Filename, SysErrorMessage(Error)]), mtWarning, [mbOk], 0); end; end; class procedure Shell.DisplayURL(const URL: string; Parent: TWinControl; const AdditionalParams: string); var Error: integer; URI: TIdURI; FinalURL: string; FinalParams: string; ParamList: TStringDynArray; s: string; Params: TStringList; n: integer; Name, Value: string; begin try URI := TIdURI.Create(URL); try // Note that we use TIdURI even with no additional params as we would still like to get the original params encoded (' '->'%20'). if (AdditionalParams <> '') then begin Params := TStringList.Create; try Params.CaseSensitive := False; // Create a Key/Value list of original parameters ParamList := SplitString(URI.Params, '&'); for s in ParamList do Params.Add(s); // Add additional parameters, overriding the original values if there are duplicates ParamList := SplitString(AdditionalParams, '&'); for s in ParamList do begin n := Pos('=', s); if (n <> 0) then begin // Key/Value pair Name := Copy(s, 1, n-1); Value := Copy(s, n+1, MaxInt); Params.Values[Name] := Value; end else // No value, just key Params.Values[s] := ''; end; // Build parameter string FinalParams := ''; for s in Params do if (FinalParams = '') then FinalParams := s else FinalParams := FinalParams + '&' + s; finally Params.Free; end; URI.Params := FinalParams; end; FinalURL := URI.URI; finally URI.Free; end; except on E: EIdURIException do begin s := URL; if (AdditionalParams <> '') then s := s + '(' + AdditionalParams + ')'; MessageDlgEx(Format('Invalid URL: %s'#13'%s', [s, E.Message]), mtWarning, [mbOk], 0); exit; end; end; if (not Execute(Parent, 'rundll32.exe', 'open', 'url.dll,FileProtocolHandler '+FinalURL)) then begin Error := GetLastError; MessageDlgEx(Format(sShellExecuteBrowseError, [FinalURL, SysErrorMessage(Error)]), mtWarning, [mbOk], 0); end; end; class function Shell.Execute(Parent: TWinControl; const FileName, Operation, Parameters: string; ShowCmd: Integer; Wait: boolean): boolean; var Handle: HWND; ShellExecuteInfo: TShellExecuteInfo; Error: integer; Res: Cardinal; Msg: TMsg; begin if (Parent <> nil) then Handle := Parent.Handle else Handle := Application.MainForm.Handle; FillChar(ShellExecuteInfo, SizeOf(ShellExecuteInfo), 0); ShellExecuteInfo.cbSize := SizeOf(ShellExecuteInfo); ShellExecuteInfo.fMask := SEE_MASK_FLAG_NO_UI or SEE_MASK_HMONITOR or SEE_MASK_NOZONECHECKS;// or SEE_MASK_NOCLOSEPROCESS; if (Wait) then ShellExecuteInfo.fMask := ShellExecuteInfo.fMask or SEE_MASK_NOCLOSEPROCESS or SEE_MASK_NOASYNC; ShellExecuteInfo.Wnd := Handle; ShellExecuteInfo.hMonitor := THandle(Application.MainForm.Monitor.Handle); // Cast to avoind range check error if (Operation <> '') then ShellExecuteInfo.lpVerb := PChar(Operation); if (FileName <> '') then ShellExecuteInfo.lpFile := PChar(FileName); if (Parameters <> '') then ShellExecuteInfo.lpParameters := PChar(Parameters); ShellExecuteInfo.lpDirectory := PChar(TPath.GetDirectoryName(Filename)); ShellExecuteInfo.nShow := ShowCmd; SaveCursor(crAppStart); Result := ShellAPI.ShellExecuteEx(@ShellExecuteInfo); if (not Result) then begin Error := GetLastError; if (Error = ERROR_ACCESS_DENIED) then begin // See: // * https://support.microsoft.com/en-us/kb/287087 // * http://wellsr.com/vba/2016/excel/use-vba-shellexecute-to-open-url-in-default-browser/ if (ShellAPI.ShellExecute(Handle, ShellExecuteInfo.lpVerb, ShellExecuteInfo.lpFile, ShellExecuteInfo.lpParameters, nil, CmdShow) > SE_ERR_DLLNOTFOUND) then Result := True else SetLastError(Error); end; end else if (Wait) then begin try while (True) do begin Res := MsgWaitForMultipleObjects(1, ShellExecuteInfo.hProcess, False, INFINITE, QS_PAINT); case Res of WAIT_OBJECT_0: break; WAIT_OBJECT_0+1: while (PeekMessage(Msg, 0, QS_PAINT shl 16, QS_PAINT shl 16, PM_REMOVE)) do begin if (Msg.message = WM_QUIT) then begin PostQuitMessage(Msg.wParam); exit; end; TranslateMessage(Msg); DispatchMessage(Msg); end; else break; end; end; finally CloseHandle(ShellExecuteInfo.hProcess); end; end; end; var NeedCoUninitialize: boolean = False; initialization // ShellExecute needs CoInitialize NeedCoUninitialize := Succeeded(CoInitializeEx(nil, COINIT_APARTMENTTHREADED or COINIT_DISABLE_OLE1DDE)); finalization if (NeedCoUninitialize) then CoUninitialize; end.
-
3
-
-
39 minutes ago, Uwe Raabe said:(Sigh! Sometimes I miss the automatic branching in NNTP readers...)
Yeah. It's amazing, given how far web software has come, that web forums (fora?) still can't match 20 years old newsreaders. Sure, there are some things a forum does better (rich content for example) but I still prefer newsreaders.
(let's see how many times we can branch this thread 🙂 )
-
1 hour ago, alnickels said:Can somebody explain curl in the original post please?
Have you read the documentation?
https://developer.here.com/documentation/vector-tiles-api/dev_guide/topics/send-request.html
or are you asking what curl is?
-
29 minutes ago, Rollo62 said:If its a new project, then its still time to change to FMX.
My point was that if we're talking about VCL then the platform must be Windows. If the platform is Windows then the FMX TMapView control can't be used since it only supports iOS and Android.
-
5 hours ago, Rollo62 said:Do you know that FMX instead of VCL basically has maps for iOS and Android included ?
In a new project, maybe FMX makes sense for you too ?
Since he's asking about VCL I think we can assume that it will not be running on iOS or Android.
-
I would be very careful with basing something on Google Maps. They have already deprecated their API several times and it appears that there's currently no official public API.
https://stackoverflow.com/questions/44520345/how-do-i-enable-google-maps-tile-api
https://stackoverflow.com/questions/58846393/how-to-apply-api-key-to-google-maps-tile-server-url
https://cloud.google.com/maps-platform/terms/
DevExpress has a map control that supports OpenStreetMap and Bing Maps.
OpenStreetMap:
Bing Maps (most of the links you'll find with Google are currently dead for some reason):
QuoteThe ExpressMap Control allows you to embed multi-layered maps into your VCL applications (be it raster maps provided by popular web mapping resources, vector maps built with elements stored in map files, or a combination of both), add image and text overlays, and pinpoint specific locations on your map with indicators of your choice. With a comprehensive set of customization options, built-in navigation tools and animation support, the ExpressMap Control helps you create interactive map interfaces with ease.
Main features include:- Capability to simultaneously display an unlimited number of layers painted with image tiles (Image Tile Layer), vector items (Item Layer), and/or shapes loaded from the Esri shapefiles and KML map files (Item File Layer);
- Support for the Bing Maps™ and OpenStreetMap online map providers (see the licensing information below);
- A set of UI elements that allow your end-users to scroll, zoom in and out, and see detailed information about the current view;
- Smooth scroll and zoom animation;
- Map element highlighting;
- Support for skins provided with the ExpressSkins Library.
-
You should only get conflicts when trying to apply a stash if the files you've stashed have changed since you stashed them. If you haven't changed them then something's broken. If you have, well, then there's your conflict.
I really would suggest that you try to use a GUI Git client. That would make it much more clear what's going on.
-
1
-
-
I don't understand why you have all these "pull ...resolve conflict".
When you are doing a pull you shouldn't have any local changes that aren't pushed so there should be nothing to resolve.
Ordinarily I only have conflicts when I merge two local branches. There's never a conflict on pull and I don't even think my tool (SourceTree) allows me to do a pull if there are conflicts.
Also, if I had to interrupt my work to change context I would stash my changes, not commit them.
11 hours ago, David Schwartz said:If someone else is misusing a tool, why should you be impacted by it?
Because it's possible to break the rules. For example by doing rebase on a branch that has already been pushed.
See: Peter Parker Principle.
-
As far as I remember there's no API for that. I think you will have to parse the resource block yourself. If you're lucky the memory layout is the same as the RES layout but even then many of the structures in the VERSIONINFO RES format are undocumented or very poorly documented.
The only suggestion I have is to have a look at the source of Collin Willson's old resource editor and see how he did it (with regard to the RES format).
-
1
-
-
7 minutes ago, aehimself said:it could be custom-drawn on a TWinControl-descendant and call it a component.
They're alpha blended so you'd have to either give that up or use GDI+, Graphics32 or something like it. If I were to implement it as a custom control but I would probably use bitmaps and maybe draw them as 9-patch images so it could be resized. The colors could be applied with a simple HUE filter.
-
On 9/4/2020 at 9:03 AM, Lars Fosdal said:If the series of stages are sequential, I'd consider a segmented progress bar,
Building on your concept I would suggest something like this:
I've attached the 14 image segments used to create the above.
-
5
-
-
4 hours ago, David Heffernan said:you aren't getting great feedback
Hrmph!
-
36 minutes ago, Mike Torrettinni said:Should I look into if any string manipulation methods would be faster with working on Ansistrings?
Do you need them to be faster?
-
1
-
-
10 minutes ago, luebbe said:Dock another window (TestInsight) onto the messages window
I would suggest you do all these tests without 3rd party add-ons involved. It hard to know where to place the blame otherwise.
-
3 hours ago, David Schwartz said:I think in pictures, and I've never seen any good illustrations about what goes on when you're working in git.
First of all: Get a GUI Git client. I rarely use the command line during my daily work.
I came from Svn and found the transition to Git very confusing because the terminology is different and because you're basically working with two repositories (the local and the one on the server) at once.
What Git server do you use?
4 hours ago, David Schwartz said:I don't understand what's meant by "use pull requests to merge into Master".
A pull request is just a request to merge a branch into another. The "pull" is from the perspective of the target so it's a request that the target pull the supplied changes.
I'm guessing the way you work now is something like this:
- Create a local branch.
- Work on the files in the branch.
- Commit changes to the branch.
- Merge the branch into Master.
- Push Master to the server.
With a pull request you would work like this:
- Create a branch (either locally or on the server, doesn't matter).
- Work on the files in the branch.
- Commit changes to the branch.
- Push the branch to the server.
- Create a pull request on the server.
- Review the pull request on the server (should be done by someone else). Accept or Reject the pull request.
- Apply the pull request on the server thereby merging the branch into Master.
4 hours ago, David Schwartz said:Nobody likes that we do work in one folder and git is constantly shuffling around files in other folders, and throwing up conflicts because someone else is in the middle of doing some work that has nothing to do with what you're working on
I'm still not sure I understand the problem but I'll try with a solution anyway.
Let's say your main project is in the Projects repository and that you have this mapped locally to C:\Project.
Your client data is in the Clients repository and you have this mapped to I:\.
Within the Projects repository you have a branch for each client and the same for the Clients repository.
The Master branch of each repositories contains the changes that are common for all clients and the individual client branches contains the client specific stuff.
When you make changes to Master you will have to merge that back into each of the client branches to keep them up to date. You can create a script that automates this task.
Now if you make Clients a submodule of Projects then you can make the individual project branches track the corresponding branch in Clients. This means that when you check out a Projects branch then the corresponding Clients branch will automatically be checked out as well so your I:\ data will contain the correct files.
-
1
-
6 hours ago, pyscripter said:However I got an error message saying:
When did you get that message? On package install?
I don't have 10.4.1 installed at the moment (tested the uninstaller yesterday and haven't had time to install again) so I can't try myself.
-
I can't see anything in what you describe that is out of the ordinary. Looks like a pretty standard workflow to me.
One thing I would do is make sure that very few people have rights to push to Master or whatever you call your primary branch. Instead use pull requests to merge into Master. This avoids the situation where someone forces a push and rewrite history and then later claim that "git must have messed something up".
I'm not sure what to do about your I: drive if you really want to have all the files there at all time, regardless of the branch you're working on. If you're okay with pulling the files for a given branch to I: when you work on that branch, then you could reference you I: repository as a submodule in your main Git project. Then each customer could get their own branch in the I: repository.
HTH
-
1
-
-
1 hour ago, ntavendale said:Strangely though, they left Classic Undocked as an option in the drop down used to select the layout, both in the Min IDE form and in the options
I believe this is mentioned in the release notes:
QuoteDesktop layouts which cannot be applied (i.e. are floating layouts, no longer supported, see above) will be listed in gray in the Desktop Layout combo box in the title bar. When a floating layout is applied, the IDE will instead show a dialog.
-
1 minute ago, Sherlock said:Yes. It has been this way for some time now. I just trusted them to stick to that plan.
Well that's what I get for actually reading the installation instructions.
-
3
-
DFM Serialization Properties order
in RTL and Delphi Object Pascal
Posted
You can republish properties: