Jump to content

Remy Lebeau

Members
  • Content Count

    2343
  • Joined

  • Last visited

  • Days Won

    95

Everything posted by Remy Lebeau

  1. Remy Lebeau

    Range check error (10016) on SetWindowLong

    Type-cast the 3rd parameter: SetWindowLong(thisform.Handle, GWL_STYLE, LONG(WS_POPUP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_SYSMENU)); Though, SetWindowLong() has been deprecated for a long time, as it doesn't support 64-bit apps. You really should be using SetWindowLongPtr() instead: SetWindowLongPtr(thisform.Handle, GWL_STYLE, LONG_PTR(WS_POPUP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_SYSMENU));
  2. Remy Lebeau

    Is Embarcadero's DocWiki down?

    Anyone else having trouble accessing https://docwiki.embarcadero.com ?
  3. Remy Lebeau

    Page Control

    Unfortunately, the underlying Win32 tab control which TPageControl is built on does not provide that information natively. The TPageControl.OnChanging event is fired BEFORE the active TabSheet changes, and the TPageContro.OnChange event is fired AFTER the active TabSheet is changed. So, you will have to keep track of the previous TabSheet in your own code, eg: private PreviousTabSheet: TTabSheet; procedure TForm1.PageControl1Changing(Sender: TObject; var AllowChange: Boolean); begin PreviousTabSheet := PageControl1.ActivePage; AllowChange := True; end; procedure TForm1.PageControl1Change(Sender: TObject); begin if PreviousTabSheet <> nil then begin // use PreviousTabSheet as needed... PreviousTabSheet := nil; end; end;
  4. Remy Lebeau

    Change 'DPI awareness' on runtime

    Embarcadero's DPI handling is still quite broken. They have taken several major releases to work on it, and it still has problems. You are probably best off simply disabling DPI awareness at the project level, and then scale your UI in your own code as needed.
  5. Remy Lebeau

    display hint

    You can either subclass the Gauge control to handle the CM_HINTSHOW message, or you can use the TApplication.OnShowHint/TApplicationEvents.OnShowHint event, to get access to a (pointer to a) THintInfo record, which has HintControl, HintStr, CursorPos, and CursorRect members (amongst other things). As the mouse moves around your UI, the THintInfo members will update accordingly. When the mouse moves from one control to another, the active hint gets reset. When the mouse stays inside of a given control and the CursorPos moves outside of the CursorRect, the active hint gets updated. This allows a control to sub-divide itself so it can have separate hints for different areas. So, if you want the hint to be updated with new text on every mouse move while the mouse is inside of the Gauge control, then whenever the THintInfo's HintControl is pointing at the Gauge control, you can simply set the THintInfo's CursorRect to a 1x1 pixel square at the current CursorPos coordinates, and set the HintStr to the desired text. This way, the next mouse move will go outside of the CursorRect and update the active hint with the new HintStr text. No, you do not.
  6. LoadFromStream() can potentially raise an exception, which will bypass your Free'ing of the TBitmap. Move LoadFromStream() inside the try..except block.
  7. Remy Lebeau

    Delphifeeds.com??

    Embarcadero took over DelphiFeeds 2 years ago to revive it: https://blogs.embarcadero.com/the-all-new-delphifeeds-com/ I guess they are not doing a very good job of that. Or, maybe they are just having system troubles? This wouldn't be the first time an Embarcadero system used by the community went down for weeks at a time.
  8. Remy Lebeau

    Access Violation using TVariantManager.VarToInt64

    I did, actually. I stated as much in my earlier reply:
  9. Remy Lebeau

    Access Violation using TVariantManager.VarToInt64

    You are instantiating a TVariantManager instance without populating it, so it has unassigned function pointers at the time you are calling VarToInt64(). You would need to call GetVariantManager() first to initialize the record before you can use it, eg: var v : Variant; N : Int64; VMGR : TVariantManager; begin v := 1234567890; if IsVariantManagerSet then begin GetVariantManager(VMGR); N := VMGR.VarToInt64(v); end; end; However, TVariantManager has been deprecated for a very long time (since sometime between D7..D2006, so approx 20 years!), so wherever did you get the idea that you need to use it in the first place? Since at least D2006 (maybe earlier), GetVariantManager() just fills the record with nil pointers, and IsVariantManagerSet() always returns False. In modern coding, simply assign the Variant directly to the Int64 variable and let the compiler handle the conversion for you, eg: var v : Variant; N : Int64; begin v := 1234567890; N := v; // compiler generates: N := System.Variants._VarToInt64(v); end;
  10. Remy Lebeau

    generics

    Have you read the official documentation yet? https://docwiki.embarcadero.com/RADStudio/en/Generics_Index
  11. Remy Lebeau

    General Question

    That is an app-specific internal folder, so it should get deleted on app uninstall. Are you saying that is not the case? If so, then you will have to take up that issue with Google.
  12. Remy Lebeau

    NetHTTPCLient, NetHTTPRequest and CURL

    Why are you using 'string' for binary data? Don't do that. Use TBytes/TArray<Byte> for that instead. And then you can wrap that with TBytesStream instead of TMemoryStream (avoiding an unnecessary copy) Or, just pass your TMemoryStream into ZipAddJson() and let it Write() its bytes directly to the stream (again avoiding an unnecessary copy). Either way, you are not Seek()'ing the stream back to Position 0 before calling AddStream().
  13. Remy Lebeau

    In fmx how can i display files from a website to a combobox

    There is no facility in the HTTP or HTML standards for a web server to provide a list of files on the server. If a webpage does offer such a list, it does so manually, so you will have to download that page's HTML and parse it yourself to extract the list. There is no standard format for this.
  14. Remy Lebeau

    General Question

    That does not sound right. TPath.GetDocumentsPath() is documented as using Android's Context.getFilesDir() method, and Android documents that as an app-specific internal folder that gets removed during app uninstall. Clearly. But the question is, why? What path does TPath.GetDocumentsPath() actually return on your device? It must be using a public/shared folder, rather than an internal app-specific folder.
  15. Remy Lebeau

    NetHTTPCLient, NetHTTPRequest and CURL

    It expects that in the URL itself? That is extremely odd. But even so, that doesn't change anything I said earlier. The code I provided, for both TNetHTTPClient and TIdHTTP, sends a POST in 'multipart/form-data' format, same as curl's CURLOPT_MIMEPOST option does. This is a standardized format. So, what exactly is the server complaining about this when using the code I gave you? Then please show the RAW request that curl is actually transmitting (which you can get by using the CURLOPT_VERBOSE and CURLOPT_DEBUGFUNCTION options), compared to the RAW requests that TNetHTTPClient and TIdHTTP are transmitting (not sure how to get that info with TNetHTTPClient, but for TIdHTTP you can assign any TIdLog... component to the TIdHTTP.Intercept property). In what way, exactly? Oh, so that data is not in the URL, but actually in the POST body? That makes more sense. But even so, the code I gave you should be posting that data just fine. Whatever bytes you put into the TStream will get transmitted to the server. Can you be more specific? Of course, according to the MIME standards for the 'multipart/form-data' format. Yes, you do, because that is what the original curl code is doing, too.
  16. Remy Lebeau

    Add text to existing metafile

    I don't know if this is covered in the documentation (I can't find it), but in TMetaFile's source code is the following comment: So, you just need to Draw() the existing TMetaFile onto the TMetafileCanvas before drawing anything else onto the Canvas - hmmm, but you are already doing that! Looking at the docs and the source code, TMetafileCanvas should not be clearing anything in the TMetaFile at all. Also, the ReferenceDC in the TMetaFileCanvas constructor can be 0, in which case the screen HDC will be used instead. Based on the info above, you don't need a clone at all, since modifications made to the Canvas will be applied to the original TMetaFile only when the Canvas is destroyed, eg: OrigMF := // my metafile in memory MFCanvas := TMetafileCanvas.Create(OrigMF, 0); try MFCanvas.Draw(0, 0, OrigMF); // Draw my stuff on MFCanvas finally MFCanvas.Free; end;
  17. Remy Lebeau

    Where is the VC++ option check box

    I don't have 11.2.1 to verify this, but the checkbox should be in the initial dialog when creating a new DLL project. It is not something you can toggle in the Project Options after the project is created.
  18. Both TTreeNode.Level and TTreeNode.HasAsParent() are recursive, they walk the entire TTreeNode.Parent chain until the root of the tree is reached, or in the case of HasAsParent(), until the specified node is reached. You don't really need that recursiveness in your situation. Paul's solution is more efficient and will suit your situation just fine: if Assigned(Node.Parent) then // or: if Node.Parent <> nil then begin strParentText := Node.Parent.Text; end; Alternatively, to eliminate a redundant function call: var myParentNode: TTreeNode := Node.Parent; if Assigned(myParentNode) then // or: if myParentNode <> nil then begin strParentText := myParentNode.Text; end;
  19. Remy Lebeau

    NetHTTPCLient, NetHTTPRequest and CURL

    Using TNetHTTPRequest, you can do something like this: type TReadOnlyMemoryBufferStream = class(TCustomMemoryStream) public constructor Create(APtr: Pointer; ASize: NativeInt); function Write(const Buffer; Count: Longint): Longint; override; end; constructor TReadOnlyMemoryBufferStream.Create(APtr: Pointer; ASize: NativeInt); begin inherited Create; SetPointer(APtr, ASize); end; function TReadOnlyMemoryBufferStream.Write(const Buffer; Count: Longint): Longint; begin Result := 0; end; ... DataStream := TReadOnlyMemoryBufferStream.Create(databuf, data_len); try PostData := TMultipartFormData.Create; try PostData.AddStream('data', DataStream, 'filename', 'application/octet-stream'); NetHTTPRequest1.Post(url, PostData); finally PostData.Free; end; finally DataStream.Free; end; Using Indy's TIdHTTP instead, you can do this: DataStream := TIdReadOnlyMemoryBufferStream.Create(databuf, data_len); try PostData := TIdMultiPartFormDataStream.Create; try PostData.AddFormField('data', 'application/octet-stream', '', DataStream, 'filename'); IdHTTP1.Post(url, PostData); finally PostData.Free; end; finally DataStream.Free; end;
  20. Remy Lebeau

    Custom component on a VCL frame

    The message's coordinates are expressed as screen coordinates, but a control's BoundsRect is expressed as client coordinates within the parent's client area. So, you would need to normalize the two sets of coordinates to the same coordinate space before you can compare them. Also, it turns out that TWinControl already handles CM_DESIGNHITTEST, by forwarding the message to any child control that is at the specified coordinates. By default, TControl returns 0 for the message's result. So, another option may be to have your Frame class subclass its child controls and have them unconditionally return 1 for CM_DESIGNHITTEST, instead of handling the message at the TFrame level. Just a thought. That flag only affects right mouse clicks, by converting them into left mouse clicks. Maybe. I've never tried to make a component out of a Frame before. Have you tried basing the component on TPanel instead?
  21. Remy Lebeau

    Custom component on a VCL frame

    You can add a message handler to the Frame class to handle the CM_DESIGNHITTEST message, setting the message's result to 1 if the mouse is over a child control within the Frame's client area. That will allow the child control to handle the mouse click.
  22. There is always Indy's TIdHTTP component The standard TIdSSLIOHandlerSocketOpenSSL component will support up to TLS 1.2 with OpenSSL 1.0.2, and this WIP SSLIOHandler will handle TLS 1.3 with OpenSSL 1.1+.
  23. I don't know. Worse case, you could simply not install Indy into the IDE at all, and just have your project refer to Indy's source files directly.
  24. In this code: var LDay: TSysDay; LFieldName: string; LFieldName := GetAttribute(LDay.Day); You are passing in the value that is returned by reading the Day property. You are not passing in the property itself. You can't pass around properties, that is simply not allowed. You will have to pass in the property's name as a string and use RTTI to access it, eg: function GetFieldAttribute(Obj: TObject; const PropName: string): string; var LC: TRttiContext; LT: TRttiType; LP: TRttiProperty; LA: TCustomAttribute; begin Result := ''; LC := TRttiContext.Create; try LT := LC.GetType(Obj.ClassType); LP := LT.GetProperty(PropName); if LP <> nil then begin for LA in LP.GetAttributes() do begin if LA is TFieldNameAttribute then Exit(TFieldNameAttribute(LA).Name); end; end; end; finally LC.Free end; end; var LDay: TSysDay; LFieldName: string; LFieldName := GetFieldAttribute(LDay, 'Day'); LFieldName := GetFieldAttribute(LDay, 'A'); LFieldName := GetFieldAttribute(LDay, 'B'); LFieldName := GetFieldAttribute(LDay, 'C');
  25. https://github.com/IndySockets/Indy/wiki/Updating-Indy
×