|
Hi guys!
For showing context-sensitive help in one of my applications, I've created an HTML page with bookmarks for several topics.
In order to show the page, I'm simply using something like
Process.Start(pathToHtmlFile);
Unfortunately, I can't give a bookmark to jump to, because if I do, the path looks something like C:\Program Files\MyApp\AppHelp.htm#icons and therefor windows doesn't recognize the htm extension anymore
Also using file:///C:/Program Files/MyApp/AppHelp.htm#icons instead of the plain path doesn't work.
Any other ideas?
Thanks in advance.
Regards,
mav
--
Black holes are the places where God divided by 0...
|
|
|
|
|
Hi mav,
you could integrate a WebBrowser in your app, and order it to Navigate() wherever
you want.
|
|
|
|
|
I could, but I'd rather use the user's default browser...
In fact (and I'm a little ashamed about it) I had implemented a workaround some time ago, but while testing this app under Vista, the whole thing blew right into my face.
The idea then was to create a temporary html file containing a tiny javascript call to actually navigate to the real URL including the bookmark. This temporary file was called with Process.Start() .
After a 1 second wait I deleted the temp file. (that's the part I'm ashamed about now. The 1 second was hard-coded and isn't enough for Vista to start the browser. I even thought about posting it under WTF).
I _could_ increase the time, but it still feels like a hack.
That's why I was asking for a different way to do it, a cleaner way.
Regards,
mav
--
Black holes are the places where God divided by 0...
|
|
|
|
|
Hi,
if you are willing to spend the effort, here is an idea:
- find out what is the default browser; I think you could do this by using
Process.Start on any html file, then wait for idle, and look at StartInfo.
Or search the registry...
- now for each of your help items, do a Process.Start of the right browser app,
and pass the URL as the first argument. (I am hoping whatever the browser,
it always looks at its command line).
Of course, you could silently combine both methods: first time launch your
help file without bookmark (and note down the app info), later on use the above.
BTW: the WaitForIdle() is also an improvement on your earlier fixed 1 sec delay,
but I did not like your temp file much in the first place...
|
|
|
|
|
Luc Pattyn wrote: but I did not like your temp file much in the first place...
me neither...
At that time it seemed a good idea, tho (well, at least it was working...)
Regards,
mav
--
Black holes are the places where God divided by 0...
|
|
|
|
|
Hi,
I've created the following function (it gets forms from a pool):
public formType GetForm<formType>(string form_id) where formType : Form
I've stored the type of form I want to get in a Type variable somewhere, for example:
Type classToGet = typeof(Form);
The Form is just an example, this normally determined dynamically.
Now when I try to call my GetForm function like this:
GetForm<classToGet>("myformid");
I get a compiler exception saying "classToGet is a type parameter but is used like variable" and that "Type or namespace classToGet could not be found".
Is there anyway of solving this problem? I suppose there's a problem involving me not understanding reflection thoroughly enough. I realize I'm passing an argument of type Type but I can't seem te get my mind around converting the Type class to the class-reference I need here.
Thanks in advance for any help!
Standards are great! Everybody should have one!
|
|
|
|
|
This behaviour is because you are trying to use a variable instead of a type. This goes against the nature of generics which identifies information about an object at compile time.
Now, to get around this you would use:
GetForm<Form>("myformid");
|
|
|
|
|
I know how to get around it. The thing is, I want to provide the type at runtime using reflection. The reason for this is that somewhere in the GetForm method there's a line saying:
formType ret = Activator.CreateInstance<formType>();
I need to call the specific constructor for the type that's provided. This is why simply passing type Form will not do. Since I can ensure the compiler that the type passed will be a descendant of Form, I figured there's enough information for it to work with.
Standards are great! Everybody should have one!
|
|
|
|
|
I don't understand why you would want to do this in this way. As I stated before, generics are really handled at compile time. I knocked up the following quick routine to get a form.
namespace GenericForms
{
public static class TestForms
{
public static Form ShowForm(string formName)
{
return (Form)Activator.CreateInstance(Type.GetType(formName));
}
}
} Calling this becomes as simple as GenericForms.TestForms.ShowForm("Form1").ShowDialog(); .
|
|
|
|
|
The thing is, I'm working in a MDI application and want to store and retrieve all of the forms that were open when the application last closed. Here's my code, maybe not so pretty, but I think you'll get it...
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Drawing;
using System.Diagnostics;
namespace Tools
{
[Serializable]
public class FormsPool
{
/// <summary>
/// This dictionary will store the form's properties that we want to save to file.
/// </summary>
private Dictionary<string, FormData> dataPool = new Dictionary<string, FormData>();
/// <summary>
/// And this one is used to store forms at runtime.
/// </summary>
[field: NonSerialized]
private Dictionary<string, Form> formPool = new Dictionary<string, Form>();
/// <summary>
/// Get the form with the specified id.
/// </summary>
/// <param name="form_id">Unique string identifying the form to get.</param>
/// <returns></returns>
public Form GetForm(string form_id)
{
return GetForm<Form>(form_id);
}
/// <summary>
/// Returns the form with the given id from the pool. If it's not there, it'll be constructed.
/// </summary>
/// <typeparam name="formType">The form class you want to be returned.</typeparam>
/// <param name="form_id">The id for the form to return.</param>
/// <returns></returns>
public formType GetForm<formType>(string form_id) where formType : Form
{
if (formPool == null) // make sure our dictionaries are there
formPool = new Dictionary<string, Form>(); // (deserialization can set them to be null)
if (dataPool == null)
dataPool = new Dictionary<string, FormData>();
if (this.formPool.ContainsKey(form_id)) // check out if we have a reference to the form
{
if (formPool[form_id] != null)
return formPool[form_id] as formType; // if so, return it
else formPool.Remove(form_id);
}
formType ret = Activator.CreateInstance<formType>(); // not there, so create it
if (dataPool.ContainsKey(form_id)) // check for past references to this form
{ // and get the data used in that case
ret.StartPosition = FormStartPosition.Manual;
ret.Size = dataPool[form_id].size;
ret.Location = dataPool[form_id].location;
this.formPool.Add(form_id, ret);
}
else // otherwise, reset all parameters
{
FormData data = new FormData();
data.type = typeof(formType);
this.dataPool.Add(form_id, data);
this.formPool.Add(form_id, ret);
}
// the form that was asked for has been newly instantiated, so we'll need to track movement and sizechanges
ret.LocationChanged += delegate(object sender, EventArgs e)
{
foreach (string key in formPool.Keys)
{
if (formPool[key].Equals(sender))
{
if (dataPool.ContainsKey(key))
{
Form form = sender as Form;
FormData data = dataPool[key];
data.location = form.Location;
dataPool[key] = data;
}
}
}
};
ret.SizeChanged += delegate(object sender, EventArgs e)
{
foreach (string key in formPool.Keys)
{
if (formPool[key].Equals(sender))
{
if (dataPool.ContainsKey(key))
{
Form form = sender as Form;
FormData data = dataPool[key];
data.size = form.Size;
dataPool[key] = data;
}
}
}
};
return ret;
}
/// <summary>
/// Save all formdata to a file. Look out, no errorhandling.
/// </summary>
/// <param name="filename">The filename to store our data in.</param>
public void Save(string filename)
{
Stream stream = File.Open(filename, FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, this);
stream.Close();
}
/// <summary>
/// Return a formspool from file that was saved using the Save method.
/// </summary>
/// <param name="p"></param>
/// <returns></returns>
public static FormsPool FromFile(string filename)
{
Stream stream;
try
{
stream = File.Open(filename, FileMode.Open);
}
catch (FileNotFoundException)
{
return new FormsPool();
}
BinaryFormatter formatter = new BinaryFormatter();
FormsPool pool = null;
try
{
pool = formatter.Deserialize(stream) as FormsPool;
}
catch { }
finally
{
if (pool == null) pool = new FormsPool();
stream.Close();
}
return pool;
}
}
[Serializable]
public struct FormData
{
public Type type;
public string form_id;
public Point location;
public Size size;
}
}
Standards are great! Everybody should have one!
|
|
|
|
|
Biggest mistake :
this code :
Type classToGet = typeof(Form);
here Form is the base class of all the forms, so u cant use base class to get the type of form.
Instead if u use as argument in typeof() any derived class of base class(Form)then it will return that derived Class and base on it this code :
Type classToGet = typeof(DerivedClassOfForm);//Return Form "derived Class"
which you can during debug time it will view as GetForm<derivedclass>("myformId")
GetForm<classtoget>("myformid");
This is difficult to explain as well as to understand .For more details learn Factory Pattern from http://www.c-sharpcorner.com.
Regards
Chintan
www.visharadsoft.com
(Nothing is so purify as KNOWLEDGE)
|
|
|
|
|
Actually it doesn't work with Form-derived classes either: The Form class was really just an example: At runtime it can be any class implementing Form. Thank you anyway, I'll try and see what I can find at c sharp corner too.
Standards are great! Everybody should have one!
|
|
|
|
|
Generics are for compile-time type resolution. For run-time types, use abstract classes or interfaces.
-----
If atheism is a religion, then not collecting stamps is a hobby. -- Unknown
|
|
|
|
|
Dictionary<string, form=""> pool = new Dictionary<string, form="">(10);
pool.Add("myformid", new LoginForm());
pool.Add("myAboutformid", new AboutForm());
public class LoginForm : Form
{
}
public class AboutForm : Form
{
}
Type typLoginForm = typeof(LoginForm);
LoginForm lf = GetForm<typloginform>("myformid");
lf.ShowDialog();
public T GetForm<t>(string form_id) where T: Form
{
return pool[form_id] as T;
}
You can change the Dictionary<string,form> to Dictionary<string, collection<form="">> to add more than 1 item under the same key. Or Dictionary<type, collection<form="">> to get a pool item with its type instead of form_id value which is string.
Fire and Water, Love and Death, Sex and the City?
|
|
|
|
|
Thanks. But this way I'll be creating a new Form eacht time the GetForm function is called, while all I really want is a reference to an existing instance of the form if it exists, or a reference to a new instance if it doesn't. This works. The real problem for me is that the pool is serializable: Some basic data (location, position) can be stored and retrieved from a file. I save the info when the application is exited. When I start it up I want it to reconstruct each instance using its respective constructor...
Standards are great! Everybody should have one!
|
|
|
|
|
No, you won't be creating a new Form each time. It was just an example,
you can replace:
pool.Add("myformid", new LoginForm());
pool.Add("myAboutformid", new AboutForm());
as
pool.Add("myformid", myAlreadyCreatedLoginForm);
pool.Add("myAboutformid", myAlreadyCreatedAboutForm());
also:
GetForm(...) code I sent you does not create anything. Do you see any "new" keyword in the code/or am I blind?
Result:
- You have an assembly created in you bin\debug folder in which your Forms are also embedded. This is your store to create the Forms at run-time. You want to store some configuration related to your forms, so what you need is to store this configuration like size and location somewhere like an xml file. If you've done it(you've written Some basic data(location, position) can be retrieved from a file), then you want to get a Form from the pool. Then your pool is the one which is responsible of returning an instance of the Form type if there is already one, created in pre-call to GetForm(...) or you want to create a new instance with the configuration parameters stored using reflection. If this is what you want:
// The configurtation of the Form you serialize/deserialize
public class FormConfig : ConfigurationProperty /*or string, or xml file, or whatever you want */
{
}
public T GetForm<t>(string form_id) where T: Form
{
if(pool.ContainsKey(form_id))
{
return pool[form_id] as T;
}
else
{
// you may have a look at other overloaded method(s) of Activator.CreateInstance
return Activator.CreateInstance(T, new object[]{GetConfig(typeof(mySerializedForm))}) as T;
}
}
public FormConfig GetConfig(string key)
{
return ..... // return the deserialized config
}
public FormConfig GetConfig(Type key)
{
return ..... // return the deserialized config
}
"Peace at home, peace in the world"
Mustafa Kemal Atatürk(the founder of the Republic of Turkey and its first President.))
|
|
|
|
|
Hmm, I think I might have been having a bit of an off day in explaining what I was aiming for, but you guessed about right the second time. This line of code was close enough to what I was looking for:
return Activator.CreateInstance(T, new object[]{GetConfig(typeof(mySerializedForm))}) as T;
I've just been staring at the same CreateInstance method without ever realizing there's a bunch of overloads to choose from. Thanks very much for the help .
Standards are great! Everybody should have one!
|
|
|
|
|
If I could help you then I'm glad to win a coder's heart
|
|
|
|
|
Hi all,
I need help regarding how to communicate with OPCServer. i am developing application in C#. In project Reference i added OPCAutomation 2.0(COM) . I am adding the code which i done .
OPCServer MyServer = null;
OPCGroups MyOPCGroups = null;
OPCGroup MYOPCGroup = null;
MyServer = new OPCServer();
MyServer.Connect(ProgID,NODE);
// till here ok
MyOPCGroups =(OPCGroups) MyServer.OPCGroups;
// but when i tried to create the OPCGroups i am getting casting error //saying that " OPCAutmation.OPCServerClass to type OPCAutomation.IOPCGroup"
MYOPCGroup = (OPCGroup)MyOPCGroups.Add("MyGroup");
any help is appreciated
Regards,
Kotha.
|
|
|
|
|
Hi!
I have the same problem
Were you able to solve it?
Would be glad for any help...
Regards,
Alessandro
|
|
|
|
|
Hi.
I want to develope an application that this application will be installed on computers of a LAN.
Now I want the DataBase(Access , SQL Server) of these applications be one and on one of the computers(Server).
i.e. I want the DB be shared between these applications.
Best wishes
|
|
|
|
|
So make the connection string of the app point to the one DB, on the LAN.
Christian Graus - Microsoft MVP - C++
"I am working on a project that will convert a FORTRAN code to corresponding C++ code.I am not aware of FORTRAN syntax" ( spotted in the C++/CLI forum )
|
|
|
|
|
And if in same time 2 want to update one table what happens?
Best wishes
|
|
|
|
|
mehrdadc48 wrote: if in same time 2 want to update one table what happens?
SQL Server is a highly scalable multi user database system. You get versions from Express upto Enterprise which can handle thousands of users simultaneously. The database engine deals with it - that's what its good at.
Upcoming events:
* Glasgow: Mock Objects, SQL Server CLR Integration, Reporting Services, db4o, Dependency Injection with Spring ...
"I wouldn't say boo to a goose. I'm not a coward, I just realise that it would be largely pointless."
Ready to Give up - Your help will be much appreciated.
My website
|
|
|
|
|
You have a few choices, you can have it as last one to update wins, you could put in a check to see if the record has been updated since the last read (sql server provides the TIMESTAMP column type for this).
You could create some sort of checkout/checkin/lock system.
It all depends on what the app is for and how it will be used. This issue is called concurrency if you want to do some searching on the subject. I personally tend towards optimistic concurrency, but that is what normally suits my apps.
|
|
|
|