Jump to content

bravesofts

Members
  • Content Count

    106
  • Joined

  • Last visited

Community Reputation

30 Excellent

Recent Profile Visitors

1888 profile views
  1. bravesofts

    identify whether a TMenuItem is a top-level menu bar item

    Thanks, but I actually did try that earlier — checking if TMenuItem.Parent = nil. Unfortunately, in my specific case, it didn’t give the expected result. Even top-level menu items were affected, possibly due to the way OwnerDraw, when my MainMenu is hosted by TToolbar. I also checked the documentation, and while Parent should be nil for main menu items, it didn’t behave consistently in my setup. That’s why I started exploring alternatives like checking the Windows hSubMenu via MENUITEMINFO. Appreciate the suggestion though — it’s good in theory, just didn’t work reliably in my case.
  2. bravesofts

    identify whether a TMenuItem is a top-level menu bar item

    Thanks, that worked correctly! However, I'm still not knowing the native way to distinguish between true menu bar items (top-level items in the TMainMenu) and internal submenu items !
  3. bravesofts

    identify whether a TMenuItem is a top-level menu bar item

    procedure TdmUI.FixMenuCaptions(aMenu: TMainMenu); var I, K: Integer; procedure FixItem(aItem: TMenuItem); var J: Integer; begin if (Pos('&', aItem.Caption) = 0) and (not aItem.IsLine) then // and // (not IsMenuBarItem(aMenu, aItem)) then //or (aItem.Count > 0) or (aItem.Tag <> 2) aItem.Caption := '&' + aItem.Caption; // Add & if missing for J := 0 to aItem.Count - 1 do FixItem(aItem.Items[J]); end; begin for I := 0 to aMenu.Items.Count - 1 do for k := 0 to aMenu.items[I].Count -1 do FixItem(aMenu.Items[I]); end; I tried that approach, but it still adds the & to top-level menu bar items as well — so the issue remains. Even with separate loops or skipping directly in the main loop, the FixItem() call still affects them unless I explicitly check whether the item is a menu bar item.
  4. bravesofts

    identify whether a TMenuItem is a top-level menu bar item

    I know about using the Tag property, but I'm aiming to write a clean, universal solution or design pattern that works reliably with any dropped TMainMenu, without relying on manual tagging or special-case logic. I want something that auto-detects whether a TMenuItem is a menu bar item based purely on its structure, so it can be reused across different forms and menus with minimal setup.
  5. In Delphi VCL, I'm trying to identify whether a TMenuItem is a top-level menu bar item (a MenuBarItem) as opposed to a regular submenu item. I'm currently using this check: if aItem.Count > 0 then But this returns True for both top-level menu items (e.g., "File", "Edit" in the main menu bar) and submenu items that have their own children (like "Recent Files" under "File"). Is there a more reliable way—perhaps using TMenuItem properties or GetMenuItemInfo from the Windows API—to distinguish true menu bar items from submenu items with children? i'm using this: function IsMenuBarItem(aMenu: TMainMenu; aItem: TMenuItem): Boolean; var LInfo: MENUITEMINFOW; LHMenu: HMenu; I: Integer; begin Result := False; LHMenu := aMenu.Handle; ZeroMemory(@LInfo, SizeOf(LInfo)); LInfo.cbSize := SizeOf(LInfo); LInfo.fMask := MIIM_SUBMENU; for I := 0 to GetMenuItemCount(LHMenu) - 1 do begin if GetMenuItemInfoW(LHMenu, I, True, LInfo) then begin if LInfo.hSubMenu = aItem.Handle then begin Result := True; Exit; end; end; end; end; is possible to avoid iterating all items in the main menu if i trying to determine whether a given TMenuItem is a menu bar item, using only information from the TMenuItem itself ! --- 🧩 Context: The reason I'm doing this is to work around the automatic access key (Alt + key) assignment that Windows applies when menu items don't have an & in their caption. Even after setting: TMainMenu.AutoHotkeys := maManual; the issue persisted. I'm working in a Right-to-Left (BiDiMode) environment with OwnerDraw := True, and the system still assigns hotkeys unless the & is explicitly added to the menu captions. 👉Hint: the TMainMenu is hosted by TToolBar and not the Form ! -- 🛠️ MySolution: Add "&" to Non-MenuBar Items Here's the utility I use to ensure all non-menu bar items have an & prefix: procedure TdmUI.FixMenuCaptions(aMenu: TMainMenu); var I: Integer; procedure FixItem(aItem: TMenuItem); var J: Integer; begin if (Pos('&', aItem.Caption) = 0) and (not aItem.IsLine) and (not IsMenuBarItem(aMenu, aItem)) then //or (aItem.Count > 0) or (aItem.Tag <> 2) aItem.Caption := '&' + aItem.Caption; // Add & if missing for J := 0 to aItem.Count - 1 do FixItem(aItem.Items[J]); end; begin for I := 0 to aMenu.Items.Count - 1 do FixItem(aMenu.Items[I]); end; This approach above ensures that only submenu items get the &, preserving the expected behavior on the menu bar, especially in right-to-left and owner-drawn setups.
  6. bravesofts

    Is there a Trackbar that has two sliders?

    If full WinRT control support were available, we could simply use the built-in RangeSelector control: 🔗 RangeSelector I realize this is part of the XAML Island Surface Controls, but it's still a native Windows control — part of the OS-level UI framework.
  7. I have a TMainMenu hosted on a TToolBar on my form. In my application's .dpr file (before anything else, especially before the TMainMenu is created), I call Screen.MenuFont to set a custom font. Initially, everything works perfectly — the menu displays using my custom font. However, when I change the monitor's DPI scaling while the application is running, I notice that the MainMenu font resets back to the default system font. I tried handling the OnAfterMonitorDpiChanged event by unhosting the TMainMenu from the TToolBar, resetting Screen.MenuFont to my custom settings again, and then rehosting the menu — but it doesn't seem to have any effect. How can I correctly reapply my custom MenuFont when the monitor DPI changes during runtime?
  8. Yes, here’s a practical use case: Example: Suppose I have a legacy application with over 100 forms, and I need to log every time a form is shown. Instead of modifying each form manually or forcing them to inherit from a new base class, I use TMethodsInjector to dynamically inject a logging procedure into the OnShow event of each form at runtime — all without changing the existing form code. This approach is especially useful in scenarios where inheritance or code edits aren't feasible — such as working with third-party components, plugin-based modules, or dynamically loaded forms. That said, this class is still in a beta/concept stage and hasn’t been fully battle-tested in real-world production scenarios. If you have a more robust or elegant way to achieve this kind of dynamic behavior injection without modifying the original source, I’d be genuinely glad to hear and learn from it!
  9. i succeed to have this: TMethodsInjector = class private class var fM1, fM2: TMethod; class procedure InvokeCombined; class function CombineMethods(const M1, M2: TMethod): TMethod; static; public class procedure InjectPropertyMethod(aTarget: TObject; const aPropertyName: string; aMethodAddress: Pointer; aMethodData: TObject; aOverrideOldIfAssigned: Boolean = False); static; end; implementation { TMethodsInjector } class procedure TMethodsInjector.InvokeCombined; type TProcOfObject = procedure of object; begin if Assigned(fM1.Code) then TProcOfObject(fM1)(); if Assigned(fM2.Code) then TProcOfObject(fM2)(); end; class function TMethodsInjector.CombineMethods(const M1, M2: TMethod): TMethod; begin fM1 := M1; fM2 := M2; TMethod(Result).Code := @InvokeCombined; TMethod(Result).Data := fM1.Data; end; class procedure TMethodsInjector.InjectPropertyMethod(aTarget: TObject; const aPropertyName: string; aMethodAddress: Pointer; aMethodData: TObject; aOverrideOldIfAssigned: Boolean); var LRttiContext: TRttiContext; LRttiType: TRttiType; LRttiProperty: TRttiProperty; LOldMethod, LNewMethod, LCombined: TMethod; begin if not Assigned(aTarget) then Exit; LRttiContext := TRttiContext.Create; try LRttiType := LRttiContext.GetType(aTarget.ClassType); LRttiProperty := LRttiType.GetProperty(aPropertyName); if Assigned(LRttiProperty) and (LRttiProperty.PropertyType.TypeKind = tkMethod) then begin LOldMethod := GetMethodProp(aTarget, aPropertyName); LNewMethod.Code := aMethodAddress; LNewMethod.Data := aMethodData; LCombined := LNewMethod; // Case old is nil or (assigned and must override) if Assigned(LOldMethod.Code) and not aOverrideOldIfAssigned then LCombined := CombineMethods(LOldMethod, LNewMethod); SetMethodProp(aTarget, aPropertyName, LCombined); end else raise Exception.CreateFmt('Property %s not found or is not a method on %s', [aPropertyName, aTarget.ClassName]); finally LRttiContext.Free; end; end; end. the code works perfectly, but in case of mousedown i got AccessViolation error when i release my mouse from the dragging form, here is the code: procedure FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); private procedure InternalOnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure InjectClickToButton(AButton: TButton; aWithOverride: Boolean = False); public { Public declarations } end; implementation uses API.Methods.Injector; {$R *.dfm} procedure GlobalOnClickHandler(Sender: TObject); begin ShowMessage('Injected Click!'); end; procedure TMainView.InjectClickToButton(AButton: TButton; aWithOverride: Boolean); begin TMethodsInjector.InjectPropertyMethod( AButton, 'OnClick', @GlobalOnClickHandler, Self, // or Self if inside a class aWithOverride ); end; procedure TMainView.BtnInjectWithoutOverrideClick(Sender: TObject); begin InjectClickToButton(BtnTarget); end; procedure TMainView.BtnInjectWithOverrideClick(Sender: TObject); begin InjectClickToButton(BtnTarget, True); end; procedure TMainView.BtnTargetClick(Sender: TObject); begin ShowMessage('Hi from Default'); end; procedure TMainView.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin ReleaseCapture; end; procedure TMainView.InternalOnMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Perform(WM_SYSCOMMAND, $F012, 0); end; procedure TMainView.BtnIjectFormDragClick(Sender: TObject); begin TMethodsInjector.InjectPropertyMethod( Self, 'OnMouseDown', @TMainView.InternalOnMouseDown, Self ); end; end.
  10. I’m working on a class TMethodsInjector that uses RTTI to inject a method into a method-type property (like events). If a method is already assigned, I want to combine it with the new one (same signature) and assign the result. The key part is here: if not Assigned(LOldMethod.Code) then LCombined := LNewMethod else LCombined := GenerateCombinedMethod(LRttiProperty, LOldMethod, LNewMethod); I need help implementing GenerateCombinedMethod — it should dynamically wrap both LOldMethod and LNewMethod (same structure) into a single TMethod that invokes both in order. Is there a clean way to do this using RTTI, without knowing the method signature in advance? my full class code is: unit API.Methods.Injector; interface uses System.Classes, System.SysUtils, System.Rtti, System.TypInfo; type TMethodsInjector = class public class procedure InjectMethod(aTarget: TObject; const aPropertyName: string; aMethodAddress: Pointer; aMethodData: TObject); static; end; implementation { TMethodsInjector } class procedure TMethodsInjector.InjectMethod(aTarget: TObject; const aPropertyName: string; aMethodAddress: Pointer; aMethodData: TObject); var LRttiContext: TRttiContext; LRttiType: TRttiType; LRttiProperty: TRttiProperty; LOldMethod, LNewMethod, LCombined: TMethod; begin if not Assigned(aTarget) then Exit; LRttiContext := TRttiContext.Create; try LRttiType := LRttiContext.GetType(aTarget.ClassType); LRttiProperty := LRttiType.GetProperty(aPropertyName); if Assigned(LRttiProperty) and (LRttiProperty.PropertyType.TypeKind = tkMethod) then begin LOldMethod := GetMethodProp(aTarget, aPropertyName); LNewMethod.Code := aMethodAddress; LNewMethod.Data := aMethodData; if not Assigned(LOldMethod.Code) then LCombined := LNewMethod else LCombined := GenerateCombinedMethod(LRttiProperty, LOldMethod, LNewMethod); SetMethodProp(aTarget, aPropertyName, LCombined); end else raise Exception.CreateFmt('Property %s not found or is not a method on %s', [aPropertyName, aTarget.ClassName]); finally LRttiContext.Free; end; end; end.
  11. At the very least, Embarcadero should provide a solid wrapper for the OS compositor’s rendering Layers—both Windows.UI.Composition and Microsoft.UI.Composition—similar to what they did with TDirect2DCanvas. WinUI isn’t just about UI controls. Handling XAML, controls, and manifest configurations based on OS requirements is something that developers can manage themselves—whether through their own development efforts or through community-driven projects that evolve year by year. We will likely see at least some serious GitHub repositories dedicated to WinRT growth over time.. But direct access to the Windows compositor would unlock real native UI rendering, low-level OS services, and system interactions and a TRUE access to core Windows technologies that are otherwise hidden behind the WinRT layer. that aren’t possible with FMX or VCL alone. Without this essential rendering layer, many critical Windows OS services and WinRT libraries remain difficult to access properly in Delphi. Features like deep integration with the Windows Input System, system-level animations, true windowing effects (Acrylic, Mica, Shader effects), media and graphics pipelines, and power-efficient rendering, Devices, Security, Management and more are all tied indirectly to the modern Windows compositor Features. The absence of a direct wrapper means developers must rely on workarounds or limited interoperability with COM-based WinRT APIs, making these essential system features harder to implement and maintain. FMX can't fully replicate a true Windows OS experience, especially with deeper WinRT integration. WinUI isn’t just about the UI—it connects directly to the Windows compositor|system services in ways FMX doesn’t. A proper wrapper for Windows.UI.Composition and Microsoft.UI.Composition would give developers more native power while keeping things efficient. Additionally, clear documentation and practical examples—such as how to initialize a composition surface, interact with system Features, or leverage deeper OS services—would make these capabilities far more accessible to Delphi developers. In the end, I am not an expert in Windows programming, and some of my information may be incomplete or inaccurate. However, there is no shame in expressing my opinion, even if only on a superficial level.
  12. Embarcadero has always focused on making complex APIs easier to use, so adding WinUI support seems like the natural next step. The longer they wait, the more chances they miss to keep Delphi as a top choice for Windows development. The main subject is going to disappear. So the big question is—will we see WinUI in the next RAD Studio version? Hopefully! 🚀 Thank you all, and please don’t criticize this reply as AI-generated too! 😄
  13. First and foremost, let me start by expressing my deep respect, admiration, and love for Ms. Dalija's response. She is well aware of how much I appreciate and respect her, as I have for many years. However, please do not take my response personally or interpret it as an attack against you. Despite my utmost respect for you, I firmly stand by my principles, and I am always ready to stand against the whole world if necessary to speak the truth, and I am proud of that. Now, my response this time might be very harsh, but since it touches on a very sensitive topic, I will not hesitate to defend it with full determination! First: The Use of AI in My Responses The claim that my responses are AI-assisted does not bother me at all—on the contrary, I am extremely proud of this technology and hold it in the highest regard. AI is the only tool in our harsh world that has opened the doors of opportunity for people like me, who have limited resources, to keep up with modern technological advancements. I openly and proudly acknowledge that AI has provided me—and many others like me—with golden opportunities that we could have never even dreamed of! I repeat, I am proud that almost every aspect of my life is assisted by AI. What truly angers me and pushes me to respond harshly, especially on this particular topic, is the elitist mindset that some people have—trying to prevent others from using this technology. I am firmly and strictly opposed to anyone who stands against people's freedom to use AI or who spies on their private activities using third-party tools to "expose" them for using AI, as if that were somehow unfair. For example, I do not speak English fluently like you do, yet thanks to AI, I now have the ability—at the very least—to communicate with you as an equal. At the end of the day, AI does not generate my ideas from scratch—it simply refines, translates, and enhances them. What’s even more impressive is that it provides me with advice and polishes my words, compared to the raw, unfiltered thoughts that I write in this chat. Second: My Transparency and Honesty I take great pride in the fact that I have no problem with people knowing the reality of my life. I am an extremely straightforward person, and I prefer not to use my real photo on my profiles rather than pretending to be someone I’m not. Unlike many people who present a fake online persona that is completely different from their real-life selves, I choose to be completely transparent about who I am. Anyone who follows my posts (if they understand Arabic) will see this clearly. I have absolute confidence in showing my real self, both in the virtual world and in reality. It does not bother me in the slightest if people know that I use AI tools to express my ideas or write elegant code. So why is there so much negativity and unnecessary propaganda against people who use AI? Third: A Point About Programmers and AI Who can say whether I am typing these words with my feet or my mouth, while you type effortlessly with your golden fingers and closed eyes? Furthermore, one of the strangest fears I see among programmers is the idea that their employers might find out that they use AI for coding! I find this mindset absurd—especially when you see platforms like Stack Overflow banning AI-generated content for questions and answers! Fourth: The Issue of WinUI Libraries in RAD Studio Regarding the integration of WinUI libraries by Embarcadero, you stated that this is not the company’s responsibility but rather the job of advanced programmers and third-party developers. I completely disagree with this notion. WinUI interfaces are not like Android, where it makes sense for Delphi to rely on third-party JNI bridge units. Delphi does not include built-in Android UI components because the Delphi IDE itself can only be installed on Windows. In contrast, WinUI is part of the core Windows operating system—the only platform where Delphi is natively supported. This makes WinUI components a fundamental right for every Delphi programmer, and they should be available in the Standard component panel, just like other built-in Windows UI controls. Delphi itself was originally designed to wrap Windows components natively. Additionally, WinUI libraries have been around since 2012 with the release of Windows 8. Today, we are in 2025—how can we justify such a long delay with such an unconvincing excuse? More than 12 years have passed, yet no one has fully integrated WinUI into RAD Studio. Instead, we have poorly implemented Windows 10-style components that are so unconvincing that even hobbyist programmers would not take them seriously! It’s time to stop lying to ourselves and be honest—as a developer community, we have completely neglected this technology, either out of arrogance or overconfidence in the FireMonkey framework, treating it as a magical solution for all modernization challenges. However, there is absolutely no logical reason to avoid wrapping WinUI components in RAD Studio. The process is no longer complicated at all, especially considering the advanced state of Embarcadero’s bridging and API wrapping tools. At this point, the only thing missing is UI integration and component wrapping—a golden opportunity for both the Delphi community and Embarcadero itself. Final Thoughts: WinUI Integration Will Not Distract Embarcadero Integrating WinUI components will not take significant time away from Embarcadero’s core focus. The company has already implemented almost everything needed. At this stage, there are likely only one or two steps left, and completing them will not divert attention from other critical improvements, such as the compiler, debugger, language features, or IDE functionality. On the contrary, this addition will increase the development team’s focus on these areas rather than distract them. Thank you. the ChatGpt Chat Link here
  14. Haha, no, but I do appreciate well-thought-out discussions about Delphi’s future. At the end of the day, it's all about exploring possibilities rather than dismissing them outright.
  15. 🔍 Will GUI-Based Development Go Extinct? 🤔 Some argue that GUI-based development is fading away in favor of code-centric or terminal-driven development. However, the reality is quite different: GUI development is evolving, not disappearing. 🧐 Why GUI-Based Development Won't Disappear? 1️⃣👨‍💻 Humans Prefer Productivity and Speed People naturally gravitate towards tools that enhance efficiency and reduce complexity. Development environments like Delphi and RAD Studio provide rapid application development, a demand that won't fade away anytime soon. Even with AI-powered coding assistants, GUI tools remain a time-saving necessity in many domains. Most developers prefer being productive rather than just looking like hackers typing endlessly in a green-on-black terminal. Writing code should be about building real solutions efficiently, not about proving how much you can type without a mouse! 2️⃣ 🚀 AI Is Enhancing GUI-Based Development, Not Replacing It AI-powered tools like GitHub Copilot, JetBrains AI, and AI-driven refactoring are deeply integrated into GUI-based IDEs. Delphi, C#/.NET, and Python IDEs now leverage AI to accelerate development, proving that GUI-based environments remain essential. 3️⃣ 🏢 Businesses Need Ready-to-Use Tools, Not Just Code In the real world, businesses prioritize rapid, efficient software development. Companies aren’t interested in reinventing the wheel—hence, RAD (Rapid Application Development) environments remain highly relevant. Delphi, C#/.NET, and even Java-based UI frameworks continue to play a critical role in enterprise solutions. 4️⃣ 🛠️ Clean Code and GUI Development Are Not Mutually Exclusive Some mistakenly believe that GUI development leads to messy, unstructured code, which is far from true. Modern Delphi supports clean architecture, OOP principles, design patterns (MVVM, MVP, SOLID), and well-structured projects. Many Delphi projects today adhere to clean coding practices just as rigorously as C# or Java applications. ----------- 🔹 The False Comparison Between Delphi and VB ✅ Delphi is NOT just another "Visual Basic"—it is a professional-grade development environment that offers: Full-fledged OOP (Object-Oriented Programming) support. Robust architectural patterns (MVVM, Layered Architecture, SOLID, Dependency Injection). Comprehensive libraries like FireMonkey and VCL for cross-platform and native development. Seamless integration with Windows APIs and modern OS features. ❌ On the other hand, VB had fundamental limitations in its OOP and architectural capabilities. 📌 Comparing Delphi to VB is completely inaccurate and misleading. 🟢 Delphi Is Continuously Evolving ✅ Delphi Has Strong OOP and Architectural Support Delphi has long evolved beyond just "drag-and-drop" development. It supports Dependency Injection, Unit Testing, and scalable architectures. ✅ Seamless Integration with Windows APIs, Including WinRT While Embarcadero has not natively included full WinUI support, they have provided highly professional WinRT integration using TWinRTGenericImport. This approach is similar to their work on Android libraries, offering a clean and efficient way to interact with WinRT. ✅ The Delphi Community Is More Active Than Ever GitHub repositories, Stack Overflow discussions, and Delphi-focused YouTube content demonstrate the language’s ongoing evolution. Modern Delphi development embraces clean code, architectures, and high-quality patterns. ⚡ Final Thoughts: GUI Development Isn't Dying—It's Evolving! ❌ The claim that GUI-based development is disappearing is an oversimplification. ✅ In reality, tools like Delphi are thriving because they adapt to modern development needs. ✅ Delphi is no longer just about drag-and-drop—it supports advanced architectures, OOP, and scalable patterns. ✅ The competition with C#, Java, and C++ does not mean Delphi is obsolete—on the contrary, it's gaining new strengths. 💡 However, if there’s one thing I can guarantee will go extinct, it’s not Delphi itself, but the era of classic, messy "spaghetti code" development. 🚀 Most modern Delphi developers no longer even have the patience or willingness to open old, disorganized projects because of their lack of structure, logic, and maintainability. 🔥 Clean, well-architected code is the new standard—and that’s where Delphi is heading! 🔥 Delphi will remain a powerhouse as long as it continues to adapt and evolve! 🚀
×