On 06/01/2005 5:10 AM, in article
83b31e2a.0501052110.529cb1aa@posting.google.com, "MailInterface"
> Iam creating Application implementing IDesigner host and facing
> problem when embedding image in the form.After embedding the image in
> the form when i compile i get an Error "resource not found".I tried
> this on the MSDN provided Sample Designer host and it is also giving
> the same error.Any clues solution this problem
The MSDN sample doesn't write out the resources except in its XML format, if
you change the code as follows (apologies if it gets mangled by line
breaks):
SampleResourceService.cs
using System;
using System.Resources;
using System.ComponentModel.Design;
using System.IO;
using System.Collections;
namespace SampleDesignerHost
{
/// Resource service using .resx files
public class SampleResourceService : IResourceService, IDisposable
{
private Hashtable writers;
private Hashtable readers;
private IDesignerHost host;
private MemoryStream ms;
// Track whether Dispose has been called.
private Boolean disposed = false;
public SampleResourceService(IDesignerHost host)
{
this.host = host;
writers = new Hashtable();
readers = new Hashtable();
}
~SampleResourceService()
{
Dispose(false);
}
private void SerializationComplete()
{
foreach (IResourceWriter writer in writers.Values)
{
if (writer != null)
{
writer.Close();
writer.Dispose();
}
}
writers.Clear();
foreach (IResourceReader reader in readers.Values)
{
if (reader != null)
{
reader.Close();
reader.Dispose();
}
}
readers.Clear();
}
public byte[] Resources
{
get
{
SerializationComplete();
return ms.GetBuffer();
}
}
#region Implementation of IResourceService
public System.Resources.IResourceReader
GetResourceReader(System.Globalization.CultureInfo info)
{
ResXResourceReader reader = (ResXResourceReader) readers[info];
if (reader == null)
{
if (ms == null)
{
ms = new MemoryStream();
}
reader = new ResXResourceReader(ms);
readers.Add(info, reader);
}
return reader;
}
public System.Resources.IResourceWriter
GetResourceWriter(System.Globalization.CultureInfo info)
{
ResXResourceWriter writer = (ResXResourceWriter) writers[info];
if (writer == null)
{
if (ms == null)
{
ms = new MemoryStream();
}
writer = new ResXResourceWriter(ms);
writers.Add(info, writer);
}
return writer;
}
#endregion
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(Boolean disposing)
{
// Check to see if Dispose has already been called.
if(!disposed)
{
SerializationComplete();
}
disposed = true;
}
#endregion
}
}
SampleDesignerLoader.cs - Save method
/// Save the current state of the loader. If the user loaded the
file
/// or saved once before, then he doesn't need to select a file
again.
/// Unless this is being called as a result of "Save As..." being
clicked,
/// in which case forceFilePrompt will be true.
internal void Save(bool forceFilePrompt)
{
try
{
if (dirty)
{
// Flush any changes to the buffer.
Flush();
}
// If the buffer has no name or this is a "Save As...",
// prompt the user for a file name. The user can save
// either the C#, VB, or XML (though only the XML can be
loaded).
//
int filterIndex = 3;
if ((fileName == null) || forceFilePrompt)
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.DefaultExt = "xml";
dlg.Filter = "C# Files|*.cs|Visual Basic Files|*.vb|XML
Files|*.xml";
if (dlg.ShowDialog() == DialogResult.OK)
{
fileName = dlg.FileName;
filterIndex = dlg.FilterIndex;
}
}
if (fileName != null)
{
switch (filterIndex)
{
case 1:
{
// Generate C# code from our codeCompileUnit and
save it.
CodeGeneratorOptions o = new
CodeGeneratorOptions();
o.BlankLinesBetweenMembers = true;
o.BracingStyle = "C";
o.ElseOnClosing = false;
o.IndentString = " ";
StreamWriter sw = new StreamWriter(fileName);
CSharpCodeProvider cs = new
CSharpCodeProvider();
cs.CreateGenerator().GenerateCodeFromCompileUnit(codeCompileUnit, sw, o);
sw.Close();
} break;
case 2:
{
// Generate VB code from our codeCompileUnit and
save it.
CodeGeneratorOptions o = new
CodeGeneratorOptions();
o.BlankLinesBetweenMembers = true;
o.BracingStyle = "C";
o.ElseOnClosing = false;
o.IndentString = " ";
StreamWriter sw = new StreamWriter(fileName);
VBCodeProvider vb = new VBCodeProvider();
vb.CreateGenerator().GenerateCodeFromCompileUnit(codeCompileUnit, sw, o);
sw.Close();
} break;
case 3:
{
// Write out our xmlDocument to a file.
StringWriter sw = new StringWriter();
XmlTextWriter xtw = new XmlTextWriter(sw);
xtw.Formatting = Formatting.Indented;
xmlDocument.WriteTo(xtw);
// Get rid of our artificial super-root before
we save out
// the XML.
//
string cleanup =
sw.ToString().Replace("<DOCUMENT_ELEMENT>", "");
cleanup = cleanup.Replace("</DOCUMENT_ELEMENT>",
"");
xtw.Close();
StreamWriter file = new StreamWriter(fileName);
file.Write(cleanup);
file.Close();
} break;
}
//------------------------------------------------
// SHL - Write out the resources into a resx file
{
SampleResourceService rs = (SampleResourceService)
this.host.GetService(typeof(IResourceService));
FileStream resxfile = new
FileStream(Path.ChangeExtension(fileName, ".resx"), FileMode.Create,
FileAccess.Write );
byte[] buf = rs.Resources;
resxfile.Write(buf, 0, buf.Length);
resxfile.Flush();
resxfile.Close();
}
//------------------------------------------------
unsaved = false;
}
}
catch(Exception ex)
{
MessageBox.Show("Error during save: " + ex.Message);
}
}
Then it will write out a .resx file for the form in the same way as VS.NET
does. You can then convert this to a .resources file using RESGEN.EXE in the
framework SDK, and you can link it with the code for the form in your call
to the command line compiler (i.e. VBC.EXE or CSC.EXE depending on your
language). If you don't want to require the SDK with your app, it's very
easy to reproduce this function of RESGEN (load the file with a
ResXResourceReader, write it out with a ResourceWriter) in your own code
before you call the compiler. Alternatively, you could change the
ResXResourceReader and ResXResourceWriter declarations in
SampleResourceService.cs above back to ResourceWriter and ResourceReader
respectively, but I find the resx format is useful as then you can open the
forms in VS.NET if necessary.
Hope that helps,
Simon
MailInterface ! - 09 Jan 2005 11:40 GMT
Hi Simon Lawrence,
Thank you very much for your detailed reply.But still
facing some problem.here is the replication steps.
Open the designer host and put a image as background image.go to the C#
code view,we can see the
System.Resources.ResourceManager resources = new
System.Resources.ResourceManager(typeof(form1));
entry in the Initialize component.Now go back to the designer view and
add one control into it.go back to the code view then you can notice
that
System.Resources.ResourceManager resources = new
System.Resources.ResourceManager(typeof(form1));
is missing and the entry
this.BackgroundImage =
((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage")));
has changed to
this.BackgroundImage =
((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage1")));
(Some times this happens after adding 2-3 controls).
At this time when i compile the project i will get error resource not
found.
Even the first time iam not able to run the application,if i have an
background on the form.
Have any idea about this problem?
Thanks
Simon Lawrence - 09 Jan 2005 15:27 GMT
On 09/01/2005 11:40 AM, in article ea0j8$j9EHA.2804@TK2MSFTNGP15.phx.gbl,
> Thank you very much for your detailed reply.But still
> facing some problem.here is the replication steps.
[Snip]
> System.Resources.ResourceManager resources = new
> System.Resources.ResourceManager(typeof(form1));
[quoted text clipped - 5 lines]
> this.BackgroundImage =
> ((System.Drawing.Image)(resources.GetObject("$this.BackgroundImage1")));
If I remember correctly you may need to subclass CodeDOMSerializer to handle
the ResourceManager member of the form as a special case. I'll have a look
through my own code and see what I can pull out and shove in to the sample
but it may take me a day or two to get round to it as my stuff is in VB.Net
rather than C sharp. I hadn't really looked at this sample in any detail
before and noticed that it takes some other shortcuts apart from the
resource stuff (e.g. not exposing a "Name" extender property for components
in the designer!) that have an impact on serialization to code. It would be
nice if copy/paste was implemented in it as well, as that's the bit I can't
get working in my own implementation.
Cheers,
Simon
Ulrich Sprick - 10 Jan 2005 22:13 GMT
Hi,
can someone point me to the SampleDesignerHost in MSDN? I simply can't find
it...
Thx!
ulrich
MailInterface ! - 11 Jan 2005 04:04 GMT
Here is the link
http://download.microsoft.com/download/f/d/9/fd986a23-d3d6-44c3-8fa0-75e
21b0094bf/designerhost.exe