Jump to content

Remy Lebeau

Members
  • Content Count

    2988
  • Joined

  • Last visited

  • Days Won

    134

Everything posted by Remy Lebeau

  1. Remy Lebeau

    How to solve System Out of Resources in TScrollBox

    There are three options for influencing the height of TListView items: 1. Assign an ImageList of desired size. 2. Assign a Font of sufficient size. 3. Owner-draw the TListView and handle the WM_MEASUREITEM notification in the parent window (or subclass the TListView to handle CN_MEASUREITEM). No, there is not.
  2. By default, Pascal-generated HPP headers bring their C++ namespaces into the namespace that is #include'ing the HPP file (which is usually the global scope). So, in this case, there are two Fmx namespaces in the same scope, and the compiler ends up picking your namespace instead of FireMonkey's, which is why it can't find the Fmx::Controls namespace. If you look at your HPP files, you will notice that there are 'using namespace' statements at the bottom which are wrapped in preprocessor blocks, eg: #if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_EHLIB_FMX_TYPE) using namespace EhLib.Fmx.Type; #endif #if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_EHLIB_FMX) using namespace EhLib.Fmx; #endif #if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_EHLIB) using namespace EhLib; #endif To avoid this ambiguity, you can specify either DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE or the desired NO_USING_NAMESPACE_... conditional(s) in the "Conditional defines" section of your C++ project's settings. Or, at least, simply #define them above the relevant #include statement(s) in your C++ code. Alternatively, another workaround would be to add {$HPPEMIT NOUSINGNAMESPACE} to your Pascal units to avoid any 'using namespace' statements in their generated HPP files.
  3. In fact, this is likely the root culprit of your other issue, as you probably have multiple Fmx namespaces in the same scope that are interfering with each other. In addition to what I mentioned above, another workaround would be to add {$HPPEMIT NOUSINGNAMESPACE} to your Pascal units to avoid any 'using namespace' statements in their generated HPP files.
  4. Yes, it does. You just have to be a little strategic with it. That is correct. By default, Pascal-generated HPP headers bring their C++ namespaces into the namespace that is #include'ing the HPP file (which is usually the global scope). And since both Vcl namespaces are in the same scope, the compiler doesn't know which one to use, hence the ambiguity error. If you look closer at the HPP files, you will notice that those 'using namespace' statements are wrapped in preprocessor blocks, eg: #if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_VCL_BUTTONS) using namespace Vcl::Buttons; #endif #if !defined(DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE) && !defined(NO_USING_NAMESPACE_VCL) using namespace Vcl; #endif To avoid the ambiguity, you can specify either DELPHIHEADER_NO_IMPLICIT_NAMESPACE_USE or the desired NO_USING_NAMESPACE_... conditional(s) in the "Conditional defines" section of your C++ project's settings. Or, at least, simply #define them above the relevant #include statement(s) in your C++ code.
  5. Remy Lebeau

    How to solve System Out of Resources in TScrollBox

    Correct. If you want to use your Frames, then I would suggest using a plain TPanel, put your visible Frames on it, and then use a separate TScrollBar to "scroll" through your data, updating the Frames accordingly. If you want to use a virtual TListView, you will have to custom-draw anything beyond simple text. You can try using the TListItem.SubItemImages property or TListView.OnGetSubItemImage event, but I'm not sure if those work in virtual mode or not. I have never used them. I always custom-draw my own images. You can't add an actual button control to a TListView item. You would have to custom-draw an image of a button instead, and then handle the TListView.OnMouse(Down|Up) events to know where the user is clicking within the TListView. You can use the TListView.GetItemAt() and TListView.GetHitTestInfoAt() methods to know which item is underneath the mouse, and in some cases even which portion of the item. However, in the case of your eye button, that is not granular enough, so I would suggest sending an LVM_SUBITEMHITTEST message to the TListView window, which will tell you the item and column indexes that are at a given coordinate. And if needed, there is also the LVM_GETSUBITEMRECT message which gets the display coordinates of a given column within an item.
  6. Remy Lebeau

    [bcc32c Error] hpp: expected unqualified-id

    The Win32 constants are being declared in the SDK using #define statements, which are parsed during the preprocess stage, and are just straight text replacements. As such, they don't respect C++ namespaces at the compile stage, as the code has already been modified by the preprocessor before the compiler sees it. Thus, the compiler will not see this code, as you expect: namespace Ehlibfmx { namespace Toolcontrols { static _DELPHI_CONST System::Int8 SB_HORZ = System::Int8(0x0); } } But will see this code instead: namespace Ehlibfmx { namespace Toolcontrols { static _DELPHI_CONST System::Int8 0 = System::Int8(0x0); } } Which is a syntax error in the C++ language.
  7. Remy Lebeau

    [bcc32c Error] hpp: expected unqualified-id

    Those constants are already defined in the Win32 SDK headers (specifically, in winuser.h) using #define macros: /* * Scroll Bar Constants */ #define SB_HORZ 0 #define SB_VERT 1 #define SB_CTL 2 #define SB_BOTH 3 That will interfere with any C++ code that tries to use your constants for ANY reason (including the declarations!). For example: static _DELPHI_CONST System::Int8 SB_HORZ = System::Int8(0x0); This will be misinterpreted by the C++ compiler as the following instead, hence the error you are getting: static _DELPHI_CONST System::Int8 0 = System::Int8(0x0); To avoid this, don't redeclare Win32 constants in C++. Declare your constants in your Pascal unit as {$EXTERNALSYM} (or {$NODEFINE}) so they are omitted in your generated HPP file: const { Scroll Bar Constants } {$EXTERNALSYM SB_HORZ} SB_HORZ = 0; {$EXTERNALSYM SB_VERT} SB_VERT = 1; {$EXTERNALSYM SB_CTL} SB_CTL = 2; {$EXTERNALSYM SB_BOTH} SB_BOTH = 3; Alternatively, change your Pascal unit to use the constants that are already declared in the Winapi.Windows unit, which are EXTERNALSYM'ed (just be sure to {$IFDEF} that unit since you appear to be coding for FMX).
  8. Remy Lebeau

    Earlier version of C++ Builder program

    And, the point of this post is... what, exactly? I don't see a question or problem stated. However, why were you ever mixing C's <conio.h> with C++'s <iostream> in the first place? Get rid of <conio.h>, you don't need it. Use std::cin.get() instead of getch().
  9. Remy Lebeau

    How to solve System Out of Resources in TScrollBox

    Set TListView.OwnerData=true, set TListView.Items.Count to the number of items you want to display, and use the TListView.OnData event to provide details for each item on demand. The scrollbar will be handled for you. Because those are TListBox styles, not TListView styles. In this situation, set TListView.ViewStyle=vsReport, and add some columns to the TListView.Columns. Then, in the TListView.OnData event, you can provide data for the 1st column using TListItem.Caption, and data for the subsequent columns using TListItem.SubItems. Use the TListView.OnData... events for that purpose. Yes. Probably because you didn't populate the TListView with data yet (see above). Yes. You should not be putting any child controls on to the TListView at all. It is not designed for that. Let it handle the items for you. You just worry about supplying the items with data. And using the TListView.On...Draw... events if you want to custom-draw the items. No. It is just a wrapper for the native behavior provided by Microsoft, see: How to Use Virtual List-View Controls
  10. Remy Lebeau

    This is a change

    That is an extremely old header file for DOS development. If you are using C++ iostreams for console I/O (as you should be, ie std::cin and std::cout) then you don't need that header. Or std::cin.get(). But yes, to keep the window open, you have to wait for user input. Otherwise, open the console window first before then running the program in it. The window closes automatically only if the program launched the window in the first place. When you run a console program directly, it creates a new console window for itself. Not that I'm aware of. But without seeing the actual code, it is difficult to explain what you are experiencing.
  11. Does EhLib.Fmx.Types.pas have the FMX.Controls unit in its 'interface' uses clause? Does the generated EhLib.Fmx.Type.hpp file have an #include <FMX.Controls.hpp> statement?
  12. Remy Lebeau

    Folder ReadOnly, Hidden, Normal

    Nothing. ReadOnly has no meaning for a folder and is ignored. This is documented behavior: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-setfileattributesw Making a folder read-only is an illusion. When you do it in Explorer, it iterates the folder's files and updates them accordingly. You can't change the attribute on the folder itself. Doing so is reserved by Windows for its private use on system folders. You cannot view or change the Read-only or the System attributes of folders in Windows Server 2003, in Windows XP, in Windows Vista or in Windows 7
  13. Show off 😉 Thanks, I have added it to the bug report.
  14. That is not what I would call a MINIMAL example, but at least it compiles this time. There is still a lot of IRRELEVANT code that has nothing at all to do with demonstrating the issue at hand. But so be it. Your TBaseConnectionParams and TSqliteParams classes are duplicating similar code because THEY ARE RETURNING DIFFERENT THINGS, so how to do you expect one to just inherit the behavior of the other? They can't. If you really want to make use of class inheritance then you need to simplify the design of the common elements so they are coherent and overridable across descendants. You are not even override'ing the base methods, you are reintroduce'ing them. That is not how inheritance works.
  15. Remy Lebeau

    filenames with unicode chars

    @David Heffernan who are you directing that to?
  16. Remy Lebeau

    Should I just dive in to GUI programs?

    You don't need to change the AppType to use WriteLn(). A GUI app can simply call AllocConsole() or AttachConsole() and then WriteLn() will automatically work. That being said, another way to debug would be to use OutputDebugString() instead, and then you can see the messages in the IDE's debugger, or in SysInternals DebugView when running outside of the debugger.
  17. I can reproduce the problem in a simple example that doesn't involve Spring4D (however, I get an "E2010 Incompatible types" error instead of an E2250) : type IShared<T> = reference to function: T; Shared = class class function Make<T: class>(AObj: T): IShared<T>; end; TSharedImpl<T: class> = class(TInterfacedObject, IShared<T>) FObj: T; constructor Create(AObj: T); destructor Destroy; override; function Invoke: T; end; TTest = class end; TTester = class procedure DoTest(AObj: TTest); end; class function Shared.Make<T>(AObj: T): IShared<T>; begin Result := TSharedImpl<T>.Create(AObj) as IShared<T>; end; constructor TSharedImpl<T>.Create(AObj: T); begin inherited Create; FObj := AObj; end; destructor TSharedImpl<T>.Destroy; begin FObj.Free; inherited Destroy; end; function TSharedImpl<T>.Invoke: T; begin Result := FObj; end; procedure TTester.DoTest(AObj: TTest); begin //... end; procedure Foo1; var Tester : IShared<TTester>; TestObj : IShared<TTest>; begin Tester := Shared.Make(TTester.Create); TestObj := Shared.Make(TTest.Create); Tester.DoTest(TestObj); // <-- Compiles OK! end; procedure Foo2; begin var Tester: IShared<TTester>; var TestObj: IShared<TTest>; Tester := Shared.Make(TTester.Create); TestObj := Shared.Make(TTest.Create); Tester.DoTest(TestObj); // <-- E2010 Incompatible types: 'TTest' and 'IShared<TTest>' Tester.DoTest(TestObj()); // <-- Compiles OK! end; I have now reported this issue to Embarcadero: RSS-2613: Anonymous Method is called differently depending on whether it is declared as an Inline Variable or not
  18. Remy Lebeau

    filenames with unicode chars

    Just like in the example I gave you in my last reply, in this case I'm guessing that R.Name[10] is 0x0065 (Latin Small Letter E) and R.Name[11] is 0x0301 (Combining Acute Accent), whereas you are expecting R.Name[10] to be 0x00E9 (Latin Small Letter E with Acute) instead. To accomplish what you want, you should normalize the Unicode characters, probably to form NFC, before you can then process and replace them. Read the following for more details: Unicode Standard Annex #15: Unicode Normalization Forms Using Unicode Normalization to Represent Strings NormalizeString function I realize that. But that is reserved for markup language in plain text. You need to actually click on the '</>' button in the toolbar and put your code in the resulting popup dialog.
  19. I'm sorry, but the code you have provided is full of errors, I can't even attempt to compile it as-is, and I'm not going to waste my time trying to fix it all. When you can provide an example that can be COPY/PASTED as-is (or better, provide the actual files as attachments), and it can compile and produce a specific compiler error that you are trying to fix, then I will be happy to look at it again.
  20. Remy Lebeau

    filenames with unicode chars

    One issue I see is you are not taking into account either UTF-16 surrogates, or Unicode combining codepoints. Not all Unicode characters take up 1 WideChar, sometimes they require 2+ WideChars, especially if they are not in a normalized form. For example, the character 'á' may be 1 WideChar 0x00E1 (Latin Small Letter A with Acute), or it may be 2 WideChars 0x0061 (Latin Small Letter A) and 0x0301 (Combining Acute Accent) working together. What are the actual numeric values of the WideChars that you are actually receiving for the filename you are having trouble with? That is because you are posting the code as plain text. Put it inside of a code block instead (the '</>' button on the editor toolbar). For example: void sayHi() { cout << "This is in a code block!"; }
  21. Can you trim that down to a MINIMAL example that actually exhibits the problem? Most of that code is irrelevant to the issue. Are you getting a compiler error? If so, what is it? What EXACTLY are you trying to implement that you think is missing?
  22. Any class that derives from TBaseFoo inherits the methods that TBaseFoo implements. Why do you think any workaround is needed? What is the actual PROBLEM you are having with your code in the first place?
  23. Remy Lebeau

    filenames with unicode chars

    Feel free to step into the RTL source code for yourself with the debugger (see the code below). On Windows, the RTL's Find(First|Next)() functions simply call the API Find(First|Next)FileW() functions and then copy the WIN32_FIND_DATA fields into the TSearchRec fields: function FindFirstFile; external kernelbase name 'FindFirstFileW'; function FindNextFile; external kernelbase name 'FindNextFileW'; ... function FindMatchingFile(var F: TSearchRec): Integer; ... begin while F.FindData.dwFileAttributes and F.ExcludeAttr <> 0 do if not FindNextFile(F.FindHandle, F.FindData) then begin Result := GetLastError; Exit; end; ... F.Name := F.FindData.cFileName; // <-- HERE Result := 0; end; function FindFirst(const Path: string; Attr: Integer; var F: TSearchRec): Integer; const faSpecial = faHidden or faSysFile or faDirectory; begin F.ExcludeAttr := not Attr and faSpecial; F.FindHandle := FindFirstFile(PChar(Path), F.FindData); if F.FindHandle <> INVALID_HANDLE_VALUE then begin Result := FindMatchingFile(F); // <-- HERE if Result <> 0 then FindClose(F); end else Result := GetLastError; end; function FindNext(var F: TSearchRec): Integer; begin if FindNextFile(F.FindHandle, F.FindData) then Result := FindMatchingFile(F) // <-- HERE else Result := GetLastError; end; As you can see, the API's WIN32_FIND_DATA::cFileName is assign as-is to the RTL's TSearchRec::Name field, and since both field are based on WideChar (WIN32_FIND_DATA::cFileName is a WideChar[] array and TSearchRec::Name is a UnicodeString) then there is no manipulation of the reported characters in any way, they are copied as-is. What you get back in your code SHOULD be exactly what Windows actually reported. The TSearchRec::FindData field is the raw WIN32_FIND_DATA data that Find(First|Next)File() actually reported.
  24. The TTestFoo class inherits all of the implemented methods of the TBaseFoo class. This is literally how class inheritance works. I don't understand the question. However, interface inheritance works a little different. Sometimes you have to make sure that a derived class explicitly declares all of the interfaces it supports - even the base ones - and not rely on inheritance alone to do that for you, eg: TTestFoo = class(TBaseFoo, IBaseFoo, ITestFoo) // automatically inherits the methods of TBaseFoo... procedure TestFooMethod; end;
  25. Remy Lebeau

    filenames with unicode chars

    The RTL's Find(First|Next)() functions use the Win32 Find(First|Next)FileW() APIs internally, and have done so since 2009. That might be related to the removal of the Form's OldCreateOrder property in RAD Studio 11. But, you should never have been using the OnCreate (and OnDestroy) event(s) in C++ anyway, as that has always had the potential of introducing Undefined Behavior in user C++ code due to the different creation models between Delphi vs C++. Use the Form's constructor (and destructor) instead, that is always safe. And streamed property values are available in the constructor.
×