I am coding up a VST plugin dll. I have no trouble with the plugin until I use a PageControl and place controls on it.
Specifically, my dll seems to have trouble receiving mouse clicks if the control I click on is in a tabsheet, and has code to execute in a mouse onclick or onChange event. However, this ONLY occurs when the hosting program gives control back to my plugin. I can interact perfectly fine with the plugin before the hosting program implements the settings I select, but once it tries to hand back control, I can only click on, seemingly, any control that does not implement any written mouse event code (Tlabel clicks are fine, tabsheet changes are fine too).
The plugin works fine as long as I don't try to make changes to the settings through the controls after the hosting program hands back control to the dll. I can use the same settings over and over again with no problem. I can change them as much as I want until I let the hosting program implement the plugin values (which works perfectly).
This is really tricky to debug since the program is in a dll.
I have tried using Delphi XE2 and Delphi 2009.
Any clues?
Related
I am trying to make the TEdit control for the program on the "Tool Properties" dialog in the Delphi IDE (*1) accept dropping files from the explorer. This works fine in Delphi 6 and 7 but no longer works in the "new" IDE of Delphi 2005 up.
In Delphi 6/7 dropping a file on the edit control triggers a WM_DROPFILES message which a hook to the WindowProc of the TEdit can catch. In the later versions, no message is received. The hook on WindowProc still works, as it receives all kinds of other messages.
The dialog layout, names and controls is unchanged as far as I can determine.
As a test I even added my own TEdit and TComboBox to the dialog to make sure it's not a problem of these specific existing controls. They are shown fine, but dropping a file doesn't work with these either.
What else could be the problem?
(*1: the one you get through Tools -> Configure Tools -> Add or Edit
This will be a new functionality in GExperts. Auto complete already works for these controls.)
The code is here:
http://sourceforge.net/p/gexperts/code/HEAD/tree/trunk/Source/IDE/GX_IdeToolPropertiesEnhancer.pas
and the actual hooking code is here:
http://sourceforge.net/p/gexperts/code/HEAD/tree/trunk/Source/Utils/GX_dzVclUtils.pas
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);
The TWebBrowser component in Delphi XE2 seems to be seriously buggy. Is there some sort of code I have to run in order to instantiate it in some special way?
Create new Delphi project
Drop a TWebBrowser component onto the form.
In Form1.FormCreate() call WebBrowser1.GoHome (to google).
If I compile this 32-bit and go to some specific webpages I get error messages.
google (ncbi nucleotide blast) and click the first link.
In addition to these javascript errors if I click a link which usually opens in a new window, it opens in IE (a separate application).
The 64-bit version seems even more broken. By going to that same site (ncbi nucleotide blast) I get the entire program crashing due to a 'divide_by_zero' error.
Regarding the floating point exceptions, TWebBrowser expects to operate with floating point exceptions masked. It looks like you are using Delphi default floating point settings and have exceptions unmasked. I suspect that if you mask exceptions then your problems will disappear.
Do that like so:
SetExceptionMask(exAllArithmeticExceptions);
And as others have said, you silence the Javascript popups by setting Silent to True.
Make a Delphi 2007 application, TForm as main window.
Run application. Try to drag the form using the caption bar. The debugger shows an unending stream of error messages, complaining it can't find some unnamed routine. Escape and Break don't work. 3 finger salute doesn't work.
Clicking in some other window and then back to the Delphi application stops the avalanche of error messages and allows the application to function in its original location (the form itself hasn't moved).
Strangely, on occasion I've had related behavior using Firefox -- clicking in the browser window doesn't work 'til I click in some non-Firefox window, after which the browser window is active again.
Anyone seen related behavior? Suggestions? Might it be a mouse driver problem? Toshiba laptop with ALPS touchpad mouse.
This doesn't sound related to Delphi specifically. The "stream of error messages, complaining it can't find some unnamed routine" sounds very odd. Could you post one or two of the actual messages, please?
In the meanwhile, my guess is some form of hook or injected code. Try looking for programs that do that kind of thing and disable them one by one:
Mouse drivers (as a poster above
said)
Antivirus, especially the "big ones"
like Norton etc
Some display driver "enhancement"
utilities
If you have two screens and you're
running a second taskbar program, try
that
and so forth.
It's probably worth doing a virus scan too, you never know :)
I know there was a Logitech driver hook problem when starting a Delphi project in Delphi: it gave an exception on the first line of the .dpr. Outside Delphi it worked OK.
So do you get those exceptions/problems only in Delphi? What kind of error/exceptions?