-
Content Count
2685 -
Joined
-
Last visited
-
Days Won
113
Everything posted by Remy Lebeau
-
TEncoding.Unicode represents bytes in UTF-16LE format. VERY RARELY will you ever need to use TEncoding.Unicode (or TEncoding.BigEndianUnicode) in real production code. Most uses of Unicode<->byte conversions involve converting between Unicode and UTFs, or Unicode and charsets. So, it is much more common to use TEncoding.UTF8, TEncoding.Default (TEncoding.ANSI on Windows, TEncoding.UTF8 on POSIX platforms), or TEncoding.GetEncoding(<charset>).
-
Agreed. And believe me, it has been requested many many times, but for whatever reason Embarcadero has continued to decide not to provide it.
-
Better to use SysUtils.TEncoding.GetString(), then no intermediate AnsiString is needed. procedure TForm1.Button1Click(Sender: TObject); var ANameSpace : Variant; AFolderItem : Variant; AMailItem : Variant; RTFBody : array of Byte; RTFString : String; begin OutlookApplication1.Connect; ANameSpace := OutlookApplication1.GetNameSpace('MAPI'); AFolderItem := ANameSpace.GetDefaultFolder(olFolderInbox); AMailItem := AFolderItem.Items(1); RTFBody := AMailItem.RTFBody; RTFString := TEncoding.Default.GetString(RTFBody); Memo1.Lines.Add(RtfString); end;
-
another StrToDateTime question
Remy Lebeau replied to PavelX's topic in RTL and Delphi Object Pascal
Or the GMTToLocalDateTime() function, also in the IdGlobalProtocols unit. StrInternetToDateTime() ignores the timezone specified in the input string and just returns the date/time as-is. GMTToLocalDateTime() adjusts the date/time into UTC using the specified timezone, and then adjusts the UTC into the local timezone on output. -
TIDSmptServer does not receive mail from certain client [Fixed]
Remy Lebeau replied to mvanrijnen's topic in Indy
Actually, it should not be, otherwise the OnBeforeMsg event would not be fired, but the log clearly shows that it is. TIdSMTPServer fully supports BDAT. After firing the OnBeforeMsg event, it will read the 350 bytes that the client claims to be sending, and then it will send a 250 reply, and wait for the next BDAT command to arrive. The real issue I see is that the failing client is issuing a QUIT command before sending a final "BDAT ... LAST" command to indicate the email data is done being sent. That is why the OnMsgReceive event is not being fired. I agree, though, that the logging should be expanded to include the server's actual responses. -
Did you try the WH_CBT hook, like I suggested? For example: uses ..., Windows; type TPrintLLReportEventHandler = class private FHook: HHOOK; public constructor Create; destructor Destroy; override; procedure OnViewerButtonClicked(Sender: TObject; Button: TViewerButton; var PerformDefaultAction: Boolean); end; { TPrintLLReportEventHandler } var gPrintReportWnd: HWND = 0; function CBTProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; begin if nCode = HCBT_ACTIVATE then begin if gPrintReportWnd = 0 then gPrintReportWnd := HWND(wParam); end; Result := CallNextHookEx(0, nCode, wParam, lParam); end; constructor TPrintLLReportEventHandler.Create; begin inherited; gPrintReportWnd := 0; FHook := SetWindowsHookEx(WH_CBT, @CBTProc, HInstance, GetCurrentThreadId); end; destructor TPrintLLReportEventHandler.Destroy; begin if FHook <> 0 then UnhookWindowsHookEx(FHook); gPrintReportWnd := 0; inherited; end; procedure TPrintLLReportEventHandler.OnViewerButtonClicked(Sender: TObject; Button: TViewerButton; var PerformDefaultAction: Boolean); begin if Button = vbExit then begin MessageBox(gPrintReportWnd, ...); end; end; var evh: TPrintLLReportEventHandler; begin evh := TPrintLLReportEventHandler.Create; try MyLLReportInstance.OnViewerButtonClicked := evh.OnViewerButtonClicked; // Show preview here (using LL_PRINT_PREVIEW) finally evh.Free; end; end;
-
Reading the TListItem.Top property calls TListItem.GetPosition() and returns its Y value. GetPosition() calls ListView_GetItemPosition(), which should work the same in virtual and non-virtual modes. The ListView knows the position and sizes of its list items, it just does not know what data they contain in virtual mode. If you call ListView_GetItemPosition() directly, does it return TRUE or FALSE? I use TListView in vsReport style in virtual mode, and I find it better (and more efficient) to use the Win32 API directly rather than using TListItem for most operations. To scroll to a specific item, I call ListView_EnsureVisible(), then if I want that item to appear at a specific position then I call ListView_GetItemRect() (which TListItem.DisplayRect() calls) and ListView_GetTopItem(), and then TListView.Scroll() for the difference. Right, because I said above, a ListView knows the position and size of its items, in virual and non-virtual modes alike.
-
I don't know what kind of control "TL21_" is supposed to refer to, but if it does not expose access to its HWND, one option would be to use a thread-local WH_CBT hook via the Win32 SetWindowsHookEx() function to receive notifications of every HWND that is created by the thread. For instance, set the hook just before displaying the preview Form, and then release the hook after the Form is ready/closed. Then you will know every HWND that the preview creates.
-
[WebBrowser] how to get url on click a href in TWebbrowser
Remy Lebeau replied to Juan Young's topic in Cross-platform
Odd. Are you ABSOLUTELY SURE that those event handlers are actually assigned to the TWebBrowser? -
A class named TOAuth1SignatureMethod_PLAINTEXT already exists.
Remy Lebeau replied to psla314's topic in RTL and Delphi Object Pascal
Are you sure about that? I don't use the REST stuff, but seems to me like that should be in its own separate package, not cluttering the RTL. Just because the exception's stack trace mentions rtl250.bpl does not mean the REST stuff resides in the RTL itself. The runtime class registration functionality is in the RTL, which other packages can then call into to share their classes with each other (among other things). I suggest you hunt down the real package that the REST stuff actually resides in, and make sure your 2 DLLs are using that package dynamically rather than statically. -
If you don't want to run the whole app elevated, and don't want to use a separate elevated process for the sync code, you could separate the sync code into a COM object, and then the main app can run unelavated and load the COM object elevated when needed by using the COM Elevation Moniker. This way, everything is kept in a single process.
-
There is a free Community Edition available. What is the EXACT error message? Does it say WHICH dpr file is missing? Maybe your project has a dependency that is missing? Can you provide your project's file hierarchy, setup, etc?
-
TIdSNTP.SyncTime() uses the Win32 SetLocalTime() function, which requires the calling process to have the SE_SYSTEMTIME_NAME privilege present in its user token (even if it is not enabled, it just needs to be present - SetLocalTime() will enable it for the duration of the call). By default, only an elevated admin has that privilege present in its token. So, you will have to either run your whole app as an elevated user, or at least split out your sync code into a separate process or service that runs as an elevated admin or the SYSTEM account.
-
Can 32bit dll with Form/Frame be used in 64 bit project?
Remy Lebeau replied to Mike Torrettinni's topic in VCL
Right idea, but wrong solution. A DLL Surrogate can be registered to act as a proxy, allowing a 32bit DLL server to be accessible to a 64bit process. Not sure if this will work for your ActiveX control since it uses a UI, but it might be worth investigating. For that to work correctly, you would need to make a BPL package, not a plain DLL. But the same 32bit/64bit restriction applies to packages, too. No, a 32bit DLL/BPL cannot be used directly in a 64bit process. If the above doesn't work for your control, you may have to separate out your UI into its own 32bit program, and have your main 64bit program communicate with it using an IPC mechanism. -
Well, I don't have 10.4.1 installed (or the sources for it), so there you go, just shows how little I know
-
I doubt that Delphi has natively imported the MediaStore.Images.Media class, but you should be able to import it manually using Java2OP, then you can access the EXTERNAL_CONTENT_URI field like this, eg: var pickIntent: JIntent; // replace TJMediaStore_Images_Media with whatever name Java2OP imports for it... pickIntent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_PICK, TJMediaStore_Images_Media.JavaClass.EXTERNAL_CONTENT_URI);
-
How to detect if TIDMessage is unable to read an email
Remy Lebeau replied to Mark Williams's topic in Indy
TIdMessage is designed to parse RFC822-style emails only (EML files, etc). Attempting to load anything else is basically undefined behavior, there is no guarantee if/how errors will be reported back into user code. There is no single point of query where you can discover the result of a failed parse. So, your best option is to just filter out non-RFC822 files before you try to load them into TIdMessage. Basically, analyze a handful of bytes at the beginning of a given file, and if they don't appear to resemble RFC822-style headers then simply don't load the file at all (all of the non-EML file formats you have mentioned are well-documented and easily identifiable). This is something I may consider adding to TIdMessage itself in a future release, but that is not going to happen anytime soon, so I suggest you add it to your own code. -
In non-virtual mode, each list item has its own physical TListItem object in memory, and their respective data is stored directly in the ListView control itself (well, in its HWND, anyway). In virtual mode, all data is held in the user's code instead. There is only 1 physical TListItem created, used internally by the TListView, where its content is reset each time an operation is performed that requires a physical TListItem object. For instance, when reading the TListView.Items[index] property, or calling method that takes a TListItem as input or returns a TListItem as output. IN MOST CASES, this design allows non-virtual code to continue working the same way as in non-virtual mode, just with the addition of the OnData... event handlers. But there are some corner cases to be aware of where this design does not work as expected, for instance doing tasks that require access to more than 1 TListItem at the same time. Your example demonstrates this when by causing an operation that resets the TListItem that is being observed.
-
The TIdMessage.Date property is expressed in LOCAL TIME, not in UTC. The only way the TIdMessage.Date property would be in UTC is if either the calling machine is actually in the UTC timezone (which you say is the case here), or if Indy can't determine the local machine's timezone correctly. If you want to read an email's original timestamp (which may or may not be in UTC to begin with), you can read the raw 'Date' header via the TIdMessage.Headers.Values['Date] property. But then you will have to parse the string yourself.
-
If you can't update the app to use SSL/TLS, then yes. That is an option, yes. Though, using a full SMTP server (ie TIdSMTPServer) might be a bit excessive, a simpler connection proxy (such as TIdMappedPortTCP) might suffice, since you just need to activate SSL/TLS on the outgoing connection. It really depends on whether you intend to utilize the SMTP STARTTLS command or not, since that will dictate WHEN the SSL/TLS handshake needs to be performed.
-
Batch Reading Emails from Windows Explorer
Remy Lebeau replied to Mark Williams's topic in General Help
Only if you are planning on compiling the IdCoderTNEF unit into the IndyProtocols package each time. Which you don't NEED to do, you could simply drop IdCoderTNEF.pas into your project folder, or Indy source folder, and have your project(s) refer to that unit as-is. No. -
Runtime create new "fields" with RTTI on a tComponent
Remy Lebeau replied to microtronx's topic in RTL and Delphi Object Pascal
All of that applies to T(Object)Dictionary, as well. If the TComponent or associated object is freed, you have to manually remove them from the dictionary to avoid dangling pointers. TDictionary doesn't support object management at all. TObjectDictionary, on the other hand, simply lets you specify whether the dictionary owns the objects stored as Keys/Values, in that if an entry is removed/altered in the dictionary, the associate Key/Value objects are freed automatically as needed. But, if those same objects are freed external to the dictionary, the dictionary entry that refers to them is not removed automatically. You still have to handle that manually. The likelihood is reduced, but not eliminated. It is still possible to have invalid references, if you are not careful. In your code, perhaps, but not the overhead needed to manage the dictionary elements, hash tables, etc. You are actually adding runtime overhead to the program just to gain writing simpler code. But whatever. It is up to each user to decide whatever they are comfortable using. -
Runtime create new "fields" with RTTI on a tComponent
Remy Lebeau replied to microtronx's topic in RTL and Delphi Object Pascal
There is nothing wrong with using the Tag property for pointers. It is specifically intended to hold user-defined data, and intentionally pointer-sized because storing pointers in it is very common practice. It is even documented that way So, there is no misuse here. That is your choice, and it will certainly work. I prefer to use the Tag instead, it offers a 1:1 relationship without any overhead of a lookup table. -
Batch Reading Emails from Windows Explorer
Remy Lebeau replied to Mark Williams's topic in General Help
It is not enough to just add the file to the folder, you would have to actually edit the IndyProtocols package to reference the file. Because it is still being used by the IDE. You would have to remove Indy from the IDE first. Have you read the installation instructions yet?