Jump to content

Anders Melander

Members
  • Content Count

    2561
  • Joined

  • Last visited

  • Days Won

    133

Everything posted by Anders Melander

  1. Anders Melander

    New Delphi job opportunity

    Broken eco-system. On the Danish job-sites I can see the same Delphi jobs being posted again and again and I've had something in the neighborhood of 10 unsolicited Delphi related job offers during the past 12 months. The last one, this past Friday, need 2-3 Delphi developers. "Unfortunately" I'm fully booked, overbooked actually, and there's only one of me 🙂
  2. Anders Melander

    ANN: Better Translation Manager released

    You might be able to use the existing CSV importer to import those into a project. Just specify "=" as the delimiter instead of ";"
  3. Anders Melander

    ANN: Better Translation Manager released

    I see. Can you reveal what tool was used to produce that format? Maybe I can make an importer for it. It's open source so you can do whatever you like with it. If you prefer to keep your existing format the easiest approach would probably be to modify a copy of the amLocalization.Persistence unit and then alter the TLocalizationCommandLineTool.LoadFromFile method in the amLocalization.CommandLine unit to use your own persistence class. It should be relatively easy to extend the existing solution with support for different project file formats using either an internal or external plugin architecture [*] but I'm not sure when I will have time to add that. * Internal=You register a class to handle your format and recompile. Very easy to implement for me. external=You build and register an external DLL which handles the format. Much more work as I would need to wrap much more stuff in interfaces.
  4. Anders Melander

    ANN: Better Translation Manager released

    The PE stub I use is defined in amLocalization.ResourceWriter.pas (see below). If a file named EmptyResourceModule.dll exists in the same folder as BTM then that file will be used as the stub. Otherwise the stub is loaded from a resource (see Source\Resources folder) and finally if that resource doesn't exist the hardcoded stub below will be used. const sResourceModuleStub = 'EmptyResourceModule.dll'; sResourceModuleStubRes = 'EmptyResourceModule'; // Name of above file as an embedded resource // The following is the content of the file specified by the sResourceModuleStub constant. // It should be a minimal (i.e. no code) PE module containing nothing but a resource section without any resources. sResourceModuleData : AnsiString = #$4D#$5A#$90#$00#$03#$00#$00#$00#$04#$00#$00#$00#$FF#$FF#$00#$00#$B8#$00#$00#$00#$00#$00#$00#$00#$40#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$B0#$00#$00#$00+ #$0E#$1F#$BA#$0E#$00#$B4#$09#$CD#$21#$B8#$01#$4C#$CD#$21#$54#$68#$69#$73#$20#$70#$72#$6F#$67#$72#$61#$6D#$20#$63#$61#$6E#$6E#$6F+ #$74#$20#$62#$65#$20#$72#$75#$6E#$20#$69#$6E#$20#$44#$4F#$53#$20#$6D#$6F#$64#$65#$2E#$0D#$0D#$0A#$24#$00#$00#$00#$00#$00#$00#$00+ #$37#$CF#$3C#$DF#$73#$AE#$52#$8C#$73#$AE#$52#$8C#$73#$AE#$52#$8C#$E1#$F0#$AD#$8C#$72#$AE#$52#$8C#$E4#$F0#$50#$8D#$72#$AE#$52#$8C+ #$52#$69#$63#$68#$73#$AE#$52#$8C#$00#$00#$00#$00#$00#$00#$00#$00#$50#$45#$00#$00#$4C#$01#$02#$00#$B0#$66#$81#$5A#$00#$00#$00#$00+ #$00#$00#$00#$00#$E0#$00#$02#$21#$0B#$01#$0E#$00#$00#$00#$00#$00#$00#$04#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$10#$00#$00+ #$00#$10#$00#$00#$00#$00#$00#$10#$00#$10#$00#$00#$00#$02#$00#$00#$06#$00#$00#$00#$00#$00#$00#$00#$06#$00#$00#$00#$00#$00#$00#$00+ #$00#$30#$00#$00#$00#$02#$00#$00#$00#$00#$00#$00#$02#$00#$40#$05#$00#$00#$10#$00#$00#$10#$00#$00#$00#$00#$10#$00#$00#$10#$00#$00+ #$00#$00#$00#$00#$10#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$20#$00#$00#$10#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$10#$00#$00#$1C#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$2E#$72#$64#$61#$74#$61#$00#$00#$70#$00#$00#$00#$00#$10#$00#$00#$00#$02#$00#$00#$00#$02#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$40#$00#$00#$40#$2E#$72#$73#$72#$63#$00#$00#$00#$10#$00#$00#$00#$00#$20#$00#$00+ #$00#$02#$00#$00#$00#$04#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$40#$00#$00#$40#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$B0#$66#$81#$5A#$00#$00#$00#$00#$0D#$00#$00#$00#$40#$00#$00#$00#$1C#$10#$00#$00#$1C#$02#$00#$00#$00#$00#$00#$00+ #$00#$10#$00#$00#$1C#$00#$00#$00#$2E#$72#$64#$61#$74#$61#$00#$00#$1C#$10#$00#$00#$54#$00#$00#$00#$2E#$72#$64#$61#$74#$61#$24#$7A+ #$7A#$7A#$64#$62#$67#$00#$00#$00#$00#$20#$00#$00#$10#$00#$00#$00#$2E#$72#$73#$72#$63#$24#$30#$31#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+ #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00;
  5. Anders Melander

    ANN: Better Translation Manager released

    No. A resource module is just a PE file (a DLL) with a resource section but without any code. That's how I use it too. I use Bamboo with the following config for the BTM task (XXX is the target project name). The target is a 64-bit exe. Executable: c:\Tools\Better Translation Manager\amResourceModuleBuilder.exe Argument: "${bamboo.build.working.directory}\translation\XXX.xlat" -v -b -n:0 "-s:${bamboo.build.working.directory}\bin\XXX.exe" "-y:${bamboo.build.working.directory}\bin\XXX.drc" "-o:${bamboo.build.working.directory}\bin" What do you mean by "my own resource project format."?
  6. Anders Melander

    ANN: Better Translation Manager released

    Even if your target project is 64-bit you don't need the resource builder to be 64-bit. The 32-bit build works with both 32- and 64-bit targets. Yes, you're right. It should be a THandle or a NativeUInt. I have pushed the fix. Thanks.
  7. Anders Melander

    Developer Express gave up on FMX

    From the comment track on that page: Oh, those Russians I think you're right. https://www.linkedin.com/company/developer-express-inc./people/
  8. Anders Melander

    ANN: Better Translation Manager released

    Yes - and it works for me. Does it fail on every target project you run it against? Why do you want it as a 64-bit executable? I don't think there should be any need for it as the memory usage is quite modest when building resource modules.
  9. Anders Melander

    ImageLists. One or Multiple??

    It almost was, but they dropped that ball long time ago: http://melander.dk/reseditor/ The resource editor was meant to be a part of Delphi 2010 but even though I implemented all Embarcadero's requirements (primarily two-way RC file support) the required open tools API was never surfaced in Delphi (basically just the ability to register a custom module editor). And when they stopped communicating I simply gave up on that project. I almost deleted the source in anger.
  10. Anders Melander

    Developer Express gave up on FMX

    There's some interesting information in that thread. From what I could understand through Google translate: DevExpress is American owned. Their developers are primarily Russian. Their supporters are Russian & Ukrainian. Is that correct? BTW, I just found this one: https://supportcenter.devexpress.com/ticket/details/t1081876/regular-updates-and-new-features
  11. Anders Melander

    Developer Express gave up on FMX

    I don't know but it could be some of their support people are busy killing each other. I'm heavily invested in their products but I must say that I've had mixed experiences with them these last few years. Their attitude towards enhancements gets a bit tiresome. Too often I see a reasonable request answered with "We don't plan to further enhance X in the foreseeable future", "We're just wrapping a standard Windows control" or "That's not how Microsoft does it". It seems many of their products are, if not in actual maintenance mode, then not really evolving anymore. I'm sure it doesn't help that Julian Bucknall seems to have fallen out of love with Delphi.
  12. Anders Melander

    DUnitX and StackTraces

    I just looked in my own unit tests and I can see that I have added the following to enable madExcept support. I can't remember why - or even if it works. ...unrelated stuff snipped... // Work around for broken Delphi 10.3 compiler support in bundled DUnitX {$if defined(MADEXCEPT)} type TMadExcept4StackTraceProvider = class(TInterfacedObject, IStacktraceProvider) public function GetStackTrace(const ex: Exception; const exAddressAddress: Pointer): string; function PointerToLocationInfo(const Addrs: Pointer): string; function PointerToAddressInfo(Addrs: Pointer): string; end; function TMadExcept4StackTraceProvider.GetStackTrace(const ex: Exception; const exAddressAddress: Pointer): string; begin Result := madStackTrace.StackTrace(false, false, false, nil, nil, exAddressAddress, false, false, 0, 0, nil, @exAddressAddress); end; function TMadExcept4StackTraceProvider.PointerToAddressInfo(Addrs: Pointer): string; begin Result := String(StackAddrToStr(Addrs)); end; function TMadExcept4StackTraceProvider.PointerToLocationInfo(const Addrs: Pointer): string; begin Result := String(StackAddrToStr(Addrs)); end; {$ifend} begin {$if defined(MADEXCEPT)} TDUnitXIoC.DefaultContainer.RegisterType<IStacktraceProvider, TMadExcept4StackTraceProvider>(true); {$ifend} {$if defined(RUNNER_TESTINSIGHT)} ExecuteTestInsight; {$elseif defined(RUNNER_GUI)} ExecuteGUIRunner; {$else} ExecuteConsoleRunner; {$ifend} end.
  13. Anders Melander

    looking for remote Delphi job

    It would probably improve your chances of getting a response if you stated where in the world you're located and didn't post under an alias.
  14. You're right. I need to flush my long term memory of obsolete information 🙂. In Delphi 5 the tread was started immediately in the TThread constructor. Since Delphi 6 it is started in AfterConstruction.
  15. Create the thread suspended and then start it once the constructor returns. It is generally a bad idea to construct a thread with CreateSuspended=False. I.e. instead of: constructor TEventChannel.TEvtLoadThread.Create(parent: TEventChannel); begin fParent := parent; inherited Create(False); end; do this: constructor TEventChannel.TEvtLoadThread.Create(parent: TEventChannel); begin inherited Create(True); fParent := parent; end; ... TheThread := TEvtLoadThread.Create(Something); TheThread.Start; ...
  16. Anders Melander

    Parnassus Bookmarks for Delphi 11 Alexandria?

    I've heard that it's a special integration operation and that everything is going according to plan. Nothing to see here. Move along.
  17. Anders Melander

    Set focus on dialog box button

    Replace this: if fChooseResult.showModal=mrOK then did:=dm.qStockNum.fieldbyname('design_id').asstring; with: if fChooseResult.Execute then did := dm.qStockNum.FieldByName('design_id').AsString; and then modify the TfChooseResult form like this: const MSG_AFTERSHOW = WM_USER; type TfChooseResult = class(TForm) ... protected procedure MsgAfterShow(var Msg: TMessage); message MSG_AFTERSHOW; public function Execute: boolean; end; implementation {$R *.dfm} procedure TfChooseResult.MsgAfterShow(var Msg: TMessage); begin BitBtn1.SetFocus; end; function TfChooseResult.Execute: boolean; begin PostMessage(Handle, MSG_AFTERSHOW, 0, 0); Result := (ShowModal = mrOK); end; Edit: Maybe I should explain what's going on. The PostMessage puts a custom message into the form's message queue. When ShowModal is called the form is displayed and the modal loop pumps the message queue [*]. The message pump grabs the custom message from the queue and calls the form's message handler (the MsgAfterShow method). MsgAfterShow focuses the button. [*] Pumping the message queue means that the code loops, reading one message at a time from the message queue and dispatching these messages to the "message handlers". It's "a bit" more complicated than that but hopefully you get the overall picture.
  18. Anders Melander

    Set focus on dialog box button

    Yes You can use Search->Find in files (Ctrl+Shift+F) to locate the place. Search for " fChooseResult .Show". No problem. Happy to help.
  19. Anders Melander

    Set focus on dialog box button

    @Pat Foley That example was really confusing - and contains so many bad practices.
  20. Anders Melander

    Set focus on dialog box button

    By the way, do yourself a favor and stop using TBitBtn. They were cute in the nineties. Not anymore.
  21. Anders Melander

    Set focus on dialog box button

    Nope. He's not calling the event handler. He's calling the Click method on the button - which emulates a click on the button.
  22. Anders Melander

    Set focus on dialog box button

    Assuming that you're showing this form modally from somewhere else I would do it like this: type TfChooseResult = class(TForm) wwDBGrid1: TwwDBGrid; Panel1: TPanel; dsResult: TDataSource; BitBtn1: TBitBtn; BitBtn2: TBitBtn; procedure wwDBGrid1DblClick(Sender: TObject); private public function Execute: boolean; end; var fChooseResult: TfChooseResult; implementation {$R *.dfm} procedure TfChooseResult.wwDBGrid1DblClick(Sender: TObject); begin BitBtn1.click; end; function TfChooseResult.Execute: boolean; begin BitBtn1.SetFocus; Result := (ShowModal = mrOK); end; and then display the form like this: begin ...do other stuff here... if (fChooseResult.Execute) then begin // User pressed OK end else begin // User closed dialog some other way end; end; And like Peter suggested, set the ModalResult property of the OK button to mrOK and the Default property of the same to True. If you add a Cancel button, set its ModalResult property to mrCancel and the Cancel property to True. If you're not displaying the form modally, then you'll need to call SetFocus in the forms OnShow event handler instead. This of course assumes that the form isn't visible all the time.
  23. Anders Melander

    Set focus on dialog box button

    Set it in code: ButtonOK.SetFocus; The ActiveControl property is a property of the form but that is only applied when the form is first created and it sounds like you are only doing that once.
×