-
Content Count
2942 -
Joined
-
Last visited
-
Days Won
133
Everything posted by Remy Lebeau
-
That is a very dangerous approach. Don't do it that way. First, there is no guarantee that accessing the ClassName on an invalid object will raise an exception. And second, reading from invalid memory may cause other side effects (ie, page faults, etc). Since your integers are very small, then you could simply look for integers first, and treat higher values as objects since they should never reside at such low memory addresses, eg: const MaxObjIntValue = 8; ... var value := NativeInt(Objects[c,r]); if (value >= 0) and (value <= MaxObjIntValue) then begin // is an integer, use value as needed... end else begin // is an object, use TObject(value) as needed... end ... if NativeInt(Objects[c,r]) > MaxObjIntValue then Objects[c,r].Free;
-
How does that code have anything to do with the discussion at hand? Also, why would you not simply use TImage.Picture.LoadFromFile() and let it handle everything for you? procedure LoginImage(const RutaBase: string); var filename : string; begin // Intentar cargar como BMP filename := IncludeTrailingPathDelimiter(RutaBase) + 'flogin.bmp'; if FileExists(filename) then begin imgFLogin.Picture.LoadFromFile(filename); end else begin ShowMessage('File not found') end; end;
-
Yes, and this is documented behavior: https://docwiki.embarcadero.com/Libraries/en/Vcl.Graphics.TPicture.Bitmap Where it says "a Metafile or Icon graphic", it really means "any non-Bitmap graphic" instead. Use the TPicture.Graphic property when you need to access as-is whatever TGraphic descendant is currently loaded in the TPicture. Use the TPicture.Bitmap property instead when you specifically need a TBitmap.
-
Check the TImage.Picture.Graphic and TGraphic.Empty properties: if (Image1.Picture.Graphic = nil) or Image.Picture.Graphic.Empty then You can assign nil to the TImage.Picture property: Image1.Picture := nil; // same as: // Image1.Picture.Assign(nil); Or to its Graphic property: Image1.Picture.Graphic := nil;
-
Another option might be to use tagged pointers. Normally, objects are aligned in memory in such a way that certain bits in object pointers are always zero, so those bits can be repurposed if you are careful. For instance, if you limit your integer values to 31 bits (x86) or 63 bits (x64), you can use an unused bit in an object pointer to flag whether the pointer holds an integer value vs an object address, and just mask off the bit when extracting the value. For example: // this assumes objects are never stored at an odd-numbered memory address.. var intValue: Integer := ...; Objects[c,r] := TObject((NativeUInt(intValue) shl 1) or $1); ... var objValue: TObject := ...; Objects[c,r] := objValue; ... if (NativeUInt(Objects[c,r]) and $1) <> 0 then begin // is an integer... var intValue := Integer(NativeUInt(Objects[c,r]) shr 1); ... end else begin // is an object... var objValue := Objects[c,r]; ... end; ... if (NativeUInt(Objects[c,r]) and $1) = 0 then Objects[c,r].Free;
-
Correct. You can't. So, either store all objects only, or all integers only. Don't mix types. But, if you must, then you'll need to either wrap the integers inside of objects, or add an extra header in front of each value to identify its type, etc.
-
D12, Android 14, how to locate "assets\internal" at runtime
Remy Lebeau replied to Fudley's topic in FMX
Standard RTL Path Functions across the Supported Target Platforms -
Winapi.Windows.PROCESS_QUERY_LIMITED_INFORMATION not found
Remy Lebeau replied to PeterPanettone's topic in Windows API
It will compile, but it won't behave as you are expecting. PROCESS_QUERY_LIMITED_INFORMATION is not a compiler conditional via a {$DEFINE} statement, "-D" compiler switch, or "Conditional Defines" list in the project options, thus: {$IFDEF PROCESS_QUERY_LIMITED_INFORMATION} // will always evaluate as false {$IFNDEF PROCESS_QUERY_LIMITED_INFORMATION} // will always evaluate as true Regardless of whether PROCESS_QUERY_LIMITED_INFORMATION has been declared as a constant in a unit that your code uses. That is where {$IF (NOT) DECLARED} comes into play, as it supports declarations of types, constants, variables, etc. Not to be confused with {$IF (NOT) DEFINED}, which is the {$IF} version of {$IF(N)DEF} and thus supports only compiler conditionals. const PROCESS_QUERY_LIMITED_INFORMATION = $1000; {$IF DECLARED(PROCESS_QUERY_LIMITED_INFORMATION)} // will evaluate as true {$IF NOT DECLARED(PROCESS_QUERY_LIMITED_INFORMATION)} // will evaluate as false {$IF DECLARED(PROCESS_QUERY_DOESNT_EXIST)} // will evaluate as false {$IF NOT DECLARED(PROCESS_QUERY_DOESNT_EXIST)} // will evaluate as true That is a compiler/IDE bug that would need to be reported, with example to reproduce it. I don't get that error in my tests. Sure, though you would be using your own constant declared in your own unit, and not using a constant declared in the Winapi.Windows unit if Embarcadero ever decides to add it in at a later time. -
Winapi.Windows.PROCESS_QUERY_LIMITED_INFORMATION not found
Remy Lebeau replied to PeterPanettone's topic in Windows API
Wow, what a coincidence, so am I And what I showed works just fine in 12.2. -
Winapi.Windows.PROCESS_QUERY_LIMITED_INFORMATION not found
Remy Lebeau replied to PeterPanettone's topic in Windows API
It works perfectly fine for me exactly as I have shown it. What version are you using? {$IF} has been available since Delphi 6, -
Capture as soon as file paste is selected
Remy Lebeau replied to Mustafa E. Korkmaz's topic in Windows API
What are you going on about? That has nothing to do with the subject of this discussion. -
Winapi.Windows.PROCESS_QUERY_LIMITED_INFORMATION not found
Remy Lebeau replied to PeterPanettone's topic in Windows API
That won't work, as PROCESS_QUERY_LIMITED_INFORMATION is not a conditional you can test with {$IFNDEF}. Use {$IF NOT DECLARED} instead: {$IF NOT DECLARED(PROCESS_QUERY_LIMITED_INFORMATION)} const PROCESS_QUERY_LIMITED_INFORMATION = $1000; {$IFEND} -
Possibly interesting issue with a variant holding a Bcd.
Remy Lebeau replied to MarkShark's topic in RTL and Delphi Object Pascal
What I described earlier is based on stepping through the actual RTL source code. Adding Variant(string) + Variant(TBcd) converts the string to a TBcd, it does not convert the TBcd to a string. -
Option to set read topic on Unread Content list
Remy Lebeau replied to ŁukaszDe's topic in Community Management
You don't really need a per-topic option. Read the topics that you are actually interested in, and then you can "Mark site read" to clear out the unwanted topics. If you are on mobile, the option is in the top-right menu in the Account section. If you are on desktop, the option is on the bottom footer of every page. -
ICS - XX: The XX field is required
Remy Lebeau replied to Rolphy Reyes's topic in ICS - Internet Component Suite
Such as? Can you be more specific? What exactly are you entering into postman? Not without knowing what the endpoint is actually expecting, and what your actual code looks like that is not working for you. -
I'm not bashing you around. I'm trying to be straight with you. StackOverflow is a Q&A site, not a help forum. It can be a pretty hard place on beginners who don't take the time to read the documentation and follow the guidelines. Your question in its initial form was not a good fit for the site, that's why it got closed pretty quick. But rather than fix it, you chose to delete it. As is your right. But, I suggest you take some time to learn how the site actually works before posting a new question there again. That's Visual Basic, not Pascal. VB and Pascal are very different languages, with different syntaxes and semantics. You made some minor mistakes in the translation. Specifically: you aren't setting a couple of VSSpell's properties your while loop is looking at the wrong value your switch block is missing a case when VSR_CHECK_CANCELED is detected, you are exiting the whole function instead of just breaking the loop. Try this: SpellChk->EventOptions = 0; SpellChk->AutoPopup = false; SpellChk->CheckText = Memo1->Text; int ResCode = SpellChk->ResultCode; while (ResCode < 0) { switch (ResCode) { case VSR_WORD_MISSPELLED: case VSIR_IGNORE: SpellChk->PopupWordMisspelled = 1; ResCode = SpellChk->ResultCode; break; case VSR_BREAK: SpellChk->ReplaceRecheck; break; } if (ResCode == VSR_CHECK_CANCELED) break; ResCode = SpellChk->ResumeCheck; } Memo1->Text = SpellChk->Text;
-
It compiles and runs perfectly fine for me. What version of C++Builder are you using? The _D() macro is defined in sysmac.h (a core system header) and has been available since C++Builder 2009 when the RTL switched to Unicode. The macro ensures a string/character literal matches the same data type used by System::Char depending on which platform you are compiling for - wchar_t on Windows and char16_t on Posix. There are no Variant's or Currency's in this code, so you should not be getting those errors. The only use of operator+ is to concatenate a string literal with a System::String, and that is a well-defined operation. I'm starting to think you are trying to run VCL GUI code in a project that does not actually have the VCL enabled properly. That is because you declared the square() method as having an 'int' return type, but there was no 'return' statement inside the method's body. If you look at the code I gave you, I declared square() with a 'void' return type instead. Because there is no value worth returning to the caller. But, you are not USING THEM for anything, they are just sitting there. The rest of your code uses only LOCAL VARIABLES of the same names, which shadow the class members, All data members of a TObject-derived class (like TForm is) are initialized to zeroes before the constructor is called. And then you were not assigning any new values to them afterwards. But you did rewrite it nonetheless, even if unintentionally. Which is exactly what the code I gave you does. This code is written wrong. You removed the couts, but you did not remove the loops, too. You are calling square() inside the 1st loop, and calling 'return' in the 2nd loop. So, this code behaves as-if you had written it like this: void __fastcall TForm1::Button1Click(TObject *Sender) { int i, nums[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; for(i = 0; i < 10; i++) { square(nums, 10); } for(i = 0; i < 10; i++) { return; } } You are using the num variable that is local to the square() method, not the num variable that is declared as a member of the TForm1 class. And num is ALWAYS 0 when the 'return' statement is reached. This code is displaying the values of the class members, which you are NEVER assigning any values to, so they just have their initial values of 0. If you really want to use class members, then the code should look something more like this: class TForm1 : public TForm { __published: TButton *Button1; TButton *Button2; TLabel *Label1; TLabel *Label2; void __fastcall Button1Click(TObject *Sender); void __fastcall Button2Click(TObject *Sender); private: // User declarations int nums[10], num; void square(); ... }; void __fastcall TForm1::Button1Click(TObject *Sender) { for(int i = 0; i < 10; ++i) { nums[i] = i+1; } num = 10; square(); } //--------------------------------------------------------------------------- void TForm1::square() { int *n = nums; while(num) { *n = *n * *n; num--; n++; } } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { String s = _D("Array values:"); for(int i = 0; i < 10; ++i) { s += (_D(" ") + IntToStr(nums[i])); } Label1->Caption = s; Label2->Caption = IntToStr(num); } //---------------------------------------------------------------------------
-
Possibly interesting issue with a variant holding a Bcd.
Remy Lebeau replied to MarkShark's topic in RTL and Delphi Object Pascal
It does, but in this case, since the operation involves a native type (string) on the left and a custom user type (TBcd) on the right, the operation gives the custom type an opportunity to decide whether to cast the left side to the custom type, which it does in this situation, and then the failure occurs during that cast from string to TBcd. -
Why? Those variables are not being used anywhere, so there is no point in declaring them there. Why are you calling the function 10 times? The original OP code called it only 1 time. Each time the function is called, the contents of the array are altered, but your code is not using the array values for anything, so there's really no point in altering the array at all. At least the OP's code was outputting the original values and then the altered values. You are not doing that. Why are you updating the Label 10 times with the same value? Perhaps you meant to display nums[ i ] instead? But then you would end up displaying only the last integer in the array. If you want to display all 10 values at one time, this is not the correct code for that task. You are updating the Labels in different places using different variables that have different values, so of course the results are going to be different. When updating Label1, you are using the nums variable that is local to the Button1Click() method. For starters, that code should not even compile as shown, as nums is an array, but the Sysutils::IntToStr() function does not accept an array as input, If this is indeed your actual code, the only way it could work is if the compiler decays the array into an int* pointer to the 1st array element, and then implicitly converts that pointer into a boolean, and then implicitly converts that boolean into an integer. That is too many implicit conversions for one statement, per the C++ standard. But, lets assume your compiler ignores that fact, then that would explain how you end up with a final output of "1", as a non-null pointer converts to a boolean true, and true converts to an integer 1. When updating Label2, you are using the num parameter that is local to the square() method, which was decremented to 0 while the loop ran. If you really want to replicate the OP's code but display the results in a GUI instead of a console, then try something more like this instead: class TForm1 : public TForm { TButton *Button1; TLabel *Label1; TLabel *Label2; void __fastcall Button1Click(TObject *Sender); private: void square(int *n, int num); }; void __fastcall TForm1::Button1Click(TObject *Sender) { int i, nums[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; String s; s = _D("Original array values:"); for(i = 0; i < 10; ++i) s += (_D(" ") + IntToStr(nums[i])); Label1->Caption = s; square(nums, 10); s = _D("Altered array values:"); for(i = 0; i < 10; ++i) s += (_D(" ") + IntToStr(nums[i])); Label2->Caption = s; } //--------------------------------------------------------------------------- void TForm1::square(int *n, int num) { while(num) { *n = *n * *n; num--; n++; } } //---------------------------------------------------------------------------
-
Because, that is essentially what you did ask for - a tutorial on how to use the OCX control. THAT is what you should have asked for instead. That would have made for a better StackOverflow question, and less likely to be closed. Also, since you clearly know what you are looking for, you should have explained/shown what you had already tried that didn't work for you. Then you should have included one of those examples in your StackOverflow question and asked how to accomplish the same thing in C++. I can't find any documentation or examples of the OCX control, in ANY programing language. Can you provide a source?
-
No. There are only 10 integers declared in the array (values 1..10). Valid indexes into the array are only 0..9, inclusive.
-
tmainmenu identify whether a TMenuItem is a top-level menu bar item
Remy Lebeau replied to bravesofts's topic in VCL
The Parent will not be nil for top-level items, it will instead be pointing at the TMainMenu.Items property.- 12 replies
-
How to get the result of Activity.startActivityForResult in android
Remy Lebeau replied to iken's topic in Cross-platform
Again, appA MUST use startActivityForResult() in order to receive TMessageReceivedNotification with the result from appB. -
I would suggest making the Action hold a pointer to the desired Form, and simply read the Form's current Name whenever needed. And if the Form's Name changes, then have the Form notify any Action that is pointing at it so they can use the new Name as needed. Easy to do if Actions register themselves with the Form so it can maintain a list of pointers to the Actions.
-
That code is performing floating-point division. And as Lejos mentioned, floating-point exceptions behave differently in Delphi 12 than they did in earlier versions. https://dalijap.blogspot.com/2023/09/coming-in-delphi-12-disabled-floating.html This is also documented by Embarcadero: https://docwiki.embarcadero.com/RADStudio/Athens/en/What's_New#Disabling_Floating-Point_Exceptions_on_All_Platforms If you want to see a Call Stack at runtime, you have to display it yourself. You can catch the Exception (or use the TApplication(Events).OnException event) and then read the Exception.StackTrace property. However, this requires you to install a 3rd party exception logging library, such as MadExcept or EurekaLog, to populate the trace details. Embarcadero does not provide that functionality. In which case, you may as well use that library's own logging capabilities.