questions about RichTextBox, overriding methods, StreamWriter etc. - Programmers Heaven

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

questions about RichTextBox, overriding methods, StreamWriter etc.

rai_netrai_net Posts: 51Member
[b][red]This message was edited by rai_net at 2003-10-2 22:14:18[/red][/b][hr]
[b][red]This message was edited by rai_net at 2003-10-2 20:53:22[/red][/b][hr]
greetings and salutations,

after using C# for several days I have numerous questions that I hope someone can answer.

[red]1.[/red] I am using a RichTextBox in an application so that I can change the colour of text and use several other features, however, I do not want the user to be able to paste anything other than text into the control. I wrote some code so that when the user clicked on the 'Edit' menu that contained the Paste MenuItem it would check to see if the clipboard only contained text or not and disable the Paste MenuItem if it didn't. The MenuItem had the Shortcut.CtrlV shortcut associated with it however, when the MenuItem was disabled the RichTextBox went back to it's old Ctrl+V behaviour and the user is able to paste whatever they want into the control.
Is it possible to make the RichTextBox only accept text when the user wants to paste?. I was thinking that perhaps I could make a new class that inherits from the RichTextBox and overides the Paste routine, however, I am not quite sure how to do this(if it is even possible).
I would be grateful if someone could help me with this problem.

[red]2.[/red] Is it possible to create a class that overrides a method from another class, but is still able to call the original method from within the new method?

[red]3.[/red] While trying to perform some file I/O with the above RichTextBox I encountered several problems.
First I decided to use the RichTextBox.SaveFile() method however I stopped that because I could not change the text encoding and it did not throw any exceptions so I could not tell the user whether the disk wall full or if another process was using the file.
I then decided that I would use the StreamWriter class due to the fact that I can easily pick any encoding and because it throws exceptions when a problem is encountered.
However the StreamWriter in my program does not seem to 'give up' the file that it uses and if I try to access the same file twice with a StreamWriter I get an error stating that the file is already being used by another process even though I had already finished with it. I have a feeling that the problem lies in the way that I have structured my code.
Do I actually need to call the StreamWriter.Close() method when I am finished with the stream becuase when it says that the file is already in use and I try to close the stream in the finally{} section it throws another exception stating that the disk is full. No matter what I do I cannot make the StreamWriter 'give up' the file so that I can use it again. Here is the source code that I am currently using.

[CODE]
private void SaveAs(object sender, EventArgs e)
{
SaveFileDialog dlgSaveAs = new SaveFileDialog();
dlgSaveAs.Filter = "Text File (*.txt)|*.txt";

if(dlgSaveAs.ShowDialog() == DialogResult.OK)
{
StreamWriter stream = null;

try
{
stream = new StreamWriter(dlgSaveAs.FileName,
false, Encoding.UTF8);
stream.Write(this.Controls[0].Text);
}
catch(IOException ioe)
{
MessageBox.Show(ioe.Message, "RaiEdit");
}
finally
{
//does this try block need to be here?
try
{
if(stream != null)
{
stream.Close();
}
}
catch(IOException)
{
}
}
}

return;
}
[/CODE]

Should I not be using a StreamWriter or am I just using it incorrectly. Can somebody help me with this problem?

