Jump to content

Remy Lebeau

Members
  • Content Count

    3001
  • Joined

  • Last visited

  • Days Won

    135

Everything posted by Remy Lebeau

  1. Remy Lebeau

    TSimpleEvent how to

    Really? https://docwiki.embarcadero.com/Libraries/en/System.SyncObjs.TSimpleEvent https://docwiki.embarcadero.com/Libraries/en/System.SyncObjs.TEvent https://docwiki.embarcadero.com/RADStudio/en/Waiting_for_a_Task_to_Be_Completed
  2. Remy Lebeau

    TNetHTTPClient and custom header

    Alternatively, these would probably work, too: NetHTTPClient1->CustHeaders->Value["Authorization"] = "Token token=key1, btoken=key2"; NetHTTPClient1->CustHeaders->Add("Authorization", "Token token=key1, btoken=key2"); TNetHeaders AuthHeader; AuthHeader.Length = 1; AuthHeader[0] = TNameValuePair("Authorization", "Token token=key1, btoken=key2"); NetHTTPClient1->Get("https://examplesite", NULL, AuthHeader);
  3. Not relevant in this case, because the handle returned by CreateThread() has THREAD_ALL_ACCESS permissions, which includes THREAD_SUSPEND_RESUME. That permission is meant to prevent other people from suspending/resuming threads they don't have access to. You have full access to your own threads. You are just going to have to debug your app on these failing systems to see what ResumeThread() is actually returning: -1 = failure, what does GetLastError() report? 0 = was not suspended to begin with 1 = was suspended, now resumed (this is what you want in this situation) > 1 = was and still is suspended Not that I'm aware of. The number of threads you can create is limited only by available memory. Even if there were a configurable limit, you would be getting failures in CreateThread(), not in ResumeThread().
  4. In general, there is nothing wrong with creating a TThread with CreateSuspended=False. That has worked just fine for the past 2 decades. So, unless Embarcadero has recently broken TThread, something else is likely going on.
  5. Offhand, the code looks fine to me. I've never had any problems with using TThread with CreateSuspended=False. However, as a workaround, you can try creating the TThread with CreateSuspended=True, and then manually call TThread.Start() after the constructor has exited. If that works, then I would suspect that Embarcdero may have possibly introduced a regression in TThread's construction. What version of Delphi are you using? On Windows, the TThread constructor creates a thread with the CREATE_SUSPENDED flag enabled, then the TThread.AfterConstruction() method calls ResumeThread() if the TThread constructor was called with CreateSuspended=False (as is the case in your example). The error message you are seeing is raised if ResumeThread() fails to resume the thread, ie either because the API failed outright (ResumeThread() returns -1), or the thread was suspended multiple times (ResumeThread() returns > 1), neither of which should be happening in your example. Are you, by chance, calling TThread.Start() anywhere else in your code? If so, you should not be calling Start() on a TThread created with CreateSuspended=False. If that were the case, you would be getting an exception from the TThread constructor, not its AfterConstruction() method.
  6. Remy Lebeau

    How to read file on plugged in Android device

    The device is not accessible via the host machine's file system. There is no local drive letter or UNC share assigned to the device, so you can't use filesystem-based functions to access the device's files. So, you will have to use alternative means of accessing the device's files, such as: Win32 Shell interfaces (IShellFolder/IShellItem, PIDLs, etc) - which is what Explorer uses. Introduction to the Shell Namespace Navigating the Shell Namespace IFileOperation::CopyItem() and IFileOperation::CopyItems Windows Portable Devices API Android Debug Bridge pull command
  7. Remy Lebeau

    How to know how app was started

    On Android, there is a property in FMX (I can't find it right now) that contains the Intent that started the app if it was not already running. You can check that Intent at startup to see if your app was started because of a notification, a file open, etc, depending on how your app manifest is configured. If your app was already running when the Intent is sent, you can register with FMX's RTL to receive TMessageReceivedNotification messages, which will carry the Intent. I'm not sure of the equivalent for iOS, though I do notice that TPushRemoteNotificationMessage and TPushStartupNotificationMessage exist for it.
  8. There are a number of problems with that code: - the wScanCode parameter of ToUnicodeEx() is not optional. Unfortunately, the OnKeyUp event does not give you the original scan code that the OS provided in the WM_KEYUP message. However, in this case, since only bit 15 of the scan code is really needed, you can fake it. For a KeyUp event, bit 15 needs to be set to 1, not 0. - you are not populating the TKeyboardState before passing it in to ToUnicodeEx(). You need to call GetKeyboardState() first. - you are passing in a single WideChar for the output buffer to ToUnicodeEx(), but you are telling ToUnicodeEx() that the buffer is large enough to hold 255 WideChars, which is a lie. The output of the conversion can be more than 1 WideChar, so you need to allocate enough space to hold the entire result. The return value will tell you how many WideChars were actually written to the buffer. - ToUnicodeEx() alters the keyboard state while translating the key, unless you ask it not to (Windows 10+ only). - WideCharToString() expects a null-terminated PWideChar string, not a single WideChar. With that said, try something more like this instead: procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); var buf: array[0..15] of WideChar; KSta: TKeyboardState; numChars: Integer; begin Winapi.Windows.GetKeyboardState(ksta); numChars := Winapi.Windows.ToUnicodeEx(key, $8000, ksta, buf, Length(buf)-1, 4, 0); if numChars > 0 then begin buf[numChars] := #0; log.Lines.Add('KeyUp : ' + IntToStr(Key) + ' = ' + WideCharToString(buf)); end else if numChars = 0 then log.Lines.Add('KeyUp : ' + IntToStr(Key) + ' = (no translation)') end else log.Lines.Add('KeyUp : ' + IntToStr(Key) + ' = (dead key)'); end; However, if you really want to handle individual key presses, you should be using the OnKeyPress event of the OnKey[Down|Up] events, as previously stated. The OnKeyPress event gives you translated Unicode characters, not virtual key codes. procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); begin log.Lines.Add('KeyPress : ' + IntToStr(Key) + ' = ' + Key); end;
  9. But, why does it have to be sent char-by-char? That is much harder than sending properly encoded whole strings.
  10. Remy Lebeau

    Creating Import Library from DLL (64-Bit)

    Creating a stub .lib to use a Delphi-created DLL
  11. You can't declare a Generic for a stand-alone Set, no. But I'm pretty sure (I haven't tried it lately, though) that you can move the Set into the class, and then use a Generic on the class, eg: type TFPropertiesCpt<T> = class (TInterfacedObject, IFCompteurUpdate) public type TSetOfT = Set of T; private FItems : TDictionary<Integer, rCompteurUpdate<T>>; FProperties : TSetOfT; ... procedure Duplicate(const aValue : TFPropertiesCpt<T>); public ... property Items : TDictionary<Integer, rCompteurUpdate<T>> read FItems write FItems; property Properties : TSetOfT read FProperties; function Add(const aTypeOf: T; const aInc: Integer = 1) : TFPropertiesCpt<T>; function WithInit: TFPropertiesCpt<T>; function WithInfo(const aValue: T; aProc: TProc) : TFPropertiesCpt<T>; function WithMax(const aValue : Integer) : TFPropertiesCpt<T>; function ResetCompteur(const aValue: T): TFPropertiesCpt<T>; overload; ... class function Clone(const aValue: TFPropertiesCpt<T>): TFPropertiesCpt<T>; end; Where T can then be set to any enum type, like TTypeOfProperties, etc.
  12. Remy Lebeau

    Sniffer tool detection function

    Meaning what, exactly? Are you trying to detect when specific tools are installed on the machine your app is running on? If so, then do those tools even provide any means of detecting their installations? Do they create Registry keys for themselves? Do they create file system folders in predictable locations? Do you know how to detect these tools manually, before you code any logic for them? Is that a SPECIFIC tool? Because more than one HTTP debugger exist in the world. What does detecting tools have to do with stopping services? Why can't you just stop the services without the tools? Please explain in more detail EXACTLY what you are trying to accomplish.
  13. Are you using VCL or FMX for the sending app? I do not recommend sending individual characters. Send whole strings instead. And be sure to encode them in a platform-neutral encoding, such as UTF-8. For instance, what you consider to be a single "character" may in fact be composed of multiple Unicode codepoints grouped together to create a grapheme cluster, which can't be obtained in a single UI event or transmitted as a single byte/char. Rather than transmitting characters as they are being typed, I suggest having the user type into an Edit control first, and then when Enter is pressed, or a button is clicked, etc, then send the entire text in one go. That will be much easier to manage. In VCL at least, the OnKey(Down/Up) events deal in "virtual" key codes, whereas the OnKeyPress event deals in character codes. Only because Microsoft decided that the virtual key codes for ASCII characters would be the same numeric values as their ASCII character codes. That is not the case for non-ASCII characters. Correct. Virtual key code 222 (0xDE) is VK_OEM_7: "Used for miscellaneous characters; it can vary by keyboard. For the US standard keyboard, the 'single-quote/double-quote' key" You don't, because there is no ASCII code for that character. The best way to deal with non-ASCII characters is to deal with Unicode strings.
  14. Remy Lebeau

    Delphi JSON data to listbox

    Well, obviously, because you are not calling TJSONObject.ParseJSONValue() to parse the JSON, and then pointing the Obj variable at the JSON object which holds the 'meta_data' field, You have to do that before calling Obj.GetValue('meta_data'). Once again, just like I stated in my very first reply of this discussion, you have not shown the complete JSON document, so I cannot show you complete Delphi code, only snippets. So it is your job to apply those snippets to your actual JSON document as needed.
  15. Remy Lebeau

    Delete unicode non-breaking space

    That is because the original data is encoded in UTF-8, but once it is loaded into your string, it is no longer encoded in UTF-8, it is encoded in UTF-16 instead. $C2 $A0 are the UTF-8 bytes for the non-breaking character, whereas $00A0 (decimal 160) is the UTF-16 value of that same character.
  16. Remy Lebeau

    Delphi JSON data to listbox

    That is an numeric field. Simply Get() a TJSONValue pointer to it, then type-cast that pointer to TJSONNumber, and then read its AsInt property, eg: Arr := Obj.Get('meta_data') as TJSONArray; for Value in Arr do begin Obj := Value as TJSONObject; id := (Obj.Get('id') as TJSONNumber).AsInt; end; I suggest you read the documentation before going any further.
  17. Remy Lebeau

    Delphi JSON data to listbox

    You did not show the complete JSON, so the below example is incomplete, but it should give you an idea of what you need: uses ..., System.JSON; ... var Root, Value: TJSONValue; Obj: TJSONObject; Arr: TJSONArray; I: Integer; begin ListBox1.Items.Clear; Root := TJSONObject.ParseJSONValue(...); try Obj := ...; // get a pointer to the parent object first as needed, then... Arr := Obj.GetValue('line_items') as TJSONArray; for Value in Arr do begin Obj := Value as TJSONObject; ListBox1.Items.Add(Obj.Get('name').Value); end; finally Root.Free; end; end;
  18. Remy Lebeau

    Custom component Resource PRINTFORM not found

    Who's "He" exactly? The IDE? Your code? Where exactly are you seeing the error?
  19. Remy Lebeau

    EULA declined installing 11.1 with Network Named license

    Same reasons all of my VMs were XP, until I was forced to start making Win7 VMs. Same
  20. Remy Lebeau

    Does anyone know how to get the filesystem for usb mass storage?

    Have you read the documentation yet? Using Java Libraries in Your RAD Studio Android Apps
  21. Remy Lebeau

    Loading data from dfm

    Uwe Raabe already nailed the root cause of your error - FCaptionsAdded is not instantiated early enough, so it is nil when the DFM system is trying to access it. The real question is, why are you MANUALLY streaming FCaptionsAdded AT ALL? TStringList is a TPersistent descendant that implements its own native DFM streaming logic. So, it is enough to just declare a TStrings/TStringList property in your component and back it with a VALID TStringList instance at component creation, no manual streaming is necessary.
  22. Remy Lebeau

    Tstringgrid grid index out of bounds

    Then it has to be a bug in the Grid, as it should be working given what you have described. I would suggest turning on "Use Debug DCUs" in the Project Options, and then step into the Grid's source code with the debugger to see exactly what is actually failing, and where it is occurring. On a separate note, have you tried the Grid's Selection property yet? var r: TGridRect; r.Left := setgridcol; r.Top := setgridrow; r.Right := setgridcol; r.Bottom := setgridrow; StringGrid1.Selection := r; But, given the screenshot and the values provided, it should not be out of bounds. That is the issue.
  23. Remy Lebeau

    Indy & OpenSSL 1.1.1 & TLS 1.3

    The IF is certainly a yes, but I couldn't tell you the WHEN for sure. But you can try out the pending code for yourself at https://github.com/IndySockets/Indy/pull/299 and see if it works for you.
  24. Remy Lebeau

    Indy & OpenSSL 1.1.1 & TLS 1.3

    I totally agree. And I have been meaning to reach out to the community for a long time looking for volunteers to join the dev team on a more regular basis, I just haven't gotten around to it. Well, it is still being actively maintained, as in it receives updates for fixes, and adding minor features that are easy to add to the existing code. But major updates have been delayed for a long time. Namely, releasing Indy 11 (maintenance release to drop pre-Unicode compilers, restructure the runtime packages, etc) and starting on Indy 12 (major new features, logic rewrites, etc) has been on the back-burner for many years now. Actually, Indy 11 is almost ready, but without an IDE I haven't been able to test the new structure and finalize it.
  25. Remy Lebeau

    Indy & OpenSSL 1.1.1 & TLS 1.3

    Status hasn't changed since the last time you asked. The new support code for OpenSSL 1.1.x and TLS 1.3 is still in Pull Request #299 on GitHub awaiting review and merge into the main codebase. AFAIK, it works in general, but I offer no guarantees about it yet as there are some open issues with it, cross platform support hasn't been tested, etc. It is not dead. I still work on it pretty frequently, but I'm pretty much the only developer working on it (aside from the occasional contribution from users or Embarcadero), and I just don't have the kind of free time that I used to have. But I do what I can with the time I can spare for it. Plus, it doesn't help that I don't have a working IDE installed anymore. Many years ago (I just checked my blog, and wow, I didn't realize just how many years have past now!), a series of multiple back-to-back system crashes took out my entire development environment - all of my VMs, NAS backups, laptop, everything gone. To this day, I still haven't recovered any of my old files yet. In the case of Indy specifically, fortunately the main code was stored online, so I can continue to checkin updates/fixes as needed, but I lost a lot of internal dev code I was working on at the time. As for the IDE itself, I just haven't committed time to reinstall it yet. I don't use RAD Studio in my day job anymore. Not to mention I haven't been very happy with all the problems I see people report in various online forums about the past handful of releases, so I've been hesitant to reinstall a new IDE for awhile. But, last year I did finally buy a new laptop for future dev work, and plan on installing RAD Studio onto it (eventually). I know, it sounds like I'm just making excuses. Maybe I am. I need to pick up the slack ...
×