rubberduck-vba / Rubberduck

Every programmer needs a rubberduck. COM add-in for the VBA & VB6 IDE (VBE).
https://rubberduckvba.com
GNU General Public License v3.0
1.92k stars 302 forks source link

Code Explorer should allow opening Access form in design view #3553

Open bclothier opened 6 years ago

bclothier commented 6 years ago

Nice to have:

In Project Explorer, right-clicking an Access form/report document object allows for either View Code or View Object. In RD's Code Explorer, there is Open or Open Designer for an userform. However, Open Designer is not available for an Access form/report.

This is likely host-specific, as I'm not sure other types of document modules can be "opened in design view" but somehow PE is able to "know" that the document module has a designer and thus opens it in design, so surely CE could do the same, maybe?

retailcoder commented 6 years ago

Does HasDesigner return True for an Access form? Or report?

bclothier commented 6 years ago

There is no such property, AFAICT. Not even hidden. Besides, by definition, all forms & reports have designer, even if they have no code-behind. However, if forms/reports has no code-behind, they simply do not show up in the VBA project.

retailcoder commented 6 years ago

The property is exposed by the VBComponent interface: https://github.com/rubberduck-vba/Rubberduck/blob/next/Rubberduck.VBEEditor/SafeComWrappers/Abstract/IVBComponent.cs#L16

bclothier commented 6 years ago

From the discussion in the chat, it was determined that HasDesigner which is actually a wrapping method for testing whether VBComponent's Designer is non-null will NOT work for this case.

However, instead of tying in specific API to invoke open a designer, we can just ride on project explorer's coattail by doing the following:

1) In the CE's Open Designer's CanExecute method, test whether View Object command on the PE is enabled. If it is enabled, enable CE's. 2) when it is executed, simply invoke the same command that View Object would have executed. If it's anything like CommandBars, it should be possible to invoke without UI interaction.

Hopefully that will allow us to remain agnostic about host application-specific behavior in regards to their document module.

bclothier commented 6 years ago

Note, the command id for the View Object as exposed via View menu, which should be the same command used by the right-click for View Object:

?Application.VBE.CommandBars("View").Controls(2).Id
 2553

To avoid going via menus (and potentially internationalization issues), FindControl will work:

Application.VBE.CommandBars.FindControl(Id:=2553).Enabled
ThunderFrame commented 6 years ago

IIRC, this wouldn't be the first time, or the last time that we'd need to execute a command bar control.

It might be useful to wrap all necessary CommandBar control Find-And-Execute actions in a static class that just exposes a method for each control.

Eg.:

VBECommand.ViewObject();
bclothier commented 6 years ago

Keep in mind that we still have to support both CanExecute and Execute methods, which means we need to access the command at least twice, and being a COM object, they need to be disposed of.

A static class is not conductive to this. For that reason, I think it's best to have something akin to a provider so that we can pass in a constant representing the Id, to abstract away the COM management parts and make it possible for IoC to inject the provider into the command that needs it.