Oh components, I am writing one of them since a week, too much, I know :)
The last think that I was not able to solve is how to make the component discover where he is exactly during initialization, in other words, on what form is bean placed, and in which project.
I used a similar code in the components to discover the project in the solution that contains, the form, that the component is placed on it.
<b>
_DTE ixDTE = (_DTE)GetService(typeof(_DTE));
EnvDTE.Project ixProject = ixDTE.ActiveDocument.ProjectItem.ContainingProject;
</b>
The above code works fine in the custom controls or components, the only problem is that it is not giving me the right results when I use it in the component constructor initialization.
So, if I place a component on a form, and close and open the form again, the component initialization code will get triggered before the existing form becomes active, and the above code will bring back the previous form’s project, than can be another project in the same solution.
I will make my questions simpler
<b>The first one is:</b> is there is a simple way to get the existing form that the component is placed in during component initialization and I mean by this is immediately after dragging the component and placing it on a form, or immediately after opening a saved form that have the component on it (during component initialization, from the component designer.)
<b>The second one:</b> is there is a simple way to have a configuration file during design time, inside the project in the solution, imaging I have a solution with 3 projects, I have a form in one of the projects, and I am dragging and dropping a component to the form, I need this component to access the configuration file for that particular project that contains the form, not the entire solution. (One configuration file for a project, shared)

