How to add ActiveX control at run time - c#

I am trying to add an activeX control in an user control in a C# windows form based project.
Now if I add that activeX component from the tools menu then by simply using drag and drop I am able use the activeX control.
But when I try to add that one at run time using C# code then it throw following exception:
"Exception of Type
'System.Windows.Forms.AxHost=InvalidActiveXStateException' was
thrown".
Using CreateControl() I am able to get rid of this exception but now the activeX control does not appear on the form.

When are you adding the control and where are you adding it on the form?
You would normally load the control in the constructor just after the component is initialized:
public FormRecalculation()
{
InitializeComponent();
loadDataSelector();
}
If there are any associated license keys you will need to set them and add them to the appropriate container on the form:
private void loadDataSelector()
{
//Initialize the DataSelector
DataSelector = new AXQDataSelector(getClsidFromProgId("QDataSelLib.QDataSel"));
if (DataSelector != null)
{
System.Reflection.FieldInfo f =
typeof(AxHost).GetField("licenseKey",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
f.SetValue(DataSelector, "license-here");
splitContainer1.Panel2.Controls.Add(DataSelector);
((System.ComponentModel.ISupportInitialize)(DataSelector)).BeginInit();
this.DataSelector.Dock = System.Windows.Forms.DockStyle.Fill;
this.DataSelector.Enabled = true;
this.DataSelector.Location = new System.Drawing.Point(0, 0);
this.DataSelector.Name = "DataSelector";
this.DataSelector.Size = new System.Drawing.Size(324, 773);
this.DataSelector.TabIndex = 0;
splitContainer1.Panel2.ResumeLayout();
((System.ComponentModel.ISupportInitialize)(DataSelector)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
else
{
return;
}
}
This is actually for a wrapped OCX but you get the idea...

ok, after some changes the code looks like this. Here at runtime four tabs are created. Initially, on first tab the control is displayed. When user clicks on other tabs page activex control added on those pages dynamically. (This code is written for a .net usercontrol. On run time this usercontrol is added to the form)
private void Populate()
{
int position;
int i = 0;
//here children in list of string type
foreach (string child in children)
{
this.productLineTabs.TabPages.Add(child);
AxSftTree treeadd = loadtree(this.productLineTabs.TabPages[i]);
this.tree.Add(treeadd);
this.tree[i].Columns = 2;
this.tree[i].set_ColumnText(0, "Col1");
this.tree[i].set_ColumnText(1, "Col2");
position = this.tree[i].AddItem(child);
i++;
}
form plv = new form();
plv.Controls.Add(this);
plv.Show();
}
private AxSftTree loadtree(TabPage tab)
{
AxSftTree treeobject = new AxSftTree();
((System.ComponentModel.ISupportInitialize)(treeobject)).BeginInit();
SuspendLayout();
tab.Controls.Add(treeobject);
treeobject.Dock = DockStyle.Fill;
ResumeLayout();
((System.ComponentModel.ISupportInitialize)(treeobject)).EndInit();
return treeobject;
}
You can find some details about this implementation on this page:
http://newapputil.blogspot.in/2013/11/how-to-add-activex-control-at-run-time.html

Related

Dynamically Generate Groupboxes

I'm working on an inventory program and have finished the main functionality as a command line console app. I am now working on a version for winforms. I want to enable it to dynamically generate a Groupbox that holds some textboxes. I'd rather not design 50+ lines of multiple textboxes. Keep in mind I'm rather new to programming, having started with C# a year ago. I know next to nothing on Winforms.
I've tried to use dynamic item = new Groupbox();as a similar method allowed generation of objects at runtime. In the command line app, the way it works is that based on information given, a certain amount of objects are passed into the list _AllItems. I was thinking of generating the Groupboxes by using:
private void InitializeGroupBox()
{
foreach (Product product in Product._AllItems)
{
dynamic Item = new GroupBox();
}
}
But I have the feeling I'm nowhere near the correct method. Thanks to anybody who helps.
You will need to learn a bit more, but here is what I usually do to achieve what you asked.
internal class DynamicForm : Form
{
private FlowLayoutPanel mFlowLayoutPanel;
public DynamicForm()
{
mFlowLayoutPanel = new FlowLayoutPanel();
mFlowLayoutPanel.Dock = DockStyle.Fill;
// Add to this Form
this.Controls.Add(mFlowLayoutPanel);
InitializeGroupBox();
}
private void InitializeGroupBox()
{
mFlowLayoutPanel.SuspendLayout(); // Performance
for (int i = 1; i <= 20; i++) {
var groupBox = new GroupBox();
groupBox.Text = "GroupBox #" + i;
groupBox.Size = new Size(200, 50);
var textBox = new TextBox();
textBox.Dock = DockStyle.Fill;
// Add the TextBox to GroupBox
groupBox.Controls.Add(textBox);
// Add to this Form
mFlowLayoutPanel.Controls.Add(groupBox);
}
mFlowLayoutPanel.ResumeLayout(); // after suspend, resume!
}
}

Making a tabbed cef sharp browser rename tab page

i have been creating a cefsharp browser in C#. i have made it so you can have multiple tabs and it loads the pages correctly. however, i cannot seem to find how i can rename the tab to the name of the page.
this is the code in the load event for form1.cs:
Cef.Initialize();
toolTip1.SetToolTip(button1, "Settings");
TabPage tab = new TabPage();
Tab newtab = new Tab();
newtab.Show();
newtab.TopLevel = false;
newtab.Dock = DockStyle.Fill;
tab.Controls.Add(newtab);
tabControl1.TabPages.Add(tab);
i have tried:
private void myBrowser_isLoading(object sender)
{
myBrowser.Parent.Parent.Text = myBrowser.Title;
}
but that doesn't work.
then this is the code for tab.cs:
public Tab()
{
InitializeComponent();
// Start the browser after initialize global component
InitializeChromium();
}
public CefSharp.WinForms.ChromiumWebBrowser myBrowser;
public bool nav = new bool();
public void InitializeChromium()
{
myBrowser = new CefSharp.WinForms.ChromiumWebBrowser("http://www.google.com");
this.Controls.Add(myBrowser);
myBrowser.Dock = DockStyle.Fill;
myBrowser.Parent = panel2;
if (nav == true)
{
myBrowser.Load(textBox1.Text);
nav = false;
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Cef.Shutdown();
}
again, i am using c# with the latest build of cef sharp(or atleast the one installed from the nuget package manager).
In your tab function in form1.cs, you need to add a title changed function like this
browser.TitleChanged += OnBrowserTitleChanged;
you also need to specify what browser is and set dockstyle to fill like this
ChromiumWebBrowser browser = new ChromiumWebBrowser("google.com");
tab.Controls.Add(browser);
browser.Dock = DockStyle.Fill;
now for the OnBrowserTitleChanged, you will need an EventArg which will tell the tab to have the document title in this format
this.InvokeOnUiThreadIfRequired(() => browserTabControl.SelectedTab.Text = args.Title);
this will add the document title to the tabcontrol browserTabControl is the name of the tabcontrol you will have to change browserTabControl to whatever name you have for the tabcontrol. Also the code you have does not belong with cef initialize. you need to create an addNewTab method with all the functions that will be processed when you want to add a new tab. Also, you cannot use a panel if you want to have tabs. you need a tabcontrol

TableLayoutPanel: How can i navigate with tab key through dynamically added controls?

I have a form which contains a dynamically added TableLayoutPanel, which contains some dynamically added Labels, TextBox, CheckBox. I am obtaining exactly the visualization I would like to have, but I am struggling to get the "tab key" to work for moving from one control to the other.
I have tried to add a:
control.TabIndex = tabIndex++;
control.TabStop = true;
But this doesn't seem to have any impact...
This is the (tested) stub code:
class MyForm : Form
{
public MyForm()
{
InitializeComponent();
string[] titles = {"first","second"};
var myLayout = new TableLayoutPanel();
myLayout.AutoSize = true;
int myTabIndex = 1; //Not really necessary
int rowNumber = 0;
foreach (var title in titles)
{
var label = new Label();
label.Text = title;
myLayout.Controls.Add(label, 0, rowNumber);
var control = new TextBox();
control.TabIndex = myTabIndex++; //Not really necessary
myLayout.Controls.Add(control, 1, rowNumber);
rowNumber++;
}
this.Controls.Add(myLayout);
}
}
This is the window I get, and I am not able to navigate from first to second field using the tab key.
Update:
Applying Visual Studio 2013 Update 5 did not help.
Something must have been corrupted in my project. The best I could do is to move on with a new clean Windows Form project, and everything now is working.

C# Windows.Forms converting code to WPF

I am trying to convert my Windows Form program into a WPF program in order to get images in my NotifyIcon systemtray icon. I am having issues converting it though. My current program has a tabcontrol1 and it uses the function: TabPages and DrawItem. WPF does not have these functions, but instead of TabPages it has Items, but I do not know what to change "DrawItem" to for WPF.
The reason why I am using "DrawItem" in my Windows Form is to change the color of the Tab text.
Changing from:
if (!find<T>(p.Value))
{
T myPage = new T();
myPage.Text = "Ping";
this.FormstabControl.TabPages.Add(myPage);
this.FormstabControl.DrawItem += new DrawItemEventHandler(ListBox1_DrawItem);
myPage.DataGridView.DataSource = p.Result;
}
To:
if (!find<T>(p.Value))
{
T myPage = new T();
myPage.Text = "Ping";
this.WPFtabControl.Items.Add(myPage);
//this.WPFtabControl.DrawItem += new DrawItemEventHandler(ListBox1_DrawItem);
myPage.DataGridView.DataSource = p.Result;
}
I had to comment out DrawItem because I do not know what to use instead. Also, type "T" is of type "TabPages" not Item. Below is the Find function that checks to see if the Tab already exists in the tabcontrol. When I declare myPage of type T, it setsup the DataGridView from within a different class (same as where T is defined.) I tried to fix it by throwing the WPF TabControl1 into a Windows.Form TabControl2, then searching through that tabcontrol's tabpages instead of passing a WPF Tabcontrol Item.
private bool find<T>()
{
bool found = false;
System.Windows.Forms.TabControl FormstabControl= new System.Windows.Forms.TabControl();
FormstabControl.TabPages.Add(this.WPFtabControl.Items.ToString());
foreach (TabPage page in FormstabControl.TabPages)
{
if (page is T)
{
found = true;
break;
}
}
return found;
}
private bool find<T>(string text) where T : TabPage
{
bool found = false;
System.Windows.Forms.TabControl FormstabControl= new System.Windows.Forms.TabControl();
FormstabControl.TabPages.Add(this.WPFtabControl.Items.ToString());
foreach (TabPage page in FormstabControl.TabPages)
{
if (page is T && text.Equals(page.Text))
{
found = true;
break;
}
}
return found;
}
When I run this app and the adjacent function, it runs and completes and adds a BLANK text tab, but returns no data to the datagrid within the TabControl. I do not know what is wrong.
How can I incorporate images in my NotifyIcon? I incorporate it like this:
this.notifyIcon.ContextMenu = new ContextMenu();
this.notifyIcon.ContextMenu.MenuItems.Add(new MenuItem("Hide", new EventHandler(hideApp)));
this.notifyIcon.ContextMenu.MenuItems.Add(new MenuItem("Show", new EventHandler(showApp)));
this.notifyIcon.ContextMenu.MenuItems.Add(new MenuItem("Exit", new EventHandler(exitApp)));

Form doesn't show anything

I am new to Winforms and C# so this may sound like a stupid question. I have the class shown below for creating a form to be displayed as a modal dialog.
class FrmDelivery : Form
{
ListBox s;
public FrmDelivery()
{
s = new ListBox();
s.DataSource = new List<int>(){1,2,3,4};
s.Update();
s.Show();
}
}
However for some reson when I use the ShowDialogmethod to display this form it doesnt show anything in it. What should I do to add a list box to this form ?
EDIT:
I use the code to display the form:
FrmDelivery frm = new FrmDelivery();
frm.ShowDialog();
One note - WPF uses Windows, not Forms, so I'm not clear why you're deriving from Form rather than Window. But I'll answer as if you were talking about a WPF Window as your "form".
First, something will need to display the Window. Currently, the code provided doesn't show the Window, it attempts to show a ListBox.
Second, you either need to add a LayoutPanel to the window and add your ListBox as a child of the layout panel. Layout Panels come in many flavors, such as Grids and StackPanels and Canvases based on what type of layout you want.
Or, you can set the Content of the Window to be your ListBox. This will mean the only thing on the Window is your ListBox', so if you want multiple visual elements on yourWindow`, you'll need to use a layout panel.
The second approach would look like
this.Content = s;
For the first approach, I'd recommend reading up on Layout Panels in WPF. Here is one tutorial and here is the MSDN topic on layout. A google search will yield many more results.
I suggest you create a new form using Add|New Item|Windows Form.
You will then get a design surface to which you can add a listbox, and generated code which will initialize your form and listbox correctly. In particular your form and listbox will gain default sizes which they don't have currently.
Your code (in say Form1.cs) will then be similar to this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.listBox1.DataSource = new List<int> { 1, 2, 3, 4 };
}
public int? SelectedValue
{
get
{
return (int?)this.listBox1.SelectedValue;
}
}
}
Plus there will be a load of code in Form1.Designer.cs similar to
....
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.listBox1 = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// listBox1
//
this.listBox1.FormattingEnabled = true;
this.listBox1.Location = new System.Drawing.Point(30, 37);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(120, 95);
this.listBox1.TabIndex = 0;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(284, 261);
this.Controls.Add(this.listBox1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
And you could use your form like this:
private void button1_Click(object sender, System.EventArgs e)
{
using (var form = new Form1()) // you should dispose forms used as dialogs
{
if (DialogResult.OK == form.ShowDialog()) // optional (you could have OK/Cancel buttons etc
{
Debug.WriteLine(form.SelectedValue ?? -1);
}
}
}
You should not only add the controls to the collection but also set up his caracteristics.
Size & emplacement, at least.
class FrmDelivery : Form
{
ListBox s;
public FrmDelivery()
{
s = new ListBox();
s.Location = new System.Drawing.Point(0, 0); //relative to the parent control (not an absolute value, so)
s.Name = "listBox1";
s.Size = new System.Drawing.Size(120, 95);
s.DataSource = new List<int>(){1,2,3,4};
this.Controls.Add(s); //it will add it to the form but you can add it to another control, like panel.
}
}
Hope it will help
You need to add the listbox to the controls collection:
ListBox s;
public FrmDelivery()
{
s = new ListBox();
s.DataSource = new List<int>() { 1, 2, 3, 4 };
this.Controls.Add(s);
}
This will get the control onto your form for you, though there are a bunch of other properties you will likely want to set (e.g. to get it looking how you want) - as others have mentioned, you can see how the designer does this in the code behind by putting a listbox onto a form and examining the resulting code.
Please see if you have the InitializeComponent() in the default construct commented out. It usually initializes all the control of the form on FormLoad.

Categories

Resources