Home > Net >  C# TabController || Clone Web Browser and get the name of it
C# TabController || Clone Web Browser and get the name of it

Time:05-14

I'm currently working on a project but I can't get any further I have a tab and a button that creates another tab, the code for it looks like this

public void newtab()
{

    tabpage   ;

    string namesys = tabpage   " - Script";
    Random rnd = new Random();
    this.web = new System.Windows.Forms.WebBrowser();
    this.bt = new System.Windows.Forms.Button();
    this.tp = new System.Windows.Forms.TabPage();
    this.lb = new System.Windows.Forms.Label();

    tp.Text = namesys;

    bt.Location = new Point(3, 374);
    bt.Text = "Execute";
    this.bt.Click  = new System.EventHandler(this.tabexecute);

    for (int j = 0; j < 4; j  )
    {
        Console.WriteLine(rnd.Next());
    }
    int randit =  rnd.Next();
   
    lb.Location = new Point(414 ,377);
    lb.Text = randit.ToString();
    lb.ForeColor = Color.Black;
    lb.Name = "Code";

    web.Name = lb.Text;
    web.Url = new Uri(string.Format("file:///{0}/Ace/AceEditor.html", Directory.GetCurrentDirectory()));
    web.Location = new Point(3, 8);
    web.Size = new Size(919 ,360)  ;

    tp.Controls.Add(web);
    tp.Controls.Add(lb);
    tp.Controls.Add(bt);
    tabControl1.Controls.Add(tp);
}

but now I have the problem when you are in the tab created above the code, private void tabexecute was not working (see code)

private void tabexecute(object sender, EventArgs e)
{

    HtmlDocument document = webBrowser1.Document;
    string scriptName = "GetText";
    object[] args = new string[0];
    object obj = document.InvokeScript(scriptName, args);
    string script = obj.ToString();

    API.SendLuaCScript(script);
    API.SendLuaCScript(txt_inject.Text);     
}

Because I don't know how to do HtmlDocument document = webBrowser1.Document; can be rebuilt so that it always uses the web browser where it is currently in the tab. The web browser name is randomly generated each time a tab is created.

Here is a screenshot that might clarify the issue:

enter image description here

CodePudding user response:

Given that you seem to need to manage state for each WebBrowser you create on a tabpage your best option is to create a new class that subclasses the WebBrowser class. That subclass has the single responsibility to execute those calls in your tabExecute method. That class might look like this:

public class TabWebBrowser:WebBrowser
{

    private TextBox txt_inject;
    
    // needed state
    public void SetInject(TextBox textBox) 
    {
        txt_inject = textBox;
    }

    // Click eventhandler
    public void Execute(object sender, EventArgs e) {
    
        System.Windows.Forms.HtmlDocument document = this.Document;
        string scriptName = "GetText";
        object[] args = new string[0];
        object obj = document.InvokeScript(scriptName, args);
        string script = obj.ToString();

        API.SendLuaCScript(script);
        API.SendLuaCScript(txt_inject.Text);
    }
}

Now we need to instantiate, wire the Click event and provide needed references to other object instances, for example the textbox you called txt_inject:

... code omitted

string namesys = tabpage   " - Script";
Random rnd = new Random();

var twb = new TabWebBrowser(); // Create a new instance of our own subclass

this.web = twb;  // Set our instance as the WebBrowser to use
this.bt = new System.Windows.Forms.Button();

... code omitted

// wire up the Click event
this.bt.Click  = twb.Execute;

// the Execute method needs a txt_inject reference, no idea where that came from
// but .. let's set that as well here

twb.SetInject(txt_inject);

... rest of your code omitted

And that should do it.

CodePudding user response:

Probably the easiest

It would be probably the easiest, to use an inline event handler like this:

public void AddNewTab()
{
    ...
    //Pay attention to var to declare local variables
    var webBrowser = new WebBrowser();
    var button = new Button();
    ...
    button.Click  = (sender, e) => {
        var document = webBrowser.Document;
        ...
    };
}

Probably the best

And it would probably be the best if you create a UserControl, hosting the WebBrowser, the Button, and other controls, and encapsulating related logic:

public void AddNewTab()
{
    ...
    var userControl = new MyUserControl();
    ...
    
}
private void ExecuteButtonClick(object sender, EventArgs e)
{
    var userControl = (MyUserControl) sender;
    var webBrowser = userControl.WebBrowser;
    ... 
}

You can even use designer for arranging the controls later just create a new instance of the UserControl in the code and get rid of all those control instantiation and those layout related code.

You can expose the properties and events that you may need outside of the UserControl; For properties, it could be the whole WebBrowser control or the Document, and etc. For events, it could be an ExecuteButtonClick event, which will be raised when you click on the button.

Then in the form, by clicking on the AddNewTab button, you just need to instantiate a new instance of your UserControl and pass the required properties to it. Also you can handle ExecuteButtonClick, and do whatever you need.

And finally just for learning purpose

And finally just for learning purpose, to learn ow you can use the sender parameter of an event handler and see how you can find controls, you can change your tabexecute event handler to this:

private void tabexecute(object sender, EventArgs e)
{
    //The Button in the TabPage:
    var button = (Button) sender; 
                 
    //The TabPage: 
    var tabPage = button.Parent;   
                
    //The WebBrowser in the TabPage:
    var webBrowser = tabPage.Controls.OfType<WebBrowser>().First(); 
   
    var document = webBrowser.Document;
    ...
}

Points of improvement/learn more

  • Related