It seams I found part of the answer my self :)
real green
I just try it and it does work,
Thanks man.
public override void Initialize(IComponent ioComponent)
{
base.Initialize (ioComponent);
try
{
LxThemeManager.Initialize((EnvDTE.ProjectItem)GetService(typeof(EnvDTE.ProjectItem)), null);
}
catch(Exception ixException)
{
MessageBox.Show(ixException.Message, "Error !" ,MessageBoxButtons.OK
,MessageBoxIcon.Error);
}
}
Amal Kamel
internal static void Initialize(EnvDTE._DTE ixDTE, IDesignerHost ixHost, Assembly ioAssembly)
{
if(ixDTE != null)
{
if(!ixInitialized)
{
EnvDTE.Project ixProject = null;
// Find where is the form that contains the control in the solution.
foreach(EnvDTE.Document ixDocument in ixDTE.Documents)
{
if(ixDocument.ProjectItem.FileCodeModel != null)
{
foreach(EnvDTE.CodeElement ixCodeElement in ixDocument.ProjectItem.FileCodeModel.CodeElements)
{
EnvDTE.CodeClass ixCodeClass = ixCodeElement as EnvDTE.CodeClass;
if(ixCodeClass != null)
{
if(ixCodeClass.Name == ixHost.RootComponentClassName)
{
ixProject = ixDocument.ProjectItem.ContainingProject;
}
}
else
{
EnvDTE.CodeNamespace ixCodeNamespace = ixCodeElement as EnvDTE.CodeNamespace;
if(ixCodeNamespace != null)
{
foreach(EnvDTE.CodeElement ixCodeElementN in ixCodeNamespace.Members)
{
EnvDTE.CodeClass ixCodeClassN = ixCodeElementN as EnvDTE.CodeClass;
if(ixCodeClassN != null)
{
if(ixCodeClassN.Name == ixHost.RootComponentClassName)
{
ixProject = ixDocument.ProjectItem.ContainingProject;
}
}
}
}
}
}
}
}
// Creating the shared themes file, or loading it if it does exist.
if(ixProject != null)
{
.............................
}
}
}
}
and in the component designer
public override void Initialize(IComponent ioComponent)
{
base.Initialize (ioComponent);
try
{
LxThemeManager.Initialize(((_DTE) ioComponent.Site.GetService(typeof(_DTE)))
,(IDesignerHost) ioComponent.Site.GetService(typeof(IDesignerHost))
, null);
}
catch(Exception ixException)
{
MessageBox.Show(ixException.Message, "Error !" ,MessageBoxButtons.OK
,MessageBoxIcon.Error);
}
}
I will publish the entire code as part of the second part of the SmartLibrary (0.2) on my web site soon.
Kaktusbluete
RPaulo
DTE.ProjectItem item = (DTE.ProjectItem)GetService(typeof(DTE.ProjectItem));
The code parser adds this service at boot up so you can get at it easily. We chose this because from ProjectItem you can navigate back up the rest of the hierarchy if you want.
ika
1- Through DTE, get the ActiveDocument.
2- Access the ProjectItem Property of the ActiveDocument.
3- Access the FileNames Property of the ProjectItem.
If your component is currently on a form, then those steps should return YourForm.vb and YourForm.resx ... Just a stab in the dark, but it may just workout...
If, on the other hand, you are trying to access the Config File (as you mentioned in your original post), then once you acquire the ProjectItem you need, you should be able to retrieve what you need through the ConfigurationManager property...
Hope this is helpful.
BSHOE
Form ixForm = (Form) ixHost.RootComponent;
Skizznott
internal class CodeInjector
{
public static void InsertCode(DTE dte, IDesignerHost host, string code)
{
Document ourDoc = FindOurDocument(dte, host);
// OpenCodeDoc(dte, ourDoc); // may not be necessary
// find our class
string className = host.RootComponentClassName;
FileCodeModel cm = ourDoc.ProjectItem.FileCodeModel;
CodeClass cc = null;
foreach (CodeElement ce in cm.CodeElements)
{
cc = FindClass(ce, className);
if (cc != null)
break;
}
if (cc != null)
{
// first create codedom
CodeCommentStatement comment = new CodeCommentStatement(code);
// cannot generate code from a method -- have to use a type, or
// hope the method is already there
// CodeMemberMethod method = new CodeMemberMethod();
// method.Name = "test";
// method.Comments.Add(comment);
// generate a string from the codedom
CodeDomProvider provider;
if (ourDoc.Language == "CSharp")
provider = new Microsoft.CSharp.CSharpCodeProvider();
// TODO: need to test this -- don't know which string to use
else if (ourDoc.Language == "VB")
provider = new Microsoft.VisualBasic.VBCodeProvider();
else
return;
ICodeGenerator generator = provider.CreateGenerator();
StringBuilder sb = new StringBuilder();
TextWriter writer = new IndentedTextWriter(new StringWriter(sb));
generator.GenerateCodeFromStatement(comment, writer, null);
writer.Flush();
// if the method already exists, delete body
EditPoint start = null;
foreach (CodeElement ce in cc.Members)
{
CodeFunction cf = ce as CodeFunction;
if (cf != null && cf.Name == "test")
{
start = cf.StartPoint.CreateEditPoint();
start.LineDown(2);
start.StartOfLine();
EditPoint end = cf.EndPoint.CreateEditPoint();
end.LineUp(1);
end.EndOfLine();
start.Delete(end);
break;
}
}
if (start == null)
{
if (ourDoc.Language == "CSharp")
{
CodeFunction cf = cc.AddFunction("test", vsCMFunction.vsCMFunctionFunction,
vsCMTypeRef.vsCMTypeRefInt, -1, vsCMAccess.vsCMAccessPrivate, null);
start = cf.StartPoint.CreateEditPoint();
start.LineDown(2);
start.StartOfLine();
}
else
{
// TODO: here error message
}
}
// insert the string into the function
start.Insert(sb.ToString());
}
}
private static CodeClass FindClass(CodeElement root, string className)
{
CodeClass cc = root as CodeClass;
if (cc != null)
{
if (cc.FullName == className)
return cc;
foreach (CodeElement ce in cc.Members)
{
if (ce is EnvDTE.CodeNamespace || ce is CodeClass)
{
cc = FindClass(ce, className);
if (cc != null)
return cc;
}
}
}
else
{
EnvDTE.CodeNamespace cn = root as EnvDTE.CodeNamespace;
if (cn != null)
{
foreach (CodeElement ce in cn.Members)
{
if (ce is EnvDTE.CodeNamespace || ce is CodeClass)
{
cc = FindClass(ce, className);
if (cc != null)
return cc;
}
}
}
}
return null;
}
private static Document FindOurDocument(DTE dte, IDesignerHost host)
{
foreach (Document doc in dte.Documents)
{
if (doc.Kind != Constants.vsDocumentKindText)
continue;
foreach (Window window in doc.Windows)
{
IDesignerHost windowHost = window.Object as IDesignerHost;
if (windowHost != null && windowHost == host)
return doc;
}
}
return null;
}
private static void OpenCodeDoc(DTE dte, Document document)
{
bool codeOpen = dte.get_IsOpenFile(Constants.vsViewKindCode, document.FullName);
if (!codeOpen)
{
ItemOperations ItemOp = dte.ItemOperations;
ItemOp.OpenFile(document.FullName, Constants.vsViewKindCode);
}
}
}
drdexter33
To find the name of the form that the component is placed on during initialization from the component designer, you can use this code:
internal class LTGlobalDesigner : IDesigner
{
…………………. Code
public void Initialize(System.ComponentModel.IComponent component)
{
this.component = component;
IDesignerHost ixHost = (IDesignerHost)this.component.Site.GetService(typeof(IDesignerHost));
IContainer ixContainer = ixHost.Container;
Form ixForm = (Form) ixContainer.Components[0];
MessageBox.Show(ixForm.Name); // just for verification
}
……………… code
}
dholt
f_scholer
Marc68
audreynsarah
AndyPowell
That last piece of code has just solved my one of the biggest initialization problems; I finally know when the control is getting initialized at design time
Unfortunately I still have many other problems writing the themed controls, but at least I am one step ahead now.
Because of your code I was finally able to load the themes properly to a static buffer at design time.
internal static void Initialize(EnvDTE._DTE ixDTE, IDesignerHost ixHost)
{
ixInitialized = true;
if(ixDTE != null)
{
EnvDTE.Project ixProject = null;
foreach(EnvDTE.Document ixDocument in ixDTE.Documents)
{
foreach (EnvDTE.Window ixWindow in ixDocument.Windows)
{
IDesignerHost ixWindowHost = ixWindow.Object as IDesignerHost;
if (ixWindowHost != null && ixWindowHost == ixHost)
{
ixProject = ixDocument.ProjectItem.ContainingProject;
}
}
}
if(ixProject != null)
{
string ixFilePath = ixProject.Properties.Item("FullPath").Value.ToString() + "SmartLibrary Themes.resx";
ResXResourceWriter ixThemeFile = new ResXResourceWriter(ixFilePath);
ixThemeFile.AddResource("File Version", "SmartLibrary 0.2 Theme File");
ixThemeFile.AddResource("Themes List", ixThemeStoreCollection);
ixThemeFile.Generate();
ixThemeFile.Close();
ixProject.ProjectItems.AddFromFile(ixFilePath);
ixProject.ProjectItems.Item("SmartLibrary Themes.resx").Properties.Item("BuildAction").Value = 3;
}
}
else
{
MessageBox.Show("Runtime");
}
}
By calling the code from the control at design time:
public override ISite Site
{
get
{
return base.Site;
}
set
{
base.Site = value;
LxThemeManager.Initialize(((_DTE)value.GetService(typeof(_DTE))),
(IDesignerHost) value.GetService(typeof(IDesignerHost)) );
}
}
Of course the my code is still not completed yet and have some bugs, but the idea works
_Igor
I have it working on some computers and not working on other, or working sometimes on the same computer and sometimes not.
Is it that complicated Microsoft Millions of lines of documentation, and there is no single line explaining how for sure to get the existing EnvDTE.Projectitem that the form or component is stored in.
All what I want is: when the component gets initialized (in the designer), I need the EnvDTE.ProjectItem that the component is stored in it!