Hello (and sorry for my English), I have a problem with Printing RTF using RichTextBoxPrintCtrl and TabControl.
1) The tabcontrol got no tabs on Design, when the Form Load, it will get a tab with the method AddTab(Title). (Don't mind about other variables).
private void AddTab(string Name = "Nuova Nota*")
{
RichTextBox Body = new RichTextBox();
Body.Name = "Body";
Body.Dock = DockStyle.Fill;
Body.ContextMenuStrip = contextMenuStrip1;
TabPage NewPage = new TabPage();
string DocumentText = Nome;
if (Nome == "Nuova Nota*")
{
TabCount += 1;
DocumentText = Nome + TabCount;
}
NewPage.Name = DocumentText;
NewPage.Text = DocumentText;
tabControl1.Visible = true;
NewPage.Controls.Add(Body);
tabControl1.TabPages.Add(NewPage);
tabControl1.SelectedTab = NewPage;
Nomi_Files.Add(NewPage.Text);
Path_Files.Add("");
}
2) Once the tab is created, you can start to write, change colors, fonts, etc...
To get access on the document that you are making, i use a GetCurrentDocument that return the "Body" of the selected tab:
private RichTextBox GetCurrentDocument
{
get { return (RichTextBox)tabControl1.SelectedTab.Controls["Body"];}
}
Now, all the functions (save, open, fonts, colors...) Works Fine, i wanted to print my document and keep the style, so i Googled and i found this: How to print the content of a RichTextBox control by using Visual C#
I made the RichTextBoxPrintCtrl.dll, added the resource on my project, added the item inside the toolbox, but i can't change the RichTextBox that i create from Code, with RichTextBoxPrintCtrl.
The error that i get is:
Error 1 'RichTextBoxPrintCtrl' is a 'namespace' but is used like a
'type'
How i can use that RichTextBoxPrintCtrl without drag and drop it inside the design form?
Ok, i figured out how to solve it:
instead of declaring like:
RichTextBoxPrintCtrl NameControl = new RichTextBoxPrintCtrl();
we need to declare the namespace so:
RichTextBoxPrintCtrl.RichTextBoxPrintCtrl NameControl = new RichTextBoxPrintCtrl.RichTextBoxPrintCtrl();
Everything works fine :) thanks;
Related
I have a custom Tabs Control I created. It works as a coloured Label for the tab itself and as a Panel to hold the contents. My application reads UI parameters from config files. Take this line as an example from the controls config:
RTFBOX=(ID - rtf1) (BOUNDS - 0,0,100,100) (MULTILINE - enable) (FILE - email_rules.rtf)
This line tells the application to create an instance of my custom RichTextBoxPlus class and the important thing to take from this is that it is set up to read rich text from the FILE parameter. If I don't add this RichTextBoxPlus to another Control it shows it's rich text formatting absolutely fine.
I have another config that reads actions at runtime, this can be simple stuff like telling a Button created with the controls config that when it is clicked, it should fire off an email using content from a TextBox control. I have an action that pairs controls to each tab in the Tabs custom control. For example:
ADDTOTABS=(OBJECT - tabsControl1) (CONTROLS - panel1, panel2)
This finds tabsControl1 and adds panel1 to the 1st tab and panel2 to the 2nd tab. In this example, Panels are being added to each tab instead of individual controls as the Panels could hold multiple controls, handled at runtime through the ADDTOPANEL action.
ADDTOPANEL=(OBJECT - rtf1) (TARGET - panel1) (TRIGGER - onload)
So the rtf1 instance of RichTextBoxPlus is added to panel1 which is then added to the respective Panel of the Tabs control's 1st tab.
What I have found is rtf1 displays with rich text formatting absolutely fine if added to panel1 but not adding panel1 to Tabs.
The ADDTOTABS action executes this method:
private void TabContents_Action(Tabs tabpanel, string[] ctrls)
{
string[] tabs = tabpanel.GetTabNames();
for(int i = 0; i < tabs.Length; i++)
{
Control control = this.Controls.Find(ctrls[i], true).FirstOrDefault();
tabpanel.SetTaggedObject(control, tabs[i]);
}
tabpanel.SetTabActive(tabs[0]);
}
The SetTaggedObject method of the Tabs class finds the Panel control that corresponds with the tab name provided:
public void SetTaggedObject(Control ctrl, string tab)
{
Control container = this.Controls.Find(tab, false).FirstOrDefault();
container.Controls.Add(ctrl);
}
Doesn't seem to be anything untoward about this method.
The SetTabActive method of the Tabs class has a little more bulk. This handles changing the appearance of all tabs so that inactive tabs look different to the active tab. It is also hides and shows the panels for each tab based on whether the tab is active.
public void SetTabActive(string tab)
{
LabelPlus activeTab = this.tabs.Find(x => x.Name.Equals(tab));
List<LabelPlus> inactiveTabs = new List<LabelPlus>(this.tabs.FindAll(x => !x.Name.Equals(tab)));
activeTab.BackColor = this.ActiveColor;
activeTab.ForeColor = this.ActiveForeColor;
string panelName = tab.Remove(tab.Length - this.tabSuffix.Length);
Panel activeTabPanel = (Panel)this.Controls.Find(panelName, true).FirstOrDefault();
activeTabPanel.Bounds = new Rectangle(
new Point(this.tabStart, this.originalLocation.Y + this.TabTotalHeight), this.Size);
ControlCollection activeTabCtrls = activeTabPanel.Controls;
foreach(LabelPlus inactiveTab in inactiveTabs)
{
inactiveTab.BackColor = this.InactiveColor;
inactiveTab.ForeColor = this.InactiveForeColor;
string inactivePanelName = inactiveTab.Name.Remove(inactiveTab.Name.Length - this.tabSuffix.Length);
Panel inactiveTabPanel = (Panel)this.Controls.Find(inactivePanelName, true).FirstOrDefault();//
inactiveTabPanel.Bounds = new Rectangle(
new Point(this.tabStart, this.originalLocation.Y + this.TabTotalHeight), this.Size);
ControlCollection inactiveTabControls = inactiveTabPanel.Controls
foreach (Control ctrl in inactiveTabControls) { ctrl.Location = new Point(0, ctrl.Location.Y); ctrl.Hide(); }
}
foreach (Control ctrl in activeTabCtrls)
{ ctrl.Location = new Point(0, ctrl.Location.Y); ctrl.Show(); }
}
Not sure but I'd say the issue must be in this method. Any thoughts?
I'm a newbie in c# and probably going to ask a very easy question, but I've not been able to find anything on the web to help.
I have a tabControl with a TabPage which is containing a TextBox object; this object, when the event "Text changed" is invoked, will perform the change of the parent tabPage's name.
The textbox where I typed "text changed by me" has a method which is managing changing the name of the tabPage:
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (this.textBox1.Text != "")
this.tabControl2.SelectedTab.Text = this.textBox1.Text;
else
this.tabControl2.SelectedTab.Text = "(no name)";
}
Into the current page menu is contained a control to add a new page, which runs this method when the user click on it:
private void addNewPageToolStripMenuItem_Click(object sender, EventArgs e)
{
int numPagine;
string strPagine;
numPagine = this.tabControl2.TabCount;
strPagine = numPagine.ToString();
this.tabControl2.TabPages.Add("new page" + strPagine);
}
...and here is the output, which is expected since I'm just asking to add a new empty tabPage:
So, my question is: how can I make possible that when the user is clicking on "Add new page", rather than creating an empty new tabPage the program is rather creating a page like the first one (i.e. containing a textbox into the same position which has a method to change the text of the parent tabPage that I have just created?
Here is an example.
//..
// create the new page
TabPage tpNew = new TabPage("new page..");
// add it to the tab
this.tabControl2.TabPages.Add(tpNew);
// create one labe with text and location like label1
Label lbl = new Label();
lbl.Text = label1.Text;
lbl.Location = label1.Location;
// create a new textbox..
TextBox tbx = new TextBox();
tbx.Location = textBox1.Location;
tpNew.Controls.Add(lbl);
tpNew.Controls.Add(tbx);
// add code to the new textbox via lambda code:
tbx.TextChanged += ( (sender2, evArgs) =>
{
if (tbx.Text != "")
this.tabControl2.SelectedTab.Text = tbx.Text;
else
this.tabControl2.SelectedTab.Text = "(no name)";
} );
For more complicated layout you may want to consider creating a user control..
You also may want to create the first page with this code; the, of course with real values for text and positions!
For creating a UserControl you go to the project tag and right click Add-UserControl-UserControl and name it, maybe myTagPageUC. Then you can do layout on it like on a form. A rather good example is right here on MSDN
The problem is that is has no connection to the form, meaning you'll have to code all sorts of references to make it work..
I'm not really sure if you may not be better off writing a complete clonePage method instead. It could work like the code above, but would loop over the Controls of the template page and check on the various types to add the right controls..
It really depends on what is more complicated: the Layout or the ties between the pages and the form and its other controls..
I have a C# Form application that has a TabControl in the main form. This TabControl is used to display multilple TabPages that contain a CustomControl. This CustomControl is just a Panel with a few buttons and a PictureBox.
Here is a picture of my app when it starts up. As you can see the tab control (the white area) is empty:
If the user clicks the "Add Image" button they are presented with an OpenFileDialog to select the image then the addImage method is called with the selected file:
private void doAddImage()
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = Constants.Global.IMAGE_FILE_FILTER();
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string imageFileName = openFileDialog.FileName;
addImage(imageFileName);
}
}
private void addImage(string imageFileName)
{
// Create a new bitmap and image preview custom control. Then create a new tab
// page and add the custom control to the tab page.
Bitmap bitMap = new Bitmap(imageFileName);
ImagePreviewCustomControl previewControl = new ImagePreviewCustomControl(bitMap);
previewControl.Dock = DockStyle.Fill;
TabPage tabPage = new TabPage(Path.GetFileNameWithoutExtension(imageFileName));
tabPage.Controls.Add(previewControl);
// Insert the new tab page to the right of the currently selected tab page
int selectedTabIndex = imagesTabControl.SelectedIndex;
imagesTabControl.TabPages.Insert(selectedTabIndex + 1, tabPage);
imagesTabControl.SelectedIndex = selectedTabIndex + 1;
}
As you can see, in the addImage method I create the Bitmap, CustomControl, and TabPage and then insert it into the TabControl.
I start my application, click the "Add Image" button, everything works just fine.
Here is a picture with a tab page added:
While I am testing my app I don't want to have to add an image manually using the OpenFileDialog every time so in my constructor I just call addImage with some fixed image file name that I want to test with:
public ImageViewerApp()
{
InitializeComponent();
addImage(#"C:\MyImages\Calculator-3-icon.png");
}
The problem I am having is that when I try to add the image in my constructor it doesn't show up in the TabControl. The application starts up blank (like the first picture).
As stated above when the application is already running and I click the "Add Image" button it gets added just fine.
I found a property in the TabControl class called Created which states:
"Gets a value indicating whether the control has been created"
So to try and figure out what's going on I write the value of Created to the console just before I call addImage in the constructor. (I have a custom console for debugging my Form applications.)
public ImageViewerApp()
{
InitializeComponent();
TestConsole.WriteLine(imagesTabControl.Created);
addImage(#"D:\Development\Work\Other\Stardock\Start8\_downloaded\Calculator-3-icon.png");
}
The value of Created just before the call to addImage in the constructor is:
False
I put another console output inside the addImage method:
private void doAddImage()
{
TestConsole.WriteLine(imagesTabControl.Created);
OpenFileDialog openFileDialog = new OpenFileDialog();
...
...
}
The value of Created after the app has started and the user presses the "Add Image" button is:
True
Why is it that the TabControl is not Created inside my constructor (even after the InitializeComponent() call) and the once the application is running it is Created?
=UPDATE========================================================================
Based on the suggestion by Hans Passant I have added the following code to my addImage method:
int selectedTabIndex = -1;
if (imagesTabControl.TabCount > 0)
{
selectedTabIndex = imagesTabControl.SelectedIndex;
}
else
{
selectedTabIndex = imagesTabControl.SelectedIndex + 1;
}
imagesTabControl.TabPages.Insert(selectedTabIndex, tabPage);
imagesTabControl.SelectedIndex = selectedTabIndex;
This doesn't work.
===============================================================================
=UPDATE2=======================================================================
int selectedTabIndex = imagesTabControl.SelectedIndex;
if (imagesTabControl.TabCount == 0) selectedTabIndex = -1;
imagesTabControl.TabPages.Insert(selectedTabIndex, tabPage);
imagesTabControl.SelectedIndex = selectedTabIndex;
This causes the following Exception:
{"InvalidArgument=Value of '-1' is not valid for 'index'.\r\nParameter name: index"}
===============================================================================
=UPDATE3=======================================================================
I tried the folllowing code:
int selectedTabIndex = imagesTabControl.SelectedIndex;
if (imagesTabControl.TabCount == 0) selectedTabIndex = -1;
imagesTabControl.TabPages.Insert(selectedTabIndex + 1, tabPage);
imagesTabControl.SelectedIndex = selectedTabIndex + 1;
This one doesn't throw an exception but again no tab page added after calling
addImage in the constructor.
===============================================================================
=UPDATE4=======================================================================
I have kindof given up on adding an image in the constructor. So instead I am using an enum RunMode and a variable RUN_MODE of that type. Then, if RUN_MODE == RunMode.TESTI call a method to add a random image when I click the button. (The OpenFileDialog is not used. I just parse through all the image files in the fixed directory IMAGE_DIRECTORY.
enum RunMode { NORMAL, TEST }
private static string IMAGE_DIRECTORY = #"D:\\Work\Images";
...
...
private void doAddImage()
{
if (RUN_MODE == RunMode.TEST)
{
addRandomImage();
return;
}
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = Constants.Global.IMAGE_FILE_FILTER();
if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string imageFileName = openFileDialog.FileName;
addImage(imageFileName);
}
}
private void addRandomImage()
{
string[] allFiles = Directory.GetFiles(IMAGE_DIRECTORY);
List<string> imageFileNames = new List<string>();
foreach (string file in allFiles)
{
bool isImageFile = Constants.Global.IMAGE_EXTENSIONS.Contains(Path.GetExtension(file));
if (isImageFile)
{
imageFileNames.Add(file);
}
}
int randomIndex = new Random().Next(imageFileNames.Count);
addImage(imageFileNames.ElementAt(randomIndex));
}
This works. Now when I click the "Add Image" button during TEST_MODE I skip the
OpenFileDialog and just add a random image.
I would like to understand the issues with TabControl but at this point I just
need to continue development. My current solution works great.
As I person who like to understand everything I would like to use other people's
suggestions so I will keep monitoring this question for a solution.
===============================================================================
JonP's answer gave me the idea to just wait for the window handle to be created before inserting the tab, so I tried some events occuring between Form construction and Tab Control display.
I found it to work with both the Load or Shown events:
Right-click on the Form (the root, not child controls) in the Designer view > Properties > Events (flash icon) > Behavior > enter a method name for the Load or Shown event and confirm. To generate a Load event callback you can also double-click on the Form itself. This should generate something like this:
this.Load += new System.EventHandler(this.Form1_Load);
// or
this.Shown += new System.EventHandler(this.Form1_Shown);
Setup the tabs in the callback:
private void Form1_Load(object sender, EventArgs e)
{
// Add image (this will call imagesTabControl.TabPages.Insert(selectedTabIndex + 1, tabPage))
// This must be done on Load event because Insert requires
// the window handle, which is not ready in the constructor
addImage(#"path_to_image.png");
}
I have had this problem too and have found a workaround; I think it must be a bug with Insert():
Don't use Insert(), it usually does nothing, use Add() instead; this reliably adds a TabPage to the end of the collection.
After adding it swap it with the tab position where you actually want it.
imagesTabControl.TabPages.Add(tabPage);
// Now swap the two tabs:
imagesTabControl.TabPages[imagesTabControl.TabCount - 1] = imagesTabControl.TabPages[selectedTabIndex + 1];
imagesTabControl.TabPage[selectedTabIndex + 1] = tabPage;
Your mileage may vary of course :-)
Stop Press! An even better fix is to read the class's Handle member before calling Insert():
var handle = imagesTabControl.Handle;
Insert() works perfectly after you do that. Obvious isn't it???? The help page for Handle has this possible relevant Remark showing that the object actually does something when you read Handle:
The value of the Handle property is a Windows HWND. If the handle has not yet been created, referencing this property will force the handle to be created.
You could remove the TabControl from the designer and then instead just manually create the TabControl programmatically and add it to the Form immediately after InitializeComponent(). Then after you create the TabControl, call addImage(). Something like:
InitializeComponent();
TabControl tc = new TabControl();
tc.Location = new Point(10, 10);
tc.Size = new Size(100, 100);
tc.Visible = true;
tc.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Top);
this.Controls.Add(tc)
addImage("c:\pathToImage\image.bmp");
I am dynamically creating buttons in C# with this logic
for (int i = 1; i <= vap; ++i)
{
newButtons[i] = new Button();
newButtons[i].BackColor = Color.Gray;
newButtons[i].Name = "Button4" + i.ToString();
newButtons[i].Click += new EventHandler(NewButtons_Click);
newButtons[i].Location = new System.Drawing.Point(width,height);
newButtons[i].Size = new System.Drawing.Size(76, 38);
tabPage5.Controls.Add(newButtons[i]);
}
This is creating a button and the click event is also working but my problem is I don't know how to get the text of the newly created button. On form load I am putting the text of button from database and this also happening correctly, but I want to know how to get the text of dynamically created buttons.
You won't be able to get the text until after you populate it from the database (careful not to try and get the text too early).
But this should work:
string buttonText = FindControl("Button41").Text;
Update
Since you want the button text from within the click event, you can access the sender object:
Button button = sender as Button;
string buttonText = button.Text;
You just have to set the Text property of the button when you add it.
Using something along the lines of...
string BtnTxt = FindControl("ExampleButton1").Text;
should work fine.
This may cause problems later on however if you are trying to pull text content of buttons in a random order.
I am working on a web browser project I want to make a web browser I used ToolStrip to put all the functions of the web browser(favorite, history, home, GO, back, forward). What I want now is to make tha Tabs.
1) what do you think the best way to implement the tabs is it TabControl or is there another way.
2) how do I make to click on a label next to each tab and I open the new tab with a label next to it. So I can open a third one and so on.
I found this code, but it does not add dynamically and it add the second tab with leaving the label on the first tab
this.tabControl1.SelectedTab = tabPage2;
1) i made a tabcontrol and deleted all the tabs in the form
2)i made a button look like a plus and one looks like a minus and added this code:
int Counter = 1;
this.tabControl1.TabPages.Add("Page " + Counter);
this.tabControl1.SelectTab(Counter - 1);
Counter = Counter + 1;
this will add a new tab with title page (1,2,3,4,..,n) and then i put a code when i press go to the specified Url:
RequestAndResponsHelper RS = new RequestAndResponsHelper(Url.Text);
StringBuilder s = new StringBuilder();
s = RS.GetRequest();//get the request from a different class
string HtmlString = s.ToString();
rtb = new RichTextBox();
rtb.AppendText(HtmlString);
rtb.Name = "RichText";
rtb.Dock = DockStyle.Fill;
this.tabControl1.SelectedTab.Controls.Add(rtb);