Jump to content

Remy Lebeau

Members
  • Content Count

    2684
  • Joined

  • Last visited

  • Days Won

    113

Everything posted by Remy Lebeau

  1. Remy Lebeau

    Delphi 12 : Encoding Unicode strange behaviour

    That is not a good idea. Such an indicator should not be in the data payload itself, it should precede the payload, ie in a separate message header. Also, to differentiate between UTF8 or UTF16, you could use standard Unicode BOMs. So, for instance, have a message header that indicates whether the payload is text bytes or file bytes, and the total byte size. Then in the payload itself, if it is text then have it start with a BOM before the actual text bytes. Although, in reality, it is generally not a good idea to use UTF16 in data transmissions. Better to stick with just UTF8. Convert to/from UTF16 in memory only, if needed.
  2. Remy Lebeau

    TLS v1.3

    Which files does it delete that it shouldn't? Oh. Nevermind.
  3. Remy Lebeau

    D12 Indy install - IndyIPServer error

    https://docwiki.embarcadero.com/RADStudio/en/FireUI_Live_Preview
  4. Remy Lebeau

    Advice for Compiling Github Indy under Delphi 12

    I just now closed the PR and checked in my own changes for Delphi 12.
  5. In XE7 and later, you should use the GetTypeKind() intrinsic function instead of using TypeInfo() comparisons: https://delphisorcery.blogspot.com/2014/10/new-language-feature-in-xe7.html case GetTypeKind(T) of tkInteger: PInteger(@Result)^ := 10; tkLString: PAnsiString(@Result)^ := 'Hello'; tkUString: PUnicodeString(@Result)^ := 'Hello'; ... end;
  6. Remy Lebeau

    Comport issue

    Your getUSBDeviceInfo() function requires a symbolic name containing at least 2 '#' chars in it, but the ports you are testing with don't have any '#' chars in their names at all. When your TButton.OnClick handler calls FindPorts(), it gets the device list and checks each device name with ContainsMediaTekPort(). You are recording the result of that check to the log file, which is why you see the device being found. And then, if a matching name is found then the subsequent call to getUSBDeviceInfo() fails to parse the device name, thus skipping the retrieval of that device's info from the Registry. Your OnClick handler is then looping through the returned device array, checking each device's PortName for the device name (which in of itself is wrong since the PortName is different than the device name), and since the PortName was never being populated, that is why you see the "not found" error. You should have been able to discover this problem for yourself if you had stepped through your code with the debugger line-by-line and noticed that getUSBDeviceInfo() was never reading from the Registry. You need to fix this parsing problem so that getUSBDeviceInfo() actually returns the data you are expecting. Aside from that, just from a design perspective, I would strongly recommend changing FindPorts() to NOT include 'default' entries in the returned array. When you are filtering for a specific type of port, that is all you should be returning, eg: Function FindPorts(Filter: string = ''): TUSBDeviceList; var sub: TStringList; i: integer; begin sub := TStringList.Create; try FindAvailableCOM(sub); if Filter <> '' then begin for i := sub.Count - 1 downto 0 do begin if Pos(Filter, sub[i]) = 0 then sub.Delete(i); end; end; SetLength(Result, sub.Count); for i := 0 to sub.Count - 1 do Result[i] := getUSBDeviceInfo(sub[i]); finally sub.Free; end; end; ... procedure TForm13.Button3Click(Sender: TObject); var Ports: TUSBDeviceList; begin Ports := FindPorts('MediaTek USB Port_V1633'); if Length(Ports) > 0 then begin LogPortCheckingInfo('MediaTek port found: ' + Ports[0].DeviceParameters.PortName); ShowMessage('MediaTek port found.'); end else begin LogPortCheckingInfo('MediaTek port not found.'); ShowMessage('MediaTek port not found.'); end; end; Now, all of that being said, I do also notice a number of other mistakes and general problems with the code you have provided, such as lack of adequate error handling, use of incorrect data types, etc. It could really benefit from a good code review and cleanup in general.
  7. Remy Lebeau

    Advice for Compiling Github Indy under Delphi 12

    I'm guessing you didn't see https://github.com/IndySockets/Indy/pull/517 yet? In any case, I'm also working on my own update to Indy for D12, but that update also includes bringing Indy's Package Generator up-to-date, which is why I haven't merged the above PR yet, as I want to see how the generated files compare to the PR's files. Although, I guess at this point, I should just merge the PR and then merge in any generator diffs later...
  8. Remy Lebeau

    TListItem.MinWidth doesn't work

    TListItem does not have a MinWidth property, you meant TListColumn instead. In any case, what version of Delphi are you using? I can reproduce the problem in Delphi 12 w/ Patch 1 installed. When dragging a column divider in the header, the TListColumn.MinWidth and TListColumn.MaxWidth values get ignored when the TListView is processing an HDN_ITEMCHANGING notification from the header. TListView looks for HDN_ITEMCHANGING to trigger a redraw of the active TListItem, but there is an 'else' that skips the MinWidth/MaxWidth processing: if (Mask and HDI_WIDTH) <> 0 then begin if code = HDN_ITEMCHANGING then EnsureItemRedrawn(nil) else // <-- HERE!! begin Col := GetColumnFromTag(Item); if Col.MinWidth >= cxy then cxy := Col.MinWidth else if (Col.MaxWidth > 0) and (Col.MaxWidth <= cxy) then cxy := Col.MaxWidth; Col.Width := cxy; end; end; When I take that 'else' out, the MinWidth/MaxWidth values work properly as expected: if (Mask and HDI_WIDTH) <> 0 then begin if code = HDN_ITEMCHANGING then EnsureItemRedrawn(nil); //else // <-- HERE!!! begin Col := GetColumnFromTag(Item); if Col.MinWidth >= cxy then cxy := Col.MinWidth else if (Col.MaxWidth > 0) and (Col.MaxWidth <= cxy) then cxy := Col.MaxWidth; Col.Width := cxy; end; end; This bug does not exist in Delphi 10.3, so it was introduced sometime after that version: if (Mask and HDI_WIDTH) <> 0 then begin // NO redraw LOGIC HERE!!! Col := GetColumnFromTag(Item); if Col.MinWidth >= cxy then cxy := Col.MinWidth else if (Col.MaxWidth > 0) and (Col.MaxWidth <= cxy) then cxy := Col.MaxWidth; Col.Width := cxy; end; I would suggest filing a bug report with Embarcadero, but Quality Portal is still down. I'll report it privately.
  9. Remy Lebeau

    Comport issue

    That is a LOT of code to go through, I'm betting most of it is irrelevant to the problem at hand. And it doesn't even include your UI code that is displaying the "not found" error, so I don't even know which portions of this code are actually being exercised.
  10. Remy Lebeau

    Comport issue

    Your formatting is all messed up, please fix it.
  11. Remy Lebeau

    Comport issue

    Why does your device manager keep refreshing and showing the port disappearing? Are you perhaps opening the port during the time it has disappeared? What does your code look like that is opening the port?
  12. Look for the tfVerificationFlagChecked flag in the TTaskDialog.Flags property after TTaskDialog.Execute() returns true: if TaskDialog.Execute then begin ... Result.DoNotShowAgain := tfVerificationFlagChecked in TaskDialog.Flags; ... end And, if you want the checkbox to be initially checked when you display the dialog, enable the tfVerificationFlagChecked flag before calling TTaskDialog.Execute(): TaskDialog.Flags := [tfUseCommandLinks, tfAllowDialogCancellation, tfExpandFooterArea]; if DoNotShowAgainIsChecked then TaskDialog.Flags := TaskDialog.Flags + [tfVerificationFlagChecked];
  13. Remy Lebeau

    Don't use Application.MessageBox

    You can configure the IDE to not break on exceptions. I usually use breakpoints to tell the debugger to not break on exceptions that occur within specific sections of code I don't want to break on.
  14. Remy Lebeau

    delphi version

    The information you are looking for is not compiled into the EXE/DLL itself. Tools like IDR exist to heuristically analyze an EXE/DLL and compare its signature to a database of known compiler versions. How to detect Delphi compiler version in which exe was compiled?
  15. Remy Lebeau

    Don't use Application.MessageBox

    If the code is expecting a debugger to attach, I would just call IsDebuggerPresent() in a sleep loop until it returns true or times out.
  16. Remy Lebeau

    Menu boundaries from MenuHandle?

    You can't, as there is no way to get from the MenuHandle/HMENU to its dialog window. However, there can only be 1 menu active at a time, so you should be able to use FindWindow/Ex() to find the HWND of the active menu whose window class name is "#32768"/MAKEINTATOM(0x8000), Once you have the menu's HWND, you should be able to use GetWindowRect() to get its position and size.
  17. You can't have the 11.3 CE and 11.3 full versions installed on the same machine at the same time. This is stated in the FAQs. So you will have to uninstall 11.3 CE before installing 11.3 full. Otherwise, you can install the 12.x full version alongside the 11.3 CE version.
  18. Sorry, I don't have any examples to give you, as I don't write code for Android.
  19. You did not show the code that receives the file path from the file chooser and puts it into the TEdit, or show what the file path actually looks like. But ACTION_GET_CONTENT is documented as returning a "content:" uri, which requires you to use the ContentResolver class to access the file data. But TIdMultipartFormDataStream.AddFile() uses TFileStream, which wants direct access to the file, which will not work with a "content:" uri on modern Android versions. So you will likely have to either: access the file yourself via Android APIs and read its byte data into a TMemoryStream or TByteStream, or create a custom TStream that wraps an Android InputStream from the ContentResolver.openInputStream() method And then use TIdMultipartFormDataStream.AddFormField() instead of TIdMultipartFormDataStream.AddFile() to send whichever TStream you end up using. Alternatively, you can use ContentResolver to extract the underlying "file:" uri from a "content:" uri, and then you should be able to open the file using a normal TFileStream (provided you have permissions to the file). Also, when using ACTION_GET_CONTENT, the ACTION_GET_CONTENT documentation says to wrap your Intent with Intent.createChooser(), and also include CATEGORY_OPENABLE and FLAG_GRANT_READ_URI_PERMISSION on your Intent.
  20. Remy Lebeau

    Don't use Application.MessageBox

    Can to elaborate further? What is the actual error that you are getting? Note that TApplication.MessageBox() is generally just a wrapper for Winapi.MessageBox(). Although it is not entirely thread-safe, as it manipulates a global TaskActiveWindow list. So yes, using Winapi.MessageBox() directly is generally safer when displaying a message box in a worker thread.
  21. That's a contradiction. Either you have the permissions or you don't. What does your code look like that is asking the user for permission to access the file, and the code that tries to upload the file?
  22. Remy Lebeau

    TPanel + Mouse

    Just because the Labels are disabled does not mean the Panel will handle mouse activity when over them. You are still mousing over the Labels, so you need to catch and forward the event activity from the Labels if you want to handle them the same as events on the Panel. Otherwise, you can subclass the Panel to handle the underlying mouse messages before they get dispatched to children. Since the Panel is a windowed control and the Labels are graphical controls, the Panel is the one receiving the messages from the OS and passing them along to the Labels.
  23. Remy Lebeau

    A native VCL, and not Windows-based, TComboBox control.

    You say you have hundreds of TComboBoxes, but the screenshot above only shows 7 (presumably 11?). If this screen is similar for the rest of the app, where each item on the side list displays its own page with just a handful of ComboBoxes on it, then a simple solution would be to NOT load every page at one time, but instead to load one page at a time only when it is made visible to the user, and then unload it when it is no longer visible to the user. That will greatly speed up your load times, and then you don't have to resort to using hacks like owner-drawing, OnDropDown refreshes, etc. You can move each page to its own TFrame that you create and destroy when needed, that way you still regain design-time support for your page layout.
  24. Remy Lebeau

    GetIt Package Manager Delphi 11.3 Timeout

    Getit has not been restored for versions prior to RAD Studio 12.0 Athens yet.
  25. Remy Lebeau

    A native VCL, and not Windows-based, TComboBox control.

    Some suggestions: don't use WM_SETREDRAW directly. Use the TComboBox.Items.(Begin|End)Update() instead, which will use WM_SETREDRAW internally for you. CB_INITSTORAGE helps, but simply don't waste time putting actual string values in so many TComboBoxes to begin with. Instead, fill them with blank strings, and set their Style property to csOwnerDrawFixed and use their OnDrawItem event to render the actual text whenever a drop-down list is visible. consider using a different UI control, such as a TListBox, or a TListView in vsReport mode. Both have true virtual modes that can handle a lot of items very quickly.
×