Delphi shell context-menu, how to draw icon - delphi

Can I get some code showing how to draw a bitmap/icon on the right-click context menu?
I have working code already for a DLL for the context menu, but it's just text. Example here: http://www.marcocantu.com/code/md5/TODOSHLL.htm

It seems you can simply use the SetMenuItemBitmaps API.
Edit: Here's a Delphi example.
Edit 2: Warning: I just noticed that the Delphi example leaks the bitmap handle and will probably crash the system eventually. The bitmap should be loaded only once in the constructor of the object (and better from its own resource, not from the file system) and released in the destructor.

Related

Delphi - How to correctly register a graphic class since XE8?

I'm writing a Delphi package, which provides a new custom TGraphic object, allowing to read a new image format in VCL components like TImage.
I originally developed this package with RAD Studio XE7, and it worked well. However I migrated recently to a newer RAD Studio compiler version, and although my package continues to work properly on that new version, I noticed a strange bug that never appeared before.
I have a form with several components, some of them are TImage components. Immediately after opening the IDE, the first time I open my project in design time, all the TImage components containing my custom TGraphic component loose their content. If I close then reopen the project, the images reappear, and the bug no longer happen until I close and reopen my IDE.
I dug in my code to understand what may cause the issue. To register my custom TGraphic component, I use the class initialization section, in which I wrote the following code:
initialization
begin
Vcl.Graphics.TPicture.RegisterFileFormat('svg', 'Scalable Vector Graphics', TWSVGGraphic);
end;
However I found that, since the XE8 compiler version, the TImage constructor is called before my initialization section, causing thus apparently the above mentioned issue. All the compiler versions since XE8 are affected, but this bug never happened on XE7 or earlier. So something changed since XE8.
Here are my questions:
Is the way I use for register my custom graphic class correct?
If not, what is the correct way to do that?
As something seems different since XE8, what it the new correct manner to register my graphic component?
Did anyone else faced the same issue? How he resolved it?
Is this may be a new RAD Studio bug, or the issue is rather on my side?
This is most likely a side effect of the smart loading the IDE applies to design time packages. You can overwrite this behavior by calling ForceDemandLoadState(dlDisable) during the Register procedure of your package.
More about this can be found in the documentation of more recent versions of Delphi than XE8: Explicitly disabling smart loading of components in a design-time package

When activating OLEControl in my PowerBuilder application, toolbar items disappear

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

Correct usage of PaintTo in Delphi

I have a Firemonkey form in RAD studio and I am trying to do some experiments using MediaPlayer. MediaPlayerControl has a procedure named PaintTo, as the name implies I would expect by using this to be able and show my video in another object in my form. I don't know though, neither I can find in the documentation the correct way of using
MediaPlayerControl1.PaintTo();
It asks for a TCanvas a rectangle and a FMXObject. As a Canvas I tried giving
ImageViewer1.Bitmap.Canvas
but I don't know what an FMXObject is. Can someone provide a valid use of the PaintTo procedure?

Memory management issues between InnoSetup and Delphi DLL