[red]4.[/red] After programming with the Win32 API and using Notepad on winXP I have a desire to add a combobox to a SaveFileDialog so that the user can choose the encoding of the text that is saved. I am not sure how I would go about doing this, I was thinking that perhaps I could create a new class that inherits from the SaveFileDialog and in the constructor it create an extra combobox and makes the form large. Is it possible to do this or is there a better solution (hopefuly I won't have to delve back into the Win32 API like with the 'FindText' dialog). I hope that someone can help me with this problem.

[red]5.[/red] Is it possible to place a menu within a resource file and load it into the program. I am sick of writing 'new MenuItem(...)' 30-40 times when I create my programs MainMenu.

[red]6.[/red] Can someone tell me what [STAThread] means and why I have to put it in front of my Main() method? When I was debugging my application it kept coming up with errors whenever I tried to copy or paste inside a RichTextBox. It told me to put [STAThread] in front of my Main() method and when I did it solved the problem.

[red]7.[/red] Although this question is not directly related to C# it is still a programming question. What is the standard mehod for assigning version numbers to programs with windows programs seem to have four version numbers: minor, major, build number etc. Are there any standard methods for assigning these values or am I free to put whatever I want in there such as 'monkeygenerator v1000.69.3.1412'.

I hope that at least one of these questions will be answered and I apologise for the excessive length of each question.

rai_net




Comments

  • pingpongpingpong Posts: 937Member
    [b][red]This message was edited by pingpong at 2003-10-3 10:16:3[/red][/b][hr]
    : [red]1.[/red] I am using a RichTextBox in an application so that I can change the colour of text and use several other features, however, I do not want the user to be able to paste anything other than text into the control. I wrote some code so that when the user clicked on the 'Edit' menu that contained the Paste MenuItem it would check to see if the clipboard only contained text or not and disable the Paste MenuItem if it didn't. The MenuItem had the Shortcut.CtrlV shortcut associated with it however, when the MenuItem was disabled the RichTextBox went back to it's old Ctrl+V behaviour and the user is able to paste whatever they want into the control.
    : Is it possible to make the RichTextBox only accept text when the user wants to paste?. I was thinking that perhaps I could make a new class that inherits from the RichTextBox and overides the Paste routine, however, I am not quite sure how to do this(if it is even possible).
    : I would be grateful if someone could help me with this problem.
    :

    Subclass the rich edit control. In its wndproc, listen to ctrl-v (and shift-insert), then either pass them to the base or ignore them:
    [code]
    class MyRichTextBox : RichTextBox
    {
    [red]
    // edit. Forgot about this GetKeyState

    [DllImport("User32")]
    private static extern short GetKeyState(int vk);

    // GetKeyState to check if CTRL or SHIFT is down at any time.
    // you can probably get away with using this API and instead
    // define 2 booleans in your class, bool shiftIsDown and
    // bool controlIsDown. Set em up as false by default.
    // Then in WndProc, also check for WM_KEYDOWN/WM_KEYUP for VK_SHIT
    // and VK_CONTROL, set the booleans accordingly, then when a
    // WM_KEYDOWN/VK_Z comes along, you only to check it like this:
    // if(m.WParam.ToInt32() == VK_Z && controlIsDown) { ... }
    [/red]

    protected override void WndProc(ref Message m)
    {
    const int WM_KEYDOWN = 0x0100;
    const int VK_SHIFT = 0x10;
    const int VK_CONTROL = 0x11;
    const int VK_V = 0x56;
    const int VK_INSERT = 0x2D;

    if(m.Msg == WM_KEYDOWN)
    {
    // need to check CTRL-V and SHIFT-INSERT
    if((m.WParam.ToInt32() == VK_V && (GetKeyState(VK_CONTROL) & 0x8000) == 0x8000) ||
    (m.WParam.ToInt32() == VK_INSERT && (GetKeyState(VK_SHIFT) & 0x8000) == 0x8000))
    {
    // paste!
    if(IsClipboardFormatNotText())
    return; // dont call the base, copy operation is ignored.
    }

    base.WndProc(ref m);
    }

    [/code]
    You need to write that IsClipboardFormatNotText method yourself. Should be easy.

    : [red]2.[/red] Is it possible to create a class that overrides a method from another class, but is still able to call the original method from within the new method?

    Dont follow you, you mean the class is derived from the class with the method? then yes, use the "base" keyword:
    [code]
    class Base
    {
    public virtual void SomeFunc() {};
    }

    class Derived : Base
    {
    public override void SomeFunc()
    {
    // do work...
    // call base
    base.SomeFunc();
    // do more work...
    }
    }
    [/code]
    And it doesnt have to be virtual (if you dont want it to). In this case, replace override in Derived with "new".

    :
    : [red]3.[/red] While trying to perform some file I/O with the above RichTextBox I encountered several problems.
    : First I decided to use the RichTextBox.SaveFile() method however I stopped that because I could not change the text encoding and it did not throw any exceptions so I could not tell the user whether the disk wall full or if another process was using the file.
    : I then decided that I would use the StreamWriter class due to the fact that I can easily pick any encoding and because it throws exceptions when a problem is encountered.
    : However the StreamWriter in my program does not seem to 'give up' the file that it uses and if I try to access the same file twice with a StreamWriter I get an error stating that the file is already being used by another process even though I had already finished with it. I have a feeling that the problem lies in the way that I have structured my code.
    : Do I actually need to call the StreamWriter.Close() method when I am finished with the stream becuase when it says that the file is already in use and I try to close the stream in the finally{} section it throws another exception stating that the disk is full. No matter what I do I cannot make the StreamWriter 'give up' the file so that I can use it again. Here is the source code that I am currently using.
    :
    : [CODE]
    : private void SaveAs(object sender, EventArgs e)
    : {
    : SaveFileDialog dlgSaveAs = new SaveFileDialog();
    : dlgSaveAs.Filter = "Text File (*.txt)|*.txt";
    :
    : if(dlgSaveAs.ShowDialog() == DialogResult.OK)
    : {
    : StreamWriter stream = null;
    :
    : try
    : {
    : stream = new StreamWriter(dlgSaveAs.FileName,
    : false, Encoding.UTF8);
    : stream.Write(this.Controls[0].Text);
    : }
    : catch(IOException ioe)
    : {
    : MessageBox.Show(ioe.Message, "RaiEdit");
    : }
    : finally
    : {
    : //does this try block need to be here?
    : try
    : {
    : if(stream != null)
    : {
    : stream.Close();
    : }
    : }
    : catch(IOException)
    : {
    : }
    : }
    : }
    :
    : return;
    : }
    : [/CODE]
    :
    : Should I not be using a StreamWriter or am I just using it incorrectly. Can somebody help me with this problem?

    Your code looks right. You are closing the stream when you are done. If you dont, it causes that "used by another process" exception.

    Try adding a stream.Flush() after your last write. Dont know what happens if the buffer gets fulled.

    And your code would look more compact if you use "using" instead of that double try/catch you have:
    [code]
    try
    {
    using(stream = new StreamWriter(dlgSaveAs.FileName, false, Encoding.UTF8))
    {
    stream.Write(this.myRichTextBox1.Text);
    stream.Flush();
    }
    }
    catch(IOException ioe)
    {
    MessageBox.Show(ioe.Message, "RaiEdit");
    }
    [/code]

    :
    : [red]4.[/red] After programming with the Win32 API and using Notepad on winXP I have a desire to add a combobox to a SaveFileDialog so that the user can choose the encoding of the text that is saved. I am not sure how I would go about doing this, I was thinking that perhaps I could create a new class that inherits from the SaveFileDialog and in the constructor it create an extra combobox and makes the form large. Is it possible to do this or is there a better solution (hopefuly I won't have to delve back into the Win32 API like with the 'FindText' dialog). I hope that someone can help me with this problem.

    No you cannot inherit from SaveFileDialog, its defiend as sealed.

    In Win32, the OPENFILENAME structure supports a hook procedure. That's what people use to add their own controls, change the behavor, intercept stuff, etc for a file open/save common dialog.

    The .NET version has a HookProc that is supposed to do that, great yes? No! They defined it as protected!! With the class is sealed, there's no way to access it.

    So, either create your own Save file dialog from scratch in .NET, or wrap the Win32 OPENFILENAME/GetSaveFileName in a .NET class. Just dont make it sealed :).

    :
    : [red]5.[/red] Is it possible to place a menu within a resource file and load it into the program. I am sick of writing 'new MenuItem(...)' 30-40 times when I create my programs MainMenu.

    I have no idea. I use VS.NET to create my menus.

    :
    : [red]6.[/red] Can someone tell me what [STAThread] means and why I have to put it in front of my Main() method? When I was debugging my application it kept coming up with errors whenever I tried to copy or paste inside a RichTextBox. It told me to put [STAThread] in front of my Main() method and when I did it solved the problem.

    You need to either set put STAThread or MTAThread before your main. Basically this means that your application is gonna use either single or multi threaded apartment. If you are not going to use COM controls in your app then you can safely ignore this. Just pick one (STAThread is the default and somehow makes your code run faster since nothing will be thread safe by default).

    If you are using COM, then depends on the threading apartment the component is using. Set your main accordingly.

    :
    : [red]7.[/red] Although this question is not directly related to C# it is still a programming question. What is the standard mehod for assigning version numbers to programs with windows programs seem to have four version numbers: minor, major, build number etc. Are there any standard methods for assigning these values or am I free to put whatever I want in there such as 'monkeygenerator v1000.69.3.1412'.

    Might as well use the .NET standard. Check out the AssemblyVersion attribute in MSDN.



  • rai_netrai_net Posts: 51Member
    greetings and salutations,

    thanks so much for the help, I didn't think that I would have all of those questions answered so quickly, thanks:)

    By the way the code that you wrote for StreamWriter, I have never seen code written like this, how does it work and does it do the same thing as my previous code?

    : [code]
    : try
    : {
    : using(stream = new StreamWriter(dlgSaveAs.FileName, false, Encoding.UTF8))
    : {
    : stream.Write(this.myRichTextBox1.Text);
    : stream.Flush();
    : }
    : }
    : catch(IOException ioe)
    : {
    : MessageBox.Show(ioe.Message, "RaiEdit");
    : }
    : [/code]

    Also with the StreamWriter question, my code works perfectly, however the problem I was having only arises when the disk that is being written to is full. An exception is thrown saying that the disk is full, when the finally block is reached the 'StreamWriter.Close()' attempts to flush the contents of the stream before closing the stream. This throws another 'disk is full' exception and does not close the stream. Then when I try to access the same file later I get the exception stating that the file is in use by another process. Is there a way to 'clear' the stream so that it has nothing to flush when I close it, or is there some other solution?

    By the way thanks so much for the help, I really appreciate it.

    rai_net
  • pingpongpingpong Posts: 937Member
    : By the way the code that you wrote for StreamWriter, I have never seen code written like this, how does it work and does it do the same thing as my previous code?

    Yes it is. "using" works with classes that implement IDisposable. So your Dispose or Close are called automatically. Look it up in MSDN.

    As for the disk full error. I dont know. To be honest with you, I dont think Dispose or Finalize should throw an exception. Maybe you stumbled upon a bug here in the .NET framework.

    Have you tried the "using" block instead? What happens with this one?

  • rai_netrai_net Posts: 51Member
    : : By the way the code that you wrote for StreamWriter, I have never seen code written like this, how does it work and does it do the same thing as my previous code?
    :
    : Yes it is. "using" works with classes that implement IDisposable. So your Dispose or Close are called automatically. Look it up in MSDN.
    :
    : As for the disk full error. I dont know. To be honest with you, I dont think Dispose or Finalize should throw an exception. Maybe you stumbled upon a bug here in the .NET framework.
    :
    : Have you tried the "using" block instead? What happens with this one?
    :
    :

    I tried the 'using' block block and sadly it does the exact same thing. Either there is a bug in the .NET framework or I am using it incorrectly.

    Thanks for your help.

    rai_net
Sign In or Register to comment.