I'm injecting a number of forms into an existing application using a dll.
I don't control the existing application, nor do I have source code for it.
(I doubt the source code exists any more).
I want to show a TextHint in a TEdit.
In the form designer this works, but in the application it doesn't.
I traced it to the fact that StyleServices (This used to be called ThemeServices (now deprecated)) is not enabled, disabling the TextHint.
Obviously I cannot enable styles for the application, all I have is a dll.
Is there a way to show the texthint?
I prefer to use a stock TEdit.
The dll is written in DX and the old application is written in D7.
BTW I don't care a hood about any additional styling/theming or the like. I just want the texthint to display.
Is there a way to show the texthint?
Standard TextHint functionality in a stock TEdit is dependent on the EM_SETCUEBANNER message, which only works when Visual Styles are enabled:
Note To use this API, you must provide a manifest specifying Comclt32.dll version 6.0. For more information on manifests, see Enabling Visual Styles.
If Visual Styles are not enabled in the app you are injecting your code into, then the only way to do what you are asking for is to subclass the TEdit window and custom-draw it manually when its text is empty.
Related
We converted a large application suite from another database layer to FireDAC. The (Win32) programs currently do not implement a FDGuixWaitCursor, and the legacy code has calls to 'push', change and 'pop' the screen cursor.
Should I add FDGuixWaitCursor to my 'base' datamodule for any important/technical reason?
The documentation Preparing a FireDAC Application for Run Time does not really answer that.
Not necessarily. The TFDGUIxWaitCursor component makes sense to use if you wanted to setup the cursor, handle cursor changing events or include the project type implementation by setting up the Provider property. Nothing more at this time (Delphi 10.2.3 Tokyo).
If you don't need any of this, you can just include FireDAC.VCLUI.Wait module into a VCL project, FireDAC.FMXUI.Wait into an FMX project, or FireDAC.ConsoleUI.Wait into a console project.
It's worth adding that FireDAC includes all the necessary modules automatically for its design time created components (so one of them is most likely included in your data module).
I have created a COM Interop Control in C# to use in my PB application. If I add an ole control to my userobject and select my C# object in the painter, then an olecustomcontrol is created and everything works as expected. However, in order to use a 64-bit version of my object when building the project for a 64-bit platform (in PB Classic 12.6) I added an ole control but hit cancel when asked to select an object, so an olecontrol is created and I can use InsertClass to select my object at runtime. This is working for me but I have one issue: when the user clicks in my control, activating it, the toolbar icons on my MDI window disappear. From the research I have done, it sounds like PB may expect the ole object to provide the menus and toolbars, but my PB menu items are unaffected, it is just the toolbar. My control does contain a toolbar (the control is a rich text editor I created to workaround some shortcomings of the built in control) but I have also tried creating a new Interop Control with only a plain text box on it and got the same results. Actually I also tried using one of the Microsoft controls (Microsoft InkEdit Control) installed on my system, and again got the same results.
Does anyone know how I can fix this toolbar problem? (I'm at a loss, but I'm guessing it may be that I need to somehow tell PB to ignore OLE toolbars and/or tell my C# object not to advertise a toolbar.)
Ah, that legacy code we have to support for decades...
The following would take some research and may not eventually solve the problem, but I'd give it a try. I'd implement a "proxy" COM object that'd serve as an extra layer between your .NET OLE control and its OLE container. Such object would be exposed as OLE control to the PB runtime, and as OLE Container to the .NET control, and forward the COM methods calls between the two. It'd be much easier to code this layer with C++/ATL, but it should be doable with bare C#, too.
Then I'd watch the calls made on IOleInPlaceFrame and IOleInPlaceUIWindow interfaces and block those which lead to the undesired toolbar behavior (if any). I'd also limit the set of OLE control interfaces exposed to the PB runtime to some bare minimum.
The implementation details of AxHost and Control classes might be helpful here, as well as the ATL library source code.
This seems a bug. I created a very simple application that retrieves data into ole control and there was no code in any menu items. As soon data is fetched and ole control gets focus the main MDI toolbar disappear. Somebody should report that bug to SAP.
https://answers.sap.com/questions/300798/toolbar-disappear-when-ole-control-get-focus.html
I am using Delphi XE6 and VCL styles. I have main application and dlls. My main application has enabled runtime themes and I am using vcl style files. I did quite similar thing to my DLLs. I enabled runtime themes and added VCL.Themes, VCL.Styles under uses and resource file with VCL style file within it. When DLL is loaded I load VCL style from resources and set it for DLL gui. Main app and DLL are not built with runtime packages.
Now I have main app GUI styled with own style and DLL gui styled with own style too. This seems to work fine until...
When I click on button in my main app which event opens TPopupMenu it's styled with same style as DLL GUI instead of main app style. If I navigate through menu I get AV too and program crashes. Take a look at the attached image.
What am I doing wrong? The only workaround I currently see would be to make my own customized TPopupMenu derived from some other control.
As I promised I prepared simple demo program which is similar to my application. It consists of host application with own style and DLL with style added to resource. Run it and click on button Popup then try select something from popup. It will crash and stop in some StdWindowProc or something like that. Also if you go to window system menu (left top corner) when you try to select something from that menu you will notice that system menu is styled as DLL gui and crashes too. Link to rar file: dropbox.com/sh/f2jmbsmw18akpyg/AAA6SWdBmVhf6n6K-mvYLLmua?dl=0
Thanks for your help.
This is a fundamental problem with VCL styles and the way that they style menus. The styling is implemented with a process wide hook. Specifically a CBT hook installed by a call to SetWindowsHookEx from TCustomStyleEngine.CreateSysHook in the Vcl.Themes unit. In fact, the hook applies just to the GUI thread, but that is process wide in the sense that there is exactly one GUI thread in the process.
Since you have multiple instances of the VCL in your application (one in the DLL and one in the application), two hooks are installed. That is one too many. The hook installed most recently (the DLL as it happens) wins, and that's why the DLL menu styling infects your executable. And why you encounter an access violation. The DLL is trying to operate on a menu that belongs to the executable. And so, in spite of your best efforts, you've ended up with the DLL code accessing VCL objects from the host executable.
There's no simple way to work around this and support styles fully in both modules. What we have here is a fundamental consequence of the design. The system was not designed to support multiple VCL instances. If you wish to use VCL styles in multiple modules, then the designers expect you to use runtime packages.
I suppose that you might be able to get some traction by operating the DLL out of a completely different thread. That would involve loading the DLL from that different thread so that the VCL is initialized in the thread. And all calls to the DLL would have to be from that thread. And you'd need to run a message loop in that thread. It's possible that you might be able to make that work, but I doubt it. Even with all the provisos mentioned you still have to handle the fact that you have two GUI threads which presents all sorts of issues with the input queue handling.
Perhaps another approach would be to uninstall the hook from the DLL. So long as your DLL is not showing menus then you may well be able to get away with uninstalling that hook. It would disable styling for menus shown by the DLL, but perhaps that's acceptable.
This version of your DLL (after I simplified it somewhat also) uninstalls the hook.
library VCLStyleDLL;
{$R 'Style.res' 'Style.rc'}
uses
VCL.Styles,
VCL.Themes,
VCL.SysStyles; // to gain access to TSysPopupStyleHook
{$R *.res}
begin
TStyleManager.TrySetStyle('Glossy', false);
TCustomStyleEngine.UnRegisterSysStyleHook('#32768', TSysPopupStyleHook);
end.
With this version of the DLL, the host executable does not suffer the problems your describe in your question.
As David says this is caused because each VCL instance install a hook to detect when a popup menu (#32768) is created. So there is two hook instances working at the same time.
As workaround you can disable the popupmenu style hook in the dll (or in the app) using the UnRegisterSysStyleHook function defined in the Vcl.SysStyles unit.
TCustomStyleEngine.UnRegisterSysStyleHook('#32768', TSysPopupStyleHook);
I am using Delphi XE6 and VCL styles. I have main application and dlls. My main application has enabled runtime themes and I am using vcl style files. I did quite similar thing to my DLLs. I enabled runtime themes and added VCL.Themes, VCL.Styles under uses and resource file with VCL style file within it. When DLL is loaded I load VCL style from resources and set it for DLL gui. Main app and DLL are not built with runtime packages.
Now I have main app GUI styled with own style and DLL gui styled with own style too. This seems to work fine until...
When I click on button in my main app which event opens TPopupMenu it's styled with same style as DLL GUI instead of main app style. If I navigate through menu I get AV too and program crashes. Take a look at the attached image.
What am I doing wrong? The only workaround I currently see would be to make my own customized TPopupMenu derived from some other control.
As I promised I prepared simple demo program which is similar to my application. It consists of host application with own style and DLL with style added to resource. Run it and click on button Popup then try select something from popup. It will crash and stop in some StdWindowProc or something like that. Also if you go to window system menu (left top corner) when you try to select something from that menu you will notice that system menu is styled as DLL gui and crashes too. Link to rar file: dropbox.com/sh/f2jmbsmw18akpyg/AAA6SWdBmVhf6n6K-mvYLLmua?dl=0
Thanks for your help.
This is a fundamental problem with VCL styles and the way that they style menus. The styling is implemented with a process wide hook. Specifically a CBT hook installed by a call to SetWindowsHookEx from TCustomStyleEngine.CreateSysHook in the Vcl.Themes unit. In fact, the hook applies just to the GUI thread, but that is process wide in the sense that there is exactly one GUI thread in the process.
Since you have multiple instances of the VCL in your application (one in the DLL and one in the application), two hooks are installed. That is one too many. The hook installed most recently (the DLL as it happens) wins, and that's why the DLL menu styling infects your executable. And why you encounter an access violation. The DLL is trying to operate on a menu that belongs to the executable. And so, in spite of your best efforts, you've ended up with the DLL code accessing VCL objects from the host executable.
There's no simple way to work around this and support styles fully in both modules. What we have here is a fundamental consequence of the design. The system was not designed to support multiple VCL instances. If you wish to use VCL styles in multiple modules, then the designers expect you to use runtime packages.
I suppose that you might be able to get some traction by operating the DLL out of a completely different thread. That would involve loading the DLL from that different thread so that the VCL is initialized in the thread. And all calls to the DLL would have to be from that thread. And you'd need to run a message loop in that thread. It's possible that you might be able to make that work, but I doubt it. Even with all the provisos mentioned you still have to handle the fact that you have two GUI threads which presents all sorts of issues with the input queue handling.
Perhaps another approach would be to uninstall the hook from the DLL. So long as your DLL is not showing menus then you may well be able to get away with uninstalling that hook. It would disable styling for menus shown by the DLL, but perhaps that's acceptable.
This version of your DLL (after I simplified it somewhat also) uninstalls the hook.
library VCLStyleDLL;
{$R 'Style.res' 'Style.rc'}
uses
VCL.Styles,
VCL.Themes,
VCL.SysStyles; // to gain access to TSysPopupStyleHook
{$R *.res}
begin
TStyleManager.TrySetStyle('Glossy', false);
TCustomStyleEngine.UnRegisterSysStyleHook('#32768', TSysPopupStyleHook);
end.
With this version of the DLL, the host executable does not suffer the problems your describe in your question.
As David says this is caused because each VCL instance install a hook to detect when a popup menu (#32768) is created. So there is two hook instances working at the same time.
As workaround you can disable the popupmenu style hook in the dll (or in the app) using the UnRegisterSysStyleHook function defined in the Vcl.SysStyles unit.
TCustomStyleEngine.UnRegisterSysStyleHook('#32768', TSysPopupStyleHook);
Delphi7 (cannot use latest). I want to replace (easy way, not making my form) MessageDlg calls with Vista style dialogs (must still work on old OS!). I need buttons Yes/No/YesToAll/NoToAll in this.
How to do it?
MessageBox isn't a way: I need all 4 buttons Yes/No/YesToAll/NoToAll in one form, or maybe checkbox instead of ToAll btns.
On Vista you use the native task dialog, TaskDialogIndirect. This has all the functionality you need. You'll need to translate the headers to Pascal, but if you don't fancy doing that yourself then you can use the JEDI header translations, for instance.
On XP and older there is no task dialog. There is no native system dialog with the functionality that you desire. Therefore you need to implement the dialog yourself. Create a Delphi TForm descendent. Add the necessary text, buttons, styling etc. Show it with ShowModal.
One of the issues with all this is that TaskDialogIndirect must be bound at runtime with GetProcAddress. In fact, use GetProcAddress to determine whether TaskDialogIndirect is available, and if not fall back to the XP code path.
If you don't want to build this yourself you can use one of the many extant libraries that offer such functionality. For instance: http://blog.synopse.info/post/2011/03/05/Open-Source-SynTaskDialog-unit-for-XP,Vista,Seven