|
Hey Jim,
I've been thinking about an idea that may help to speed up search and replace a bit. Change out the line by line scrolling for something that would have the window scroll only when needed, like when the selection gets near the bottom of the searchableRichTextBox, or something like that. That also might help alleviate any flicker issues while replacing entries.
I'm just wondering how one would implement that idea, would you try to detect when the selected text is at the lowest line or what? Also, when the window scrolls to keep the selected area from leaving the window, when it's at the bottom line or whatever, it should scroll the text so that that line is now at the top, otherwise it'd just end up scrolling line by line at the bottom of the window, instead of elsewhere, and that's just as bad as the normal line by line scroll.
I'm going to try turning off the line by line scroll, and see what happens. If it flips out on me, I'll turn it back on.
Anyway, just my thoughts, happy coding
Brian
PS, no more bugs found so far, good job
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
Hey jim,
Well, I tried it without ScrollToCaret() and it runs without errors, but after a bit of scrolling it stops, and sits there. It makes you think it's frozen, but it does complete the entire operation.
Is there a possible replacement for ScrollToCaret()? Like maybe ScrollWhenNeeded()?
After I turned off ScrollToCaret() the replace speed went up dramatically, but at the cost of appearing to be unstable... So, I'm not too sure how to go about making it both faster, and still responsive. I guess multi-threading is an option, but I don't want to get that complicated for a search function. Also, that wouldn't solve the window scrolling part.
Well, I guess for now, I'll turn ScrollToCaret() back on and take the slowdown. But I'm going to try to see if there's a way to scroll the window on an "as needed" basis.
Any ideas you can come up with for anything and want tried out, I'm more than game to give a run
Talk to you later,
Brian
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
Hello everyone,
How would I extend this to search all items and subitems within a details list view?
|
|
|
|
|
The version 1.2 (not yet on CodeProject but should hopefully arrive soon, otherwise email me and I will send it to you) searches the Text of all the sub items- that will probably do what you want, if I understand you correctly. Otherwise you can supply your own search delegate to the SearchableListView and hand-code the match you desire.
|
|
|
|
|
Been looking for ages for such a thing.. you're a god. Thank you so much.
|
|
|
|
|
As the title says,
This is just what I've been trying to get together for a little app that I've been writing. Your find DLL is perfect for that job. Now I just need a Replace version to go along with it that will "plug-in" to the Searchable* items. It took me all of a few minutes to get my code converted to use the new version of the RichTextBox, once that was done, voila, search functionality.
If you'd be willing to do that, you'd make a lot of coder's days, not to mention mine
Thank you for writing such a nice and compact utility!
ArchKaine
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
Many thanks for your kind comments.
A replace function is in the new version 1.2 which should hopefully appear here soon.
|
|
|
|
|
I can't possibly put into words what a lifesaver you are! Thank you so much for implementing replace!
Question though: In my app, I'm using your DLL (didn't want to even touch the code, as it's too nice to break with my clumsy "coding" style). If so, will I have to rebind everything like the context menu and so on?
I'm guessing yes, but I'm not too sure, I'll play around with it and see what explodes
Thank you again for such incredible code.
ArchKaine
Edit:
I played around for about 2 seconds, after dropping the DLL into my project folder and recompiling. Nothing exploded, and it works beautifully, thank you again for an outstanding piece of code
/Edit
-- modified at 20:35 Wednesday 23rd August, 2006
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
Many thanks for your kind words.
Regarding the context menu question, I'm not 100% sure I understand. You can use the DLL and the enhanced context menu will work when the control is active, no other work should be needed. If you encounter any specific problems, put the case here in as much details as possible and I'll advise.
If you want to add your own context menu items, this is a touch trickier, as it always is when inheriting from .NET controls.
Here is how to do it. Make a ContextMenuStrip in the designer, I assume it is called contextMenuStrip1. Instead of binding it to the ContextMenuStrip property on the control, add the following code to your control's constructor after the InitializeComponent(); instruction...
MergeContextMenus(ContextMenuStrip, contextMenuStrip1);
Then paste this function into your control somewhere.
private static void MergeContextMenus(ContextMenuStrip target, ContextMenuStrip source)
{
List<ToolStripItem> list = new List<ToolStripItem>();
foreach (ToolStripItem item in source.Items)
{
list.Add(item);
}
foreach (ToolStripItem item in list)
{
target.Items.Add(item);
}
}
I might add this facility into any future version of this control library.
Hope that helps.
Jim
|
|
|
|
|
Hi Jim,
I'll give your code a shot and see what heppens. I was considering adding my context menu to yours but was at a loss as to how to figure it out. Thanks for clearing that up.
On an issue that I've just discovered. When I use the find+replace functionality in a searchableRichTextBox with some patterns, I get an "Index Out Of Bounds" error, even though it's a fairly straightforward search. Try the following in normal search mode (without wildcards or regexp):
<br />
Text in box:<br />
goodbye goodbye goodbye goodbye goodbye goodbye goodbye goodbye goodbye goodbye goodbye goodbye goodbye goodbye goodbye goodbye<br />
<br />
Now try searching for goodbye and replacing it with hello or something like that<br />
This may very easily be a bug in my code, and not yours, I honestly at this point don't know, so bear with me
I notice that this usually happens when there's a newline and the text being searched for is identical, I haven't yet tried this with "normal" text sections yet, except in wildcard mode, which seems to work just fine, even with regex's, and regex mode doesn't seem to like any regex that I try to use. I may just not be entering the regex's properly, I'll read up on it more and try some tutorial type stuff in it to see if that helps.
Anyway, if you're curious, I could send you my source code, it's not proprietary or anything, just don't laugh too hard when you read it. I'm still learning this stuff.
Ok, edit here. Here's an error message I just got, pardon the length of it, I chose not to leave anything out:
************** Exception Text **************
System.ArgumentOutOfRangeException: Start index cannot be less than 0 or greater than input length.
Parameter name: start
at System.Text.RegularExpressions.Regex.Run(Boolean quick, Int32 prevlen, String input, Int32 beginning, Int32 length, Int32 startat)
at System.Text.RegularExpressions.Regex.Match(String input, Int32 beginning, Int32 length)
at SearchableControls.SearchableRichTextBox.SubSearch(Regex regularExpression, Int32 start, Int32 end)
at SearchableControls.SearchableRichTextBox.findDialog1_SearchRequested(Object sender, SearchEventArgs e)
at SearchableControls.FindDialog.Search()
at SearchableControls.FindForm.SearchPressed()
at SearchableControls.FindForm.searchButton_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
************** Loaded Assemblies **************
mscorlib
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.88 (rtmLHS.050727-8800)
CodeBase: file:----------------------------------------
FLNotepad
Assembly Version: 0.1.1.9595
Win32 Version: 1.0.0.0
CodeBase: file:----------------------------------------
System.Windows.Forms
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.88 (rtmLHS.050727-8800)
CodeBase: file:----------------------------------------
System
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.88 (rtmLHS.050727-8800)
CodeBase: file:----------------------------------------
System.Drawing
Assembly Version: 2.0.0.0
Win32 Version: 2.0.50727.88 (rtmLHS.050727-8800)
CodeBase: file:----------------------------------------
SearchableControls
Assembly Version: 1.2.0.0
Win32 Version: 1.2.0.0
CodeBase: file:----------------------------------------
Anyway, thanks again for everything
ArchKaine
-- modified at 7:28 Thursday 24th August, 2006
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
You found a bug, whoops.
The bug is when text was replaced with shorter text the mechanism used to record the original start point of the search fails because the text shortening was changing the true index of the start position.
I've very quickly knocked up a version 1.2.1 with an attempted fix,
www.jimblackler.com/SearchableControls.dll
Could you let me know if this fixes it for you?
Jim
|
|
|
|
|
Hey Jim,
You are a quick one, thank you.
I'll see if I can manage to break this one too and let you know what happens.
Brian / ArchKaine
EDIT:
Here's another, after performing the same test. I'm wondering if it's in my code somewhere, but I don't know. Here's the Error:
System.IndexOutOfRangeException was unhandled
Message="Index was outside the bounds of the array."
Source="System"
StackTrace:
at System.Text.RegularExpressions.RegexBoyerMoore.Scan(String text, Int32 index, Int32 beglimit, Int32 endlimit)
at System.Text.RegularExpressions.RegexInterpreter.FindFirstChar()
at System.Text.RegularExpressions.RegexRunner.Scan(Regex regex, String text, Int32 textbeg, Int32 textend, Int32 textstart, Int32 prevlen, Boolean quick)
at System.Text.RegularExpressions.Regex.Run(Boolean quick, Int32 prevlen, String input, Int32 beginning, Int32 length, Int32 startat)
at System.Text.RegularExpressions.Regex.Match(String input, Int32 beginning, Int32 length)
at SearchableControls.SearchableRichTextBox.SubSearch(Regex regularExpression, Int32 start, Int32 end)
at SearchableControls.SearchableRichTextBox.findDialog1_SearchRequested(Object sender, SearchEventArgs e)
at SearchableControls.FindDialog.Search()
at SearchableControls.FindForm.replaceAllButton_Click(Object sender, EventArgs e)
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at TextEditor.formEditor.Main(String[] args) in F:\My Downloads\FLNotepad\FormEditor.cs:line 377
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
I'm going to try rebuilding the code again, just to make sure that it's using the new DLL.
-- modified at 8:45 Thursday 24th August, 2006
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
Hey again Jim,
I went ahead and rebuilt the code, tried the new DLL with the same test, and it passed, I'll try some other things and let you know the results, looks good so far though.
EDIT:
Ok, here's a new one, done with the normal text replace option:
Fill your document with multiple copies of "hello my friend ", then do a search for that, and replace it with "goodbye old foe ", and it'll replace all but the first instance of "hello my friend ". Do you suppose this is a case for regex? I haven't tried it under that yet, but I think that normal text search should be able to handle this case.
Sorry if I seem to be poking your work to death, I'm writing this tool of mine for a very demanding audience, and need all parts of it to work as well as possible. Not that I'm any good at coding, but I try
I'm wondering how I can embed a regex tutorial into the About Box, might be needed for the people who will be using this tool of mine (it's for a project that will be aimed at modding a game called Freelancer, and currently edits the save game files and once this is finished, with the power of regex, will allow for faster editing of Freelancer INI files).
/EDIT
Thanks for your patience
Brian
-- modified at 8:54 Thursday 24th August, 2006
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
Hey jim,
Here's a quick test for you to try.
Regex = \b\w*q(?!u)\w*\b (finds a word containing the letter "q" which is not followed immediately by a "u")
Search Text = quick queen zit hack time stiq
Mode = wildcard (works, hits on "stiq", incorrect response)
Mode = Normal (fails, finds nothing, expected response)
Mode = Regex (fails, finds nothing, incorrect response)
I have the feeling that somehow wilcard and Regex modes got switched, mind if I jump into the code and see if I can get them back how they're supposed to be? I'll send you my results if I can get them working properly.
Thanks again,
Brian
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
Be my guest. I wouldn't put the source up if I was worried about people prodding around in it. Mind you it is possible to get a heck of a lot out of a .net .dll with the reflector anyway.
I haven't really tested the Regular Expression feature all that hard myself. I only really added it because I was using RegExes behind the scenes anyway to simplify wildcards and case sensitivity.
I happen to know of a few bugs in the .net regex implementation. I've wrapped exceptions but that doens't catch everything. It is possible to hang the library by typing garbage in.
The best thing might be to take the RegEx option off the search dialog for the time being.
Jim
|
|
|
|
|
Hmm, yeah, you're probably right about leaving it out, but I think I'm going to play around with it a bit more and see if I can work around some of the problems. I'd really like to be able to give people who use my editor the ability to take advantage of the much greater flexibility of RegEx if at all possible.
Do you have an idea of *how* broken the .NET RegEx implementation is? If it makes any difference, I'm doing all this on Vista Beta 2, not that that will make a difference to the end-user.
The RegEx implementation has a huge potential, I'd hate to see it disabled. I'll keep you in the loop regarding what I manage to pull off or not. You're welcome to drop me a note if you like as well. (My nickname at Gmail)
Well, thanks again for the quick reply, and have fun programming. You've earned my 5
Brian / ArchKaine
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
Well, after making that small code correction I mentioned earlier about the Regex and the Wildcard entries in the Find Dialog being reversed, things are looking really good. I've been comparing the results gotten by your code with those gotten by Expresso, and so far they agree completely, and no more bugs so far either, so other than that reversed entries typo, at this point I'm thinking that things are looking up.
Here's the corrected code from Findform.cs:
switch ((SearchType)searchTypeComboBox.SelectedIndex)
{
case SearchType.Wildcards:
text = Regex.Escape(searchHistoryComboBox.Text).Replace(@"\*", ".*").Replace(@"\?", ".");
break;
case SearchType.RegularExpression:
text = searchHistoryComboBox.Text;
break;
case SearchType.PlainTextSearch:
default:
text = Regex.Escape(searchHistoryComboBox.Text);
break;
}
I hope this helps.
Brian / ArchKaine
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
Hi Brian
You're right... I can't really explain how I made that mistake. Bizarre.
I've incorporated your fix, a new version (1.2.3) is on my webspace here..
www.jimblackler.com/SearchableControls.dll
Thanks for helping me iron out the bugs. Keep the info coming if you find some more.
Jim
|
|
|
|
|
You got it I'm glad to help.
Incidentally, I'm having trouble getting my menus to be able to run the finder. Maybe I'm just not seeing what I need to see, but I can't get my menus to start up the find dialog. any suggestions?
I'll inclue a code snippet below to show you what I am doing, please let me know what I've done wrong here.
private void menuItem7_Click(object sender, EventArgs e)
{
searchableRichTextBox1.FindForm();
}
private void menuItem9_Click(object sender, EventArgs e)
{
searchableRichTextBox1.FindForm();
}
I know it has to be something blatantly obvious, but I'm just not seeing it I think. Thanks in advance for help
Brian
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
Try this...
private void menuItem7_Click(object sender, EventArgs e)
{
searchableRichTextBox1.FindForm().ShowDialog();
}
private void menuItem9_Click(object sender, EventArgs e)
{
searchableRichTextBox1.FindForm().ShowDialog();
}
|
|
|
|
|
Ok, I figured it'd be something obvious, but not that obvious.
Thanks Jim,
Brian
EDIT:
I just tried it with ShowDialog() and Show(), still nothing. I don't get it. It even crashed when I tried to use ShowDialog(), I forget what the error was though.
/EDIT
-- modified at 18:42 Thursday 24th August, 2006
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
Turns out the error was due to me trying to open an already opened object, since the dialogs load invisibly during program startup.
I still can't get the menu items to work, so I put in some "It's broke" message boxes for now, to remind me to fix them later.
Hmm, on to other things for now, maybe it's time to add images to all my buttons and working menu items.
Brian
Some say that ignorance is bliss... Blissful, aren't they?
|
|
|
|
|
Good innovative stuff!
M.Sendilkumar
|
|
|
|
|
it would be nice if there were a couple more features, such as a couple ratio buttons to determine whether you want to search up or down (or a "Find Previous" button or whatever you think works).
Also a Replace dialog would naturally complement this well (although it should be enabled by specific logic... control.Enabled and possibly a developer-toggleable boolean property as well.
Of course I already went through the process of making a find/replace dialog for one of my apps, if I ever go back and redo it for .NET 2 (it's in .NET 1.1 and needs a serious UI makeover) I might use your SearchableControls as a base.
But for now I'm content with it, so I'll just leave suggestions instead of actually contributing any code. >_> hehe
|
|
|
|
|
I have added a replace function in the new version 1.2 which should hopefully be published here soon (Codeproject have the code and article).
Jim
|
|
|
|
|