Situation:
a DLL that:
is written and compiled with Delphi XE3 32bit
exports a function that displays a modal VCL-form:
function EditOptions(AIniFileName: PAnsiChar; ALCID: Integer): Boolean; stdcall;
is also a COM-server
an installer created with InnoSetup 5.5.4:
imports said DLL function via external 'EditOptions#files:mydll.dll stdcall'-directive and calls it when needed
explicitly unloads the DLL before registering the COM server via the Inno utility function UnloadDLL
Problem:
When...
Windows is using a theme other than Classic
the modal dialog from the DLL is displayed during installation
the installer hangs upon unloading the DLL
no error messages are shown
logs indicate no runtime exceptions
Please note that to keep this brief, I deliberately left out the explanations for some of the more idiosyncratic details, e.g. why I'm explicitly unloading the DLL or why a COM server needs to have custom exports. Let me know if you think these details would be relevant and should be added.
To further analyse this I created a dummy host EXE that calls the DLL function so I can easier run the whole thing in the debugger. Doing so leads to an AV being raised in TUxThemeStyle.UnloadThemeData on the line that calls CloseThemeData(). When placing a breakpoint directly on that line and stepping forward from the stop, I actually get a "too many consecutive exceptions" error eventually. I can only reproduce the error when I enable runtime themes for the host EXE.
Going back through our git history it appears that this issue exists ever since we switched from Delphi 2010 to XE3 (unfortunately, the installer was not part of our regular test suite so this only cropped up now as work on the actual release comes to a close as the DLL exports exist exclusively for the benefit of the installer).
Any ideas what might be causing this? Could this really be theme-related (I have no custom theme-related code in this project) or is that maybe just a symptom of memory corruption caused somewhere else entirely? E.g. I once had an error that manifested in the form of AVs in the theme tear-down code before but in that case it actually turned out to be caused by the leaking of anonymous method references from initialization sections...
Update: I've worked hard trying to produce a dumbed-down sample project to demonstrate the issue in isolation but so far without luck. I have managed to narrow down a few more things, though. First, here are some more facts about the code:
The dialog I'm showing is a third-degree descendant of TForm. The ancestors accomplish several things:
TAppModalDialog implements a special constructor CreateOnTop that ensures it appears as the topmost window in the current process (the project is a plugin that loads into multi-windowed third-party hosts that do unfortunately not communicate their window handles for use as modal parents) - it accomplishes this by manipulating the global Application.Handle.
TTabbedDialog is part of an interface-based framework that allows registration of "pages" (actually TFrame-descendants) via a factory pattern - at runtime the form will dynamically create TTabSheets in a TPageControl and instantiate and parent the registered page frames to them
I've replaced the call to the actual dialog with a dummy, gradually working myself through the inheritance chain from a blank TForm up to my TAppModalDialog and eventually to my TTabbedDialog class. The problem only starts to occur at that last level. I also commented out all page registrations around the project so that the dialog comes up with an empty page control (this rules out code in any of the pages as the cause for the problem). I then commented out all code and data members in the routines of the TTabbedDialog class itself, leaving only empty method bodies to fulfill the interface implementation requirement and the TPageControl component (along with two empty TImageLists and a TBalloonHint component) -> the error still occurs.
I then copied the call to the dummy dialog into a new DLL project that contains nothing else but this and the tabbed dialog framework. If I load that DLL into my dummy host EXE, the problem does not occur anymore... sigh
So, my suspicion is still that there must be some sort of memory corruption occuring somewhere else entirely and the error I see is only a symptom of that. So the real question is how can I finally get to the bottom of this?
I will now continue by commenting out / removing bits from the production DLL...

ParentWindow in a DLL

I'm trying to assign a ParentWindow, to a control created in a dll. The control is an editor, I need to process a text file, but this control requires a ParentWindow.
How can I solve this problem, if I create this control in a dll?
I'm using Delphi 5.
also create the TForm (maybe not Visible) inside the dll then the control and add it to the form
This is a common question, and the correct answer is "Don't do that".
The first question I have is "why do you feel the need to create a control in a DLL?" Why not just create it in code or include the control itself in your EXE?
Second, if you want to add a control to a separate binary, but it in a Package. Packages are designed specifically to make exporting controls simple and easy.
You need to get the parent window from somewhere! Typically the host application that loads and calls the DLL would supply a window handle. It looks like your DLL provides a custom control for an application, so of course the application needs to supply a parent window handle.
Also, you typically need a window handle to the entire application as well, which you set as Application.Handle before you do anything else in your DLL.
ok, thaks for your answers, i already solved (a few minutes before first answer).
first, i need explain why i don't embed, and that is because costumer ask me that way.
the solution is send my form handle to my dll as an argument, after testing that way, i got no errors...
only modificate the prototype of my procedure, to recieve a HWND as an argument, to ParentWindow prop of my control (created in memory).
that's all.

Resources