Jump to content

Anders Melander

Members
  • Content Count

    2563
  • Joined

  • Last visited

  • Days Won

    134

Everything posted by Anders Melander

  1. Anders Melander

    Setting Scroll Bar Width problem

    procedure TMyForm.ButtonScrollPageUp(Sender: TObject); begin PostMessage(MyGrid.Handle, WM_SCROLL, SB_PAGEUP, 0); end; procedure TMyForm.ButtonScrollPageDown(Sender: TObject); begin PostMessage(MyGrid.Handle, WM_SCROLL, SB_PAGEDOWN, 0); end;
  2. Anders Melander

    Setting Scroll Bar Width problem

    The Graphics32 scrollbar can be used as inspiration or a starting point: https://github.com/graphics32/graphics32/blob/master/Source/GR32_RangeBars.pas
  3. Funny. I got booted too for suggesting he should stop posting about his non-delphi related pet projects. I guess that group wasn't big enough for both our egos Can't say I miss it much.
  4. I don't think there's a widely used convention for that. I would just name it "Radio".
  5. There are a few issues with your code and a few things that could be improved. 1) A member function has a hidden "self" parameter so in reality the signature of the MakeSine function you have declared looks like this: function MakeSine(const [ref] Self: TRadio; handle: HSTREAM; buffer: Pointer; Alength: DWORD; user: Pointer): DWORD; stdcall; If you want MakeSine declared as a member function then you need to declare it as a static class method: type TRadio = record ... class function MakeSine(handle: HSTREAM; buffer: Pointer; Alength: DWORD; user: Pointer): DWORD; stdcall; static; end; but then you lose the reference to self and can't access the member variables inside the method. I'm guessing that the user parameter is for passing context to the callback and if so you can achieve the same with an extra function: type TRadio = record ... private function DoMakeSine(handle: HSTREAM; buffer: Pointer; Alength: DWORD): DWORD; public class function MakeSine(handle: HSTREAM; buffer: Pointer; Alength: DWORD; user: Pointer): DWORD; stdcall; static; end; class function TRadio.MakeSine(handle: HSTREAM; buffer: Pointer; Alength: DWORD; user: Pointer): DWORD; begin Result := TRadioPointer(user).DoMakeSine(handle, buffer, Alength); end; function TRadio.DoMakeSine(handle: HSTREAM; buffer: Pointer; Alength: DWORD): DWORD; begin ... end; begin // Pass TRadio pointer as the "user" parameter resultValue := BASS_StreamCreate(cSAMPLE_RATE, 2, 0, @TRadio.MakeSine, PRadio); end 2) The convention would be to name your TRadio pointer type "PRadio" type TRadio = record ... end; PRadio = ^TRadio; 3) You don't need to deference typed complex pointer types with ^ PRadio^.MakeSine // standard Pascal PRadio.MakeSine // allowed in Delphi
  6. Anders Melander

    How to detect if TIDMessage is unable to read an email

    Then you are already able to answer your own question. If your assumption is "possibly unsafe" then working on that assumption is not "the safest thing". You're contradicting yourself. You are never going to be able to handle every possible scenario. I suggest you create a set of test files, both valid and invalid. Make sure you can handle those but code defensively under the assumption that there are cases you don't know of yet.
  7. Anders Melander

    Printing in a threaded program

    Yes, the Printer global TPrinter instance is a singleton and AFAIK it is not thread safe. However I can't see why it should be a problem for each thread to create their own TPrinter instance and use that to print. The print job context wrapped by TPrinter is not a singleton and the target print device does not necessarily represent a single physical device. procedure TMyThread.Execute; var Printer: TPrinter; begin ... Printer := TPrinter.Create; try ... while (not Terminated) do begin ... Printer.BeginDoc; try ... finally Printer.EndDoc; end; ... end; finally Printer.Free; end; end;
  8. Anders Melander

    How to detect if TIDMessage is unable to read an email

    I don't know but don't you have the source code? It should be fairly easy to find out exactly what TIDMessage does if you just trace into LoadFromFile in the debugger.
  9. Anders Melander

    Object created in a Try block???

    It depends. Do either this: Foo := TFooBar.Create; try ... finally Foo.Free; end; or this: Foo := nil; try Foo := TFooBar.Create; ... finally Foo.Free; end;
  10. Anders Melander

    do any git tools work like this?

    Apparently they haven't discovered that you can .gitignore files? I think we must have different definitions of "least resistance"
  11. Anders Melander

    Threads on dual-Xeon system

    No. You discussed it here:
  12. Anders Melander

    Creating Simple Com Server to return array of strings to Python 3.8

    Here you go: type // The interfaces are probably defined in your type library unless they are purely // for internal use within the application. IFoo = interface ['{922E28A3-0127-42DB-A394-2CFED29A5575}'] procedure DoFoo; safecall; end; IBar = interface ['{BECBDCE4-192C-48DC-9DC4-85DB92E01E9F}'] function GetFoo: IFoo; safecall; end; type // If you're using dual/dispatch/late bound/automation interfaces then use TAutoObject or // TAutoIntfObject as a base class instead. See the help. TFoo = class(TInterfacedObject, IFoo) private // IFoo procedure DoFoo; safecall; end; procedure TFoo.DoFoo; begin ShowMessage('Hello world'); end; type TBar = class(TInterfacedObject, IBar) private // IBar function GetFoo: IFoo; safecall; end; function TBar.GetFoo: IFoo; begin Result := TFoo.Create; end; ... procedure Test; var Bar: IBar; Foo: IFoo; begin Bar := TBar.Create; Foo := Bar.GetFoo; Foo.DoFoo; end; The principles hasn't changed since Delphi 5 and you're not going to save any time by not learning this stuff. I recommend you read this (old) one: http://www.techvanguards.com/stepbystep/comdelphi/
  13. Anders Melander

    Creating Simple Com Server to return array of strings to Python 3.8

    Yes, I agree. My point was that it's optional. safecall transforms hresult into exceptions which sometimes is exactly what you want and sometimes not.
  14. Anders Melander

    TdxfOutlookBar for Delphi 5

    Before you posted this the first hit on Google for "TdxfOutlookBar" was Q499568 Replacement for TdxfOutlookBar...
  15. Anders Melander

    Creating Simple Com Server to return array of strings to Python 3.8

    Make that: In that case your method can be declared "safecall".
  16. Anders Melander

    do any git tools work like this?

    Once again: As far as I can tell there's nothing special in the work flow your describe. It's perfectly normal to have a branch per ticket, to change branch several times a day, to get interrupted while you're working on something that hasn't yet been committed, etc. The problems with Git you describe (changes disappearing, etc) are not problems with Git but with the way you use it; It will not overwrite your uncommitted changes unless you force it to. It is unclear to me what benefits your tool provides. It sounds like the problems it solves are already handled by the existing GUI Git clients.
  17. Anders Melander

    Compare byte array to ansichar

    As I wrote you cannot compare a byte (ansichar) to 13 bytes (byte array) for equality. Since the size is different they will always be different, so what you're asking isn't making sense. Are you trying to determine if the byte array contains the ansichar? function Contains(const Bytes: TByteArray; c: AnsiChar): boolean; begin for var b in Bytes do if (b = Ord(c)) then Exit(True); Result := False; end;
  18. Anders Melander

    Compare byte array to ansichar

    Assuming you meant AnsiString and not AnsiChar (it doesn't make sense to compare 13 bytes to 1 ansichar): function Compare(const Bytes: TByteArray; const Str: AnsiString): boolean; begin Result := (Length(Str) = SizeOf(Bytes)) and (CompareMem(@Str[1], @Bytes[0], SizeOf(Bytes)); end;
  19. Anders Melander

    Creating Simple Com Server to return array of strings to Python 3.8

    I think you must have a bug somewhere else that is causing this. I can't spot a problem in the code you've posted. The following works for me with D10.3.1: function Test1: OleVariant; begin Result := VarArrayCreate([0, 1], varOleStr); Result[0] := 'Hello'; Result[1] := 'World'; end; function Test2: OleVariant; var V: OleVariant; begin V := VarArrayCreate([0, 1], varOleStr); V[0] := 'A kitten dies...'; V[1] := '...every time you use variant arrays'; Result := V; end; procedure DoTest; var V: OleVariant; begin V := Test1; V := Test2; end; Try reproducing the problem in a new empty application.
  20. Anders Melander

    Creating Simple Com Server to return array of strings to Python 3.8

    Have you tried VarArrayCreate(..., varOleStr)? I can't see why you would get an error assigning one OleVariant to another but it would help if you specified what error you're getting.
  21. Anders Melander

    TFDMemTable in use by different threads

    Yes. Moving the cursor in a clone does not affect the other clones. As I read that post read access to a cloned dataset is thread safe.
  22. Anders Melander

    remove part of string and compare

    Yes, it was poorly expressed on my part. If they went through the message queue then the application wouldn't appear hung.
  23. Anders Melander

    remove part of string and compare

    Generally speaking, the API of most Windows common controls goes through the windows message queue. So my guess is that for each item in the listbox there's a lot of messages going back and forth while the listbox is populated and that's an enormous overhead. If you break the application in the debugger while the list is loading you can see what it's doing.
  24. Anders Melander

    Compile code on the fly...?

    Okay. I'll try with a simpler example (apologies to @Kas Ob. if he/she/they already covered it, but it's friday and TLDR). Byte code is just the instruction set for a specialized virtual CPU so in this case it's a virtual CPU that only knows how to search stuff. A byte code compiler is a compiler that transforms "something" (in this case search parameters) into the virtual CPU assembler. The implementation of the virtual CPU is called an interpreter if it executes the byte code instruction from scratch each time you execute the "byte code program". If it instead compiles the byte code into actual processor opcodes the first time and then execute those the first and subsequent times, then it's called just-in-time compiler. One of the first pascal implementation was UCSD Pascal which ran on the UCSD p-System - a byte code virtual machine. P.S. You really should try to read about and understand these old concepts. While they might not seem relevant to you now, understanding and knowing about them can only improve your skills.
×