-
Content Count
3001 -
Joined
-
Last visited
-
Days Won
135
Everything posted by Remy Lebeau
-
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
-
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);
-
Error message: "'Cannot call Start on a running or suspended thread"
Remy Lebeau replied to mikerabat's topic in Windows API
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(). -
Error message: "'Cannot call Start on a running or suspended thread"
Remy Lebeau replied to mikerabat's topic in Windows API
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. -
Error message: "'Cannot call Start on a running or suspended thread"
Remy Lebeau replied to mikerabat's topic in Windows API
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. -
How to read file on plugged in Android device
Remy Lebeau replied to Martin Ortmayr's topic in General Help
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 -
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.
-
Form.OnKeyUp(key:word) = Get ASCII code of Special character(è)
Remy Lebeau replied to gioma's topic in General Help
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; -
Form.OnKeyUp(key:word) = Get ASCII code of Special character(è)
Remy Lebeau replied to gioma's topic in General Help
But, why does it have to be sent char-by-char? That is much harder than sending properly encoded whole strings. -
Creating a stub .lib to use a Delphi-created DLL
- 2 replies
-
- dll
- import library
-
(and 1 more)
Tagged with:
-
Reorganize a class / Set Of ..
Remy Lebeau replied to PatV's topic in Algorithms, Data Structures and Class Design
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. -
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.
-
Form.OnKeyUp(key:word) = Get ASCII code of Special character(è)
Remy Lebeau replied to gioma's topic in General Help
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. -
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.
-
Delete unicode non-breaking space
Remy Lebeau replied to Fons N's topic in RTL and Delphi Object Pascal
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. -
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.
-
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;
-
Who's "He" exactly? The IDE? Your code? Where exactly are you seeing the error?
-
EULA declined installing 11.1 with Network Named license
Remy Lebeau replied to Lachlan Gemmell's topic in General Help
Same reasons all of my VMs were XP, until I was forced to start making Win7 VMs. Same -
Does anyone know how to get the filesystem for usb mass storage?
Remy Lebeau replied to wilsonning's topic in FMX
Have you read the documentation yet? Using Java Libraries in Your RAD Studio Android Apps -
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.
-
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.
-
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.
-
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.
-
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 ...