I am new to C# windows application.I would like to add custom help file using help provider from the toolbar in Microsoft visual studio 2010 for windows application.
I can add my help file and that is working fine. I'd like to context-sensitive help and that is working fine with Help.ShowHelp(). In the properties window we have a HelpNavigator property where it has options like .Topic, .TopicId, .AssociateIndex, .TableOfContents, .Index, .Find. I have chosen .TopicId but i am wondering where to specify my topic ID. I have two questions
Is that possible ony by writing code in .cs file of the application?
If yes,then what is the purpose of help navigator property?
Short story - no, you can achieve this (F1-Help) without writing code (but sometimes coding is a better solution).
The HelpNavigator property is an enumeration that specifies the Help command to use when retrieving Help from the Help file for the specified control (see also: Help for controls with VB .NET).
Connecting a CHM help file with your application and providing context-sensitive help for controls has a small learn curve.
Below are (code) examples that demonstrate using context-sensitive help by F1 and how to open the help viewer by TopicId.
F1 - Help
Add a HelpProvider component to the form. This will add properties
like .HelpKeyword, .HelpNavigator, .HelpString, .ShowHelp.
Set the full path to your CHM file to the
HelpProvider.HelpNamespace property.
To enable the help ? button on the form's caption area, set the
values of the following form properties HelpButton = True,
MaximizeBox = False, MinimizeBox = False.
Use the control properties mentioned above to provide help for a
control when it has focus and F1 was pressed or the ?
button was clicked by the user. For example, set the button1
HelpKeyword property to 20010 and its HelpNavigator property to
.TopicId as shown in the screenshot below.
... and the resulting help viewer window:
Open the Help Viewer
Following code is used to open a Help Viewer and a topic by TopicId 10000:
private void btnTopicId_Click(object sender, EventArgs e)
{
Help.ShowHelp(this.btnOpenHelpShowTopic, helpProvider1.HelpNamespace, HelpNavigator.TopicId, #"10000");
}
Related
I've hit a frustrating issue with a software project I'm working on. I've got help set up on various forms such that if I press F1, the application's CHM file is opened.
I want it to always open to the topic related to the current form, however it currently opens to a different location depending on what part of the form is in focus. If some fields are in focus, it opens to the top of the first page of the help document; and if other fields are in focus it will open, correctly, to the page and heading related to the current form.
I have the following designer code for the various forms, and I'm only setting HelpKeyword on the form itself, not any of the form's controls.
this.helpProvider.HelpNamespace = #"Path\To\ChmFile.chm";
this.helpProvider.SetHelpKeyword(this, "TopicName.htm#heading_name");
this.helpProvider.SetHelpNavigator(this, System.Windows.Forms.HelpNavigator.Topic);
From experimentation, I've determined that items with either SetShowHelp(false) or Enabled = false are the only ones that show the correct chm help location. This applies when pressing F1 with them in focus (if they can hold focus), or pressing on them with the "what's this" help cursor.
As an example:
If focus is on the main dialog's first control (a TextBox which has a HelpString, which implicitly sets ShowHelp) and I press F1, I'll get sent to the overall application help page (undesired behaviour).
If focus is on a main dialog TextBox which does not have an associated help string, and I press F1, I'm shown the Dialogs help page, at the heading for the main dialog (desired behaviour).
The only workaround I've found for this so far is to set both HelpTopic and HelpNavigator on every control with a HelpString, but this is very heavy-handed and difficult to maintain.
Clarification
I am intentionally using both the "What's this?" help and the F1 help on the same forms. I will not accept a solution that says to disable "what's this" help for all controls on my form in order to allow the F1 help to work. It is a requirement for this application that interactive controls have a help tooltip, and that each dialog has a help section in the help document.
If there is no way to get these two help features to work together nicely, I will accept an effective workaround that does not sacrifice maintainability as my above workaround does.
It was only after your clarification that I was able to fully understand your question and reproduce the problem. This behavior was not known to me before.
Same undesired behaviour using Visual Studio 2019 on Windows 10 PC - it does not matter if it is coded in the Form_Load event or with the help of the IDE (Integrated Development Environment) in the designer code.
After some hours of experimenting (with the reproduced problem) I hopefully narrowed it down without fully knowing the real reason.
I have done the following steps and thoughts - FYI - experimentally (see special notes in the list below):
The default value of the HelpNavigator enumeration is AssociateIndex. If you accidentally set SetShowHelp = True and a required property is missing, the call to the Index tab may fail, corrupt something and goes to the CHM's home page topic. If you don't have an index tab in your CHM, another problem arises.
I deleted or renamed the file hh.dat several tines to reset all (!) CHM windows on my system to their default settings. Windows will create a new version of hh.dat when you next open any .chm file. You'd find hh.dat at C:\Users\%username%\AppData\Roaming\Microsoft\HTML Help. BUT - - no success with the existing problem in the first test phase.
For some more test only (code is not required later) I have tried if the Form3_HelpRequested is triggered. BUT - that did not work in the first test phase.
private void Form1_HelpRequested(object sender, HelpEventArgs hlpevent)
{
// do whatever you're gonna do here
DialogResult dr = MessageBox.Show("HelpRequested on Form1 was fired!\n\nOpen CHM help?","Test case", MessageBoxButtons.YesNo);
switch (dr)
{
case DialogResult.Yes:
// FALSE will also open any associated help file
hlpevent.Handled = false;
break;
case DialogResult.No:
// TRUE will prevent windows from also opening any associated help file
hlpevent.Handled = true;
break;
}
Last as a hard step I deleted the HelpProvider component, have inserted this again and set all properties correctly a second time. NOW - it is working for me. Controls with the property ShowHelp=True now show the assigned topic and controls with the property ShowHelp=False now show the help topic of the form as expected.
You know - this can be a complex step and should be done in a test environment first. Make sure that all properties are set correctly and that the topic is accessible in the CHM via HelpKeyword.
// Tell the HelpProvider what controls to provide help for, and what the help string is.
this.helpProvider1.SetShowHelp(this.cityTextBox, true);
this.helpProvider1.SetHelpNavigator(this.cityTextBox, HelpNavigator.Topic); // make sure to set "Topic"
this.helpProvider1.SetHelpKeyword(this.cityTextBox, #"/Garden/flowers.htm");
this.helpProvider1.SetHelpString(this.cityTextBox, "Enter the city here.");
After giving the city textbox focus and F1 the help viewer window is shown. Using the "What's this" ? button in a second step is resulting in:
tl;dr
The definition of the properties via designer code or program code is more a decision based on personal preferences. I myself prefer to set values in the program code rather than via the controls properties window of Visual Studio.
If you add here all the properties of the controls for the help functionality as code, you can easily comment out for fixing problems. In a form with many controls, it is easier to save parts of the code externally and insert them again later. But as I said - everybody likes it different.
// set F1 help topic for first form
private void Form1_Load(object sender, EventArgs e)
{
helpProvider1.SetHelpNavigator(this, HelpNavigator.Topic);
helpProvider1.SetHelpKeyword(this, #"/HTMLHelp_Examples/Jump_to_anchor.htm#SecondAnchor");
}
BTW - the "What's this?" help for large programs means a high effort and in my experience it is used less and less in help authoring (CHM's). This kind of help has a long history from the times of Visual Basic 6, for example. Today you often find only one help topic for a form or a dialog in which the single controls are explained. The problem you describe then does not appear at all.
FYI - in earlier days a ALIAS and MAP files was required and maybe used today by TopicId. The purpose of the two files is to ease the coordination between developer and help author. The mapping file links an ID to the map number - typically this can be easily created by the developer and passed to the help author. Then the help author creates an alias file linking the IDs to the topic names.
Creating Context-Sensitive Help for Applications
Where to specify topic id in c# windows application
I want to simulate drop event in my code on an outside control.
I am using a Gecko browser which connects to outside web application, which code I don't have access to.
I was thinking about two solutions to this, the first would be to simulate drop event providing a filepath, however what I did below is not working:
GeckoNode dropbox = ContentFrame.GetContentDocument().GetElementsByClassName("filepicker dropzone dz-clickable").FirstOrDefault();
if (NodeType.Element == dropbox.NodeType)
{
DependencyObject fakeobject = Application.Current.Windows[0] as DependencyObject;
GeckoHtmlElement drop2 = dropbox as GeckoHtmlElement;
drop2.Focus();
DragDrop.DoDragDrop(fakeobject, path, DragDropEffects.Copy);
}
The element which I can drop files into, on mouse click opens the "open file dialog".
The second, probably harder solution would be to somehow capture the dialog box and paste my path into it.
Or maybe there is a way to make my code still running independently of dialog box that appears and use SendKeys or something like that?
Thank you in advance for your help! (Two days of googling didn't bring me any useful results..)
Edit:
As there were no answers, maybe anyone could answer a simpler question:
How to simulate the drop event just in WPF/WinForms? What are the steps and declarations prior to use DoDragDrop (or similar) interface? I am trying to drop a file on a droppable control (simulated in C# code) on an external Website.
Thank you!
I have created a wpf application for context sensitive help using .chm files. I have created a a context sensitive help by pressing F1 after clicking a textbox or a button, thorugh xaml, AND NOT BY EVENT HANDLING. , but I need it for window also. I can have the window help as default in xaml when the window is loaded itself, which works now. But if i use text box help, then I cant switch back to window help since I have not included any events for that.
For this scenario, is using events the only possibility to include window help? what is the best practice? Is there a way to use window focus on xaml itself, or using event ends up as the best practice?
thanks a lot !!
Why not just implement a F1 Help System? it's pretty straightforward...
Take a look at this example HERE. This provides a HelpProvider class that gives you context sensitive help on any element that sets a HelpString. This should provide roughly what you need.
In your case, just make the chm file name your help name for each element you want a file sensitive to. And you could have something like so:
static private void Executed(object sender, ExecutedRoutedEventArgs e)
{
YourHelpSystem.ShowHelp(HelpProvider.GetHelpString(sender as FrameworkElement) + ".chm");
}
I created a user control using C# for windows form application. This user control has some properties. In runtime, if the user does not enter values for this properties I want to show a message box and exit the application.
The problem is when I write the checking code in the Load event of User Control. When I drag & drop it on the form the message box will appear.
private void UserControl1_Load(Object sender, EventArgs e)
{
if (_getFirstPageArgument==null || _getFirstPageArgument.Length==0)
{
throw new Exception("Some Message");
}
}
How do I distinguish between load on the form and load on run time?
I fear there is a larger problem here. But to solve your immediate problem (if I understand correctly...) There is a form attribute called DesignMode. When you are in the visual studio design mode, this will be true. At runtime, this will be false.
For beginners, #Nimas case can be a good study point to understand that Visual Studio actually runs and executes parts of our code even when we are in design time, which is why the constructor is invoked. Even "DesignMode" property is not 100% reliable. You can find an interesting note here related to that http://weblogs.asp.net/fmarguerie/archive/2005/03/23/395658.aspx
If you only want to know when the type itself has been loaded into the runtime (not a specific instance), you can put code into the static constructor for that class.
If I'm misinterpreting your question, please clarify using a timeline when you want specific events to happen.
I have a C# Winforms app that uses the HelpProvider class.
Whenever i press F1 to bring up help, the help window will always be on top of my application, I cannot bring my application UI to the foreground. I can still interact with my UI, but the help window will remain on top.
Is this by design of HelpProvider? Or am I missing something?
There is a solution to this issue, a bit dirty, but it works.
The thing is, the help window opened by HelpProvider is always on top of its parent window control, which is determined by Control instance in first parameter of Help.ShowHelp. Even if you specify null there, the main application form is still used as parent window.
To avoid this, one can create a dummy form, which will be used as a help parent form. This form will be never shown, but still, help window will be “on top” of it, effectively being NOT on top of all other application windows.
public static class AppHelp
{
private static Form mFrmDummyHost = new Form();
public static void ShowChm()
{
Help.ShowHelp(mFrmDummyHost, "my_help.chm");
}
}
Of course, all other Help.ShowHelp overloads can be called this way as well.
Hope this helps people like me, searching for answers to never-getting-old questions ;)
It is indeed by design, and its something that i did not realise. I have just recompiled my final year project and confirmed it. I have read up about it and basically the help file is set to TopMost=True every time the form is clicked. This means even if you code your form to be TopMost, as soon as you click the help file it will go back on top again.
I do believe if you use start process, it should get around the issue at the loss of some customisability the help provider gives.
private void textBox1_KeyDown(object sender,
System.Windows.Forms.KeyEventArgs e)
{
if(e.KeyCode ==Keys.F1)
{
System.Diagnostics.Process.Start(#"C:\WINDOWS\Help\mspaint.chm");
}
}
Hope it